diff --git a/ui/src/components/LayoutShell.module.css b/ui/src/components/LayoutShell.module.css index 2c09aa76..4f89366e 100644 --- a/ui/src/components/LayoutShell.module.css +++ b/ui/src/components/LayoutShell.module.css @@ -43,6 +43,34 @@ opacity: 0.6; } +.appSectionWrap { + position: relative; +} + +.addAppBtn { + position: absolute; + top: 6px; + right: 6px; + z-index: 1; + display: flex; + align-items: center; + gap: 2px; + background: none; + border: none; + padding: 2px 6px; + border-radius: 4px; + font-size: 12px; + font-weight: 500; + color: var(--sidebar-muted); + cursor: pointer; + transition: color 0.12s, background 0.12s; +} + +.addAppBtn:hover { + color: var(--amber); + background: rgba(255, 255, 255, 0.06); +} + .mainContent { flex: 1; display: flex; diff --git a/ui/src/components/LayoutShell.tsx b/ui/src/components/LayoutShell.tsx index 270e1609..fce8c9f2 100644 --- a/ui/src/components/LayoutShell.tsx +++ b/ui/src/components/LayoutShell.tsx @@ -21,7 +21,7 @@ import { } from '@cameleer/design-system'; import type { SearchResult, SidebarTreeNode, DropdownItem, ButtonGroupItem, ExchangeStatus } from '@cameleer/design-system'; import sidebarLogo from '@cameleer/design-system/assets/cameleer3-logo.svg'; -import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X, User } from 'lucide-react'; +import { Box, Settings, FileText, ChevronRight, Square, Pause, Star, X, User, Plus } from 'lucide-react'; import { AboutMeDialog } from './AboutMeDialog'; import css from './LayoutShell.module.css'; import { useQueryClient } from '@tanstack/react-query'; @@ -31,7 +31,7 @@ import { useSearchExecutions, useAttributeKeys } from '../api/queries/executions import { useUsers, useGroups, useRoles } from '../api/queries/admin/rbac'; import { useEnvironments } from '../api/queries/admin/environments'; import type { UserDetail, GroupDetail, RoleDetail } from '../api/queries/admin/rbac'; -import { useAuthStore, useIsAdmin } from '../auth/auth-store'; +import { useAuthStore, useIsAdmin, useCanControl } from '../auth/auth-store'; import { useEnvironmentStore } from '../api/environment-store'; import { useState, useMemo, useCallback, useEffect, useRef, createElement } from 'react'; import type { ReactNode } from 'react'; @@ -296,6 +296,7 @@ function LayoutContent() { // --- Role checks ---------------------------------------------------- const isAdmin = useIsAdmin(); + const canControl = useCanControl(); // --- Environment filtering ----------------------------------------- const selectedEnv = useEnvironmentStore((s) => s.environment); @@ -692,23 +693,34 @@ function LayoutContent() { /> {/* Applications section */} - - - +
+ {canControl && ( + + )} + + + +
{/* Starred section — only when there are starred items */} {starredItems.length > 0 && (