From 94fcbd9e57cc68f42aea533afbcf5efdaec553dc Mon Sep 17 00:00:00 2001 From: nakrovati <59262179+nakrovati@users.noreply.github.com> Date: Sun, 25 Jan 2026 05:23:27 +0400 Subject: [PATCH] Fix PageHeader collision with Sidebar, update dependencies, and clean up code (#44) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: PageHeader overlaps Sidebar on small screens * refactor: move appName and appDescription to defineNuxtConfig * chore: replace clipboard with vueuse useClipboard * chore(deps): remove unused deps * chore: bump deps Add type conversion `... as Shape` to AutoForm and AutoFormFiledObject for compatibility with vue-tsc v3. Add `import ‘vue-sonner/style.css’` for compatibility with vue-sonner v2. Move @aws-sdk/types to dependencies. Format code. --- app.config.ts | 11 +- components/app-sidebar.vue | 15 +- components/copy-input.vue | 49 +- components/object/path-links.vue | 40 +- components/providers/AppUiProvider.vue | 1 + components/ui/auto-form/AutoForm.vue | 4 +- .../ui/auto-form/AutoFormFieldArray.vue | 2 +- .../ui/auto-form/AutoFormFieldObject.vue | 2 +- components/ui/sidebar/Sidebar.vue | 2 +- nuxt.config.ts | 5 +- package.json | 50 +- pnpm-lock.yaml | 2832 +++++++---------- types/app-config.d.ts | 7 - 13 files changed, 1190 insertions(+), 1830 deletions(-) diff --git a/app.config.ts b/app.config.ts index 5bb52ee..5d95658 100644 --- a/app.config.ts +++ b/app.config.ts @@ -1,8 +1,9 @@ import navs from '~/config/navs' -import type { AppConfig } from '~/types/app-config' -export default defineAppConfig({ - navs: navs, - name: process.env.APP_NAME || 'RustFS', - description: process.env.APP_DESCRIPTION || 'RustFS is a distributed file system written in Rust.', +export default defineAppConfig({ + navs, + icon: { + mode: 'css', + cssLayer: 'base', + }, }) diff --git a/components/app-sidebar.vue b/components/app-sidebar.vue index b8ab697..0e0d074 100644 --- a/components/app-sidebar.vue +++ b/components/app-sidebar.vue @@ -22,15 +22,16 @@ import { import { computed } from 'vue' import { useI18n } from 'vue-i18n' import { useRoute } from 'vue-router' -import type { AppConfig, NavItem } from '~/types/app-config' +import type { NavItem } from '~/types/app-config' -const appConfig = useAppConfig() as unknown as AppConfig +const appConfig = useAppConfig() +const config = useRuntimeConfig() const route = useRoute() const { t } = useI18n() const { state } = useSidebar() const { isAdmin, canAccessPath } = usePermissions() const isCollapsed = computed(() => state.value === 'collapsed') -const brandInitial = computed(() => appConfig.name?.charAt(0)?.toUpperCase() ?? 'R') +const brandInitial = computed(() => config.public.appName.charAt(0).toUpperCase() ?? 'R') const navGroups = computed(() => { const groups: NavItem[][] = [] @@ -42,11 +43,11 @@ const navGroups = computed(() => { if (nav.children?.length) { visibleChildren = nav.children.filter(child => { if (child.to && !canAccessPath(child.to)) return false - + // If child is admin only and user is not admin, but has permission (checked above), allow it. // If child has no path (unlikely for leaf) and is admin only, hide it. if (child.isAdminOnly && !isAdmin.value && !child.to) return false - + return true }) @@ -59,10 +60,10 @@ const navGroups = computed(() => { if (nav.to && !canAccessPath(nav.to)) { continue } - + // If no path and no children (e.g. divider), check isAdminOnly if (!nav.to && nav.isAdminOnly && !isAdmin.value) { - continue + continue } } diff --git a/components/copy-input.vue b/components/copy-input.vue index f9a5d71..8421a22 100644 --- a/components/copy-input.vue +++ b/components/copy-input.vue @@ -4,8 +4,6 @@ import { Input } from '@/components/ui/input' import { Icon } from '#components' import { useMessage } from '@/lib/ui/message' -import ClipboardJS from 'clipboard' -import { onMounted, onUnmounted, ref } from 'vue' import { useI18n } from 'vue-i18n' const { t } = useI18n() @@ -31,50 +29,41 @@ const props = defineProps({ const model = defineModel() const message = useMessage() -const clipboard = ref(null) -onMounted(() => { - clipboard.value = new ClipboardJS(props.copyIcon ? `#${props.id}-btn-icon` : `#${props.id}-btn`) +const { copy } = useClipboard() + +async function handleCopyGeneratedUrl() { + try { + if (!model.value) throw new Error('No value to copy') + + await copy(model.value) - clipboard.value.on('success', function (e) { message.success(t('Copy Success')) - e.clearSelection() - }) - - clipboard.value.on('error', async function () { - // If copy fails, use navigator.clipboard.writeText as fallback - try { - if (navigator.clipboard && model.value) { - await navigator.clipboard.writeText(model.value) - message.success(t('Copy Success')) - } else { - message.error(t('Copy Failed')) - } - } catch { - message.error(t('Copy Failed')) - } - }) -}) - -onUnmounted(() => { - clipboard.value?.destroy() - clipboard.value = null -}) + } catch (error) { + message.error(t('Copy Failed')) + } +}