All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 40s
commit 579f0878e5240dc17db69be1e0b0c0f5af7ef9fe
Author: Arno Kaimbacher <arno.kaimbacher@geosphere.at>
Date: Tue Jun 9 09:25:44 2026 +0200
feat: Refactor error handling in Dataset Edit form and improve validation messages
- Updated error handling in the Dataset Edit form to use a centralized formatError function for displaying validation messages.
- Enhanced user feedback by ensuring that error messages are displayed consistently across various fields.
- Modified the validation rule for arrayContainsTypes to provide clearer error messages for missing main and translated titles/abstracts.
- Introduced a new ValidationService to manage manual construction of validation errors.
- Updated Vite configuration to streamline asset loading and improve performance.
- Adjusted Inertia setup to utilize dynamic imports for page-specific assets.
- Cleaned up unnecessary comments and code in various files for better readability.
commit 5efddc2a58c0e164fef585cc7344c06155dbc2c1
Author: Arno Kaimbacher <arno.kaimbacher@geosphere.at>
Date: Mon Jan 12 17:02:47 2026 +0100
feat: add dataset change detection and form submission composables
- Implemented `useDatasetChangeDetection` for tracking unsaved changes in dataset forms, including comparisons for licenses, basic properties, files, coverage, and more.
- Added `useDatasetFormSubmission` for handling dataset form submissions with validation, success/error handling, and auto-save functionality.
202 lines
No EOL
9.4 KiB
Vue
202 lines
No EOL
9.4 KiB
Vue
<script lang="ts" setup>
|
|
import { usePage, router } from '@inertiajs/vue3';
|
|
// import { usePage } from '@inertiajs/inertia-vue3';
|
|
// import { Inertia } from '@inertiajs/inertia';
|
|
import type { ComputedRef } from 'vue';
|
|
|
|
import { computed, ref } from 'vue';
|
|
import { containerMaxW } from '@/config';
|
|
import { StyleService } from '@/Stores/style.service';
|
|
import { LayoutService } from '@/Stores/layout';
|
|
import {
|
|
mdiForwardburger,
|
|
mdiBackburger,
|
|
mdiClose,
|
|
mdiDotsVertical,
|
|
mdiMenu,
|
|
mdiCloudDownloadOutline,
|
|
mdiCloud,
|
|
mdiCrop,
|
|
mdiAccountCog,
|
|
mdiFormatListGroup,
|
|
mdiFormatListNumbered,
|
|
mdiLogout,
|
|
mdiThemeLightDark,
|
|
mdiViewDashboard,
|
|
mdiInformationVariant,
|
|
mdiGlasses,
|
|
mdiXml
|
|
} from '@mdi/js';
|
|
import NavBarItem from '@/Components/NavBarItem.vue';
|
|
import NavBarItemLabel from '@/Components/NavBarItemLabel.vue';
|
|
import NavBarMenu from '@/Components/NavBarMenu.vue';
|
|
import BaseDivider from '@/Components/BaseDivider.vue';
|
|
import UserAvatarCurrentUser from '@/Components/UserAvatarCurrentUser.vue';
|
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
|
// import NavBarSearch from '@/Components/NavBarSearch.vue';
|
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
|
import type { User } from '@/Dataset';
|
|
import FirstrunWizard from '@/Components/FirstrunWizard/FirstrunWizard.vue'
|
|
// import Lock from 'vue-material-design-icons/Lock.vue'
|
|
// import BriefcaseCheck from 'vue-material-design-icons/BriefcaseCheck.vue'
|
|
// import SwapHorizontal from 'vue-material-design-icons/SwapHorizontal.vue'
|
|
// import AccountGroup from 'vue-material-design-icons/AccountGroup.vue'
|
|
|
|
const styleService = StyleService();
|
|
const props = defineProps({
|
|
showBurger: {
|
|
type: Boolean,
|
|
default: true // Set default value to true
|
|
}
|
|
});
|
|
// const userName = computed(() => usePage().props.user.login)
|
|
|
|
const user: ComputedRef<User> = computed(() => {
|
|
return usePage().props.authUser as User;
|
|
});
|
|
// const userName = computed(() => props.user.login)
|
|
|
|
const toggleLightDark = () => {
|
|
styleService.setDarkMode();
|
|
};
|
|
|
|
const layoutStore = LayoutService();
|
|
|
|
const isMenuNavBarActive = ref(false);
|
|
|
|
const menuNavBarToggle = () => {
|
|
isMenuNavBarActive.value = !isMenuNavBarActive.value;
|
|
};
|
|
|
|
const menuOpenLg = () => {
|
|
layoutStore.isAsideLgActive = true;
|
|
};
|
|
const userHasRoles = (roleNames: Array<string>): boolean => {
|
|
return user.value.roles.some(role => roleNames.includes(role));
|
|
};
|
|
|
|
// const logout = () => {
|
|
// // router.post(route('logout'))
|
|
// Inertia.get(stardust.route('app.index'));
|
|
// };
|
|
const logout = async () => {
|
|
// router.post(route('logout'));
|
|
await router.post(stardust.route('logout'));
|
|
};
|
|
|
|
const about = ref();
|
|
const showAbout = async () => {
|
|
// router.post(route('logout'));
|
|
about.value.open();
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<nav class="text-base top-0 left-0 right-0 fixed bg-lime h-14 z-50 w-screen transition-position lg:w-auto dark:bg-slate-800"
|
|
:class="{ 'xl:pl-60': props.showBurger == true }">
|
|
<FirstrunWizard ref="about"></FirstrunWizard>
|
|
<div class="flex lg:items-stretch" :class="containerMaxW">
|
|
<div class="flex-1 items-stretch flex h-14">
|
|
<NavBarItem type="flex lg:hidden" @click.prevent="layoutStore.asideMobileToggle()"
|
|
v-if="props.showBurger">
|
|
<BaseIcon :path="layoutStore.isAsideMobileExpanded ? mdiBackburger : mdiForwardburger" size="24" />
|
|
</NavBarItem>
|
|
<NavBarItem type="hidden lg:flex xl:hidden" @click.prevent="menuOpenLg" v-if="props.showBurger">
|
|
<BaseIcon :path="mdiMenu" size="24" />
|
|
</NavBarItem>
|
|
<NavBarItem route-name="apps.dashboard">
|
|
<NavBarItemLabel :icon="mdiViewDashboard" label="Dashboard" size="22" is-hover-label-only
|
|
route-name="apps.dashboard" />
|
|
</NavBarItem>
|
|
<!-- <NavBarItem route-name="apps.map">
|
|
<NavBarItemLabel :icon="mdiMapSearch" label="Map" size="22" is-hover-label-only route-name="apps.map" />
|
|
</NavBarItem> -->
|
|
<!-- <NavBarItem>
|
|
<NavBarSearch />
|
|
</NavBarItem> -->
|
|
</div>
|
|
<div class="flex-none items-stretch flex h-14 lg:hidden">
|
|
<NavBarItem @click.prevent="menuNavBarToggle">
|
|
<BaseIcon :path="isMenuNavBarActive ? mdiClose : mdiDotsVertical" size="24" />
|
|
</NavBarItem>
|
|
</div>
|
|
<div class="fixed w-screen top-14 left-0 shadow lg:w-auto lg:items-stretch lg:flex lg:grow lg:static lg:border-b-0 lg:overflow-visible lg:shadow-none dark:bg-slate-800"
|
|
:class="[isMenuNavBarActive ? 'block' : 'hidden']">
|
|
<div
|
|
class="bg-white lg:bg-lime dark:bg-transparent max-h-screen-menu overflow-y-auto lg:overflow-visible lg:flex lg:items-stretch lg:justify-end lg:ml-auto">
|
|
|
|
<!-- help menu -->
|
|
<NavBarMenu>
|
|
<NavBarItemLabel :icon="mdiMenu" label="Help menu" />
|
|
<template #dropdown>
|
|
<!-- <NavBarItem>
|
|
<NavBarItemLabel :icon="mdiClockOutline" label="Item One" />
|
|
</NavBarItem> -->
|
|
<NavBarItem href="/docs/HandbuchTethys.pdf" target="_blank">
|
|
<NavBarItemLabel :icon="mdiCloudDownloadOutline" label="Tethys Manual" />
|
|
</NavBarItem>
|
|
<NavBarItem href="/docs/geopackage_v01.pdf" target="_blank">
|
|
<NavBarItemLabel :icon="mdiCloud" label="GeoPackage Help" />
|
|
</NavBarItem>
|
|
<BaseDivider nav-bar />
|
|
<NavBarItem href="/docs/PreservationPlanTethys.pdf" target="_blank">
|
|
<NavBarItemLabel :icon="mdiCrop" label="Preservation Plan" />
|
|
</NavBarItem>
|
|
</template>
|
|
</NavBarMenu>
|
|
|
|
<!-- personal menu -->
|
|
<NavBarMenu>
|
|
<NavBarItemLabel v-bind:label="`hello ${user.login}`">
|
|
<UserAvatarCurrentUser :user="user" class="w-6 h-6 mr-3 inline-flex" />
|
|
</NavBarItemLabel>
|
|
<template #dropdown>
|
|
<!-- <NavBarItem> -->
|
|
<!-- <NavBarItem route-name="admin.account.info"> -->
|
|
<NavBarItem :route-name="'settings.user'">
|
|
<NavBarItemLabel :icon="mdiAccountCog" label="User Settings" />
|
|
</NavBarItem>
|
|
<NavBarItem v-if="userHasRoles(['administrator'])" :route-name="'settings.overview'">
|
|
<NavBarItemLabel :icon="mdiFormatListGroup" label="Administration" />
|
|
</NavBarItem>
|
|
<NavBarItem v-if="userHasRoles(['submitter'])" :route-name="'dataset.list'">
|
|
<NavBarItemLabel :icon="mdiFormatListNumbered" label="Submitter Menu" />
|
|
</NavBarItem>
|
|
<NavBarItem v-if="userHasRoles(['editor'])" :route-name="'editor.dataset.list'">
|
|
<NavBarItemLabel :icon="mdiFormatListNumbered" label="Editor Menu" />
|
|
</NavBarItem>
|
|
<NavBarItem v-if="userHasRoles(['reviewer'])" :route-name="'reviewer.dataset.list'">
|
|
<NavBarItemLabel :icon="mdiGlasses" label="Reviewer Menu" />
|
|
</NavBarItem>
|
|
<!-- <NavBarItem @click="showAbout">
|
|
<NavBarItemLabel :icon="mdiInformationVariant" label="About" />
|
|
</NavBarItem> -->
|
|
<BaseDivider nav-bar />
|
|
<NavBarItem @click="logout">
|
|
<NavBarItemLabel :icon="mdiLogout" label="Log Out" />
|
|
</NavBarItem>
|
|
</template>
|
|
</NavBarMenu>
|
|
|
|
<NavBarItem is-desktop-icon-only @click.prevent="toggleLightDark">
|
|
<NavBarItemLabel v-bind:icon="mdiThemeLightDark" label="Light/Dark" is-desktop-icon-only />
|
|
</NavBarItem>
|
|
<!-- <NavBarItem href="" target="_blank" is-desktop-icon-only>
|
|
<NavBarItemLabel v-bind:icon="mdiGithub" label="GitHub" is-desktop-icon-only />
|
|
</NavBarItem> -->
|
|
<NavBarItem href="/oai" target="_blank" is-desktop-icon-only>
|
|
<NavBarItemLabel v-bind:icon="mdiXml" label="OAI Interface" is-desktop-icon-only />
|
|
</NavBarItem>
|
|
<!-- <NavBarItem is-desktop-icon-only @click="showAbout">
|
|
<NavBarItemLabel v-bind:icon="mdiInformationVariant" label="About" is-desktop-icon-only />
|
|
</NavBarItem> -->
|
|
<NavBarItem is-desktop-icon-only @click="logout">
|
|
<NavBarItemLabel v-bind:icon="mdiLogout" label="Log out" is-desktop-icon-only />
|
|
</NavBarItem>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
</template> |