From a2c6d496b08dff44f765a34e83030171c092c9ef Mon Sep 17 00:00:00 2001 From: Norman Niati Date: Tue, 9 Jun 2026 19:25:32 +0200 Subject: [PATCH] feat: unified cog action menu across 6 system/project/api views --- ui/src/components/RowActionsCog.vue | 36 ++++++++++++++++++++++++ ui/src/views/ApiTokenView.vue | 21 +++++--------- ui/src/views/ProjectListView.vue | 19 ++++--------- ui/src/views/SystemConfigurationView.vue | 16 ++++------- ui/src/views/SystemNodeView.vue | 16 ++++------- ui/src/views/SystemRoleView.vue | 16 ++++------- ui/src/views/SystemUserView.vue | 16 ++++------- 7 files changed, 73 insertions(+), 67 deletions(-) create mode 100644 ui/src/components/RowActionsCog.vue diff --git a/ui/src/components/RowActionsCog.vue b/ui/src/components/RowActionsCog.vue new file mode 100644 index 0000000..40a0db2 --- /dev/null +++ b/ui/src/components/RowActionsCog.vue @@ -0,0 +1,36 @@ + + + + diff --git a/ui/src/views/ApiTokenView.vue b/ui/src/views/ApiTokenView.vue index 5c5208a..e2bf0db 100644 --- a/ui/src/views/ApiTokenView.vue +++ b/ui/src/views/ApiTokenView.vue @@ -39,18 +39,12 @@ @@ -97,6 +91,7 @@ import { ref, computed, onMounted } from 'vue' import { useApi, useAppStore, useAuthStore, useI18nStore, useClipboard, APP_BASE } from '@ligoj/host' import { VibrantDataTable, VibrantConfirmDialog as LigojConfirmDialog, LjPageHeader, LjButton, LjSearch, LjDialog } from '@ligoj/host' +import RowActionsCog from '../components/RowActionsCog.vue' const api = useApi() const app = useAppStore() @@ -222,8 +217,6 @@ onMounted(() => { .avatar-cell { display: flex; align-items: center; gap: 12px; } .kglyph { width: 34px; height: 34px; border-radius: var(--radius-sm); flex: none; display: grid; place-items: center; background: rgba(139, 92, 246, .13); color: #8b5cf6; } .kname { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--ink); } -/* Danger accent for the inline revoke trigger (base `.lj-iconbtn` is global). */ -.lj-iconbtn.danger:hover { background: rgba(var(--v-theme-error), .1); color: rgb(var(--v-theme-error)); } /* Dialog body bits (slotted into LjDialog; --pill/--mono/--accent come from the dialog card's `.lj-surface`). */ diff --git a/ui/src/views/ProjectListView.vue b/ui/src/views/ProjectListView.vue index 615e410..a006524 100644 --- a/ui/src/views/ProjectListView.vue +++ b/ui/src/views/ProjectListView.vue @@ -44,14 +44,11 @@ {{ item.subs }} @@ -71,6 +68,7 @@ import { ref, computed, onMounted } from 'vue' import { useRouter } from 'vue-router' import { useApi, useAppStore, useI18nStore } from '@ligoj/host' import ProjectEditDialog from './ProjectEditDialog.vue' +import RowActionsCog from '../components/RowActionsCog.vue' import { VibrantDataTable, VibrantConfirmDialog, LjPageHeader, LjButton, LjSearch } from '@ligoj/host' const router = useRouter() @@ -284,11 +282,6 @@ onMounted(() => { color: var(--ink-2); } -/* Danger accent for the inline delete trigger (base `.lj-iconbtn` is global). */ -.lj-iconbtn.danger:hover { - color: rgb(var(--v-theme-error)); -} - .toast { position: fixed; bottom: 24px; diff --git a/ui/src/views/SystemConfigurationView.vue b/ui/src/views/SystemConfigurationView.vue index 1d6f9d7..0077a61 100644 --- a/ui/src/views/SystemConfigurationView.vue +++ b/ui/src/views/SystemConfigurationView.vue @@ -70,14 +70,11 @@ mdi-alert @@ -106,6 +103,7 @@ import { ref, computed, onMounted } from 'vue' import { useApi, useAppStore, useI18nStore, useClipboard, APP_BASE } from '@ligoj/host' import { VibrantDataTable, VibrantConfirmDialog as LigojConfirmDialog, LjPageHeader, LjButton, LjSearch, LjDialog, LjAvailabilityField } from '@ligoj/host' +import RowActionsCog from '../components/RowActionsCog.vue' const api = useApi() const app = useAppStore() @@ -342,8 +340,6 @@ onMounted(() => { .srcpill :deep(.v-icon) { flex: none; } .src-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .ovr { color: #d9701a; margin-left: 5px; vertical-align: middle; } -/* Danger accent for the inline delete trigger (base `.lj-iconbtn` is global). */ -.lj-iconbtn.danger:hover { background: rgba(var(--v-theme-error), .1); color: rgb(var(--v-theme-error)); } /* Custom checkboxes inside the edit dialog (slotted content keeps this component's scope id; --accent/--border-2 come from the LjDialog card's diff --git a/ui/src/views/SystemNodeView.vue b/ui/src/views/SystemNodeView.vue index b68361e..fff4096 100644 --- a/ui/src/views/SystemNodeView.vue +++ b/ui/src/views/SystemNodeView.vue @@ -64,16 +64,11 @@ @@ -91,6 +86,7 @@ import { ref, computed, onMounted, onBeforeUnmount } from 'vue' import { useApi, useAppStore, useI18nStore, NodeIcon, NodeModeChip, isInstance, nodeType } from '@ligoj/host' import { VibrantDataTable, VibrantConfirmDialog as LigojConfirmDialog, LjPageHeader, LjButton } from '@ligoj/host' import NodeEditDialog from './NodeEditDialog.vue' +import RowActionsCog from '../components/RowActionsCog.vue' const api = useApi() const app = useAppStore() diff --git a/ui/src/views/SystemRoleView.vue b/ui/src/views/SystemRoleView.vue index b2a8d2d..b996e01 100644 --- a/ui/src/views/SystemRoleView.vue +++ b/ui/src/views/SystemRoleView.vue @@ -49,14 +49,11 @@ @@ -84,6 +81,7 @@ import { ref, computed, onMounted } from 'vue' import { useApi, useAppStore, useI18nStore } from '@ligoj/host' import { VibrantDataTable, VibrantConfirmDialog as LigojConfirmDialog, LjPageHeader, LjButton, LjSearch, LjDialog, LjAvailabilityField } from '@ligoj/host' +import RowActionsCog from '../components/RowActionsCog.vue' const api = useApi() const app = useAppStore() @@ -272,6 +270,4 @@ onMounted(() => { .tok.api { color: #2f6df6; background: rgba(47, 109, 246, .12); } .tok.ui { color: #1d9d63; background: rgba(29, 157, 99, .13); } .dash { color: var(--ink-3); } -/* Danger accent for the inline delete trigger (base `.lj-iconbtn` is global). */ -.lj-iconbtn.danger:hover { background: rgba(var(--v-theme-error), .1); color: rgb(var(--v-theme-error)); } diff --git a/ui/src/views/SystemUserView.vue b/ui/src/views/SystemUserView.vue index d74ebd0..1a10e1a 100644 --- a/ui/src/views/SystemUserView.vue +++ b/ui/src/views/SystemUserView.vue @@ -53,14 +53,11 @@ @@ -99,6 +96,7 @@ import { ref, computed, onMounted } from 'vue' import { useApi, useAppStore, useDataTable, useI18nStore } from '@ligoj/host' import { VibrantDataTable, VibrantConfirmDialog as LigojConfirmDialog, LjPageHeader, LjButton, LjSearch, LjDialog, LjAvailabilityField } from '@ligoj/host' +import RowActionsCog from '../components/RowActionsCog.vue' const api = useApi() const app = useAppStore() @@ -239,6 +237,4 @@ onMounted(() => { .chips { display: inline-flex; flex-wrap: wrap; gap: 6px; } .rchip { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font); font-weight: 700; font-size: 11.5px; padding: 3px 10px; border-radius: 999px; color: #8b5cf6; background: rgba(139, 92, 246, .13); } .dash { color: var(--ink-3); font-size: 13px; } -/* Danger accent for the inline delete trigger (base `.lj-iconbtn` is global). */ -.lj-iconbtn.danger:hover { background: rgba(var(--v-theme-error), .1); color: rgb(var(--v-theme-error)); }