Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
FluentProvider,
makeStyles,
Toaster,
tokens,
webDarkTheme,
webLightTheme,
Expand All @@ -22,6 +23,7 @@ import { SecretsList } from './components/secrets/SecretsList';
import { SettingsDialog } from './components/settings/SettingsDialog';
import { VaultDashboard } from './components/vault/VaultDashboard';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
import { APP_TOASTER_ID } from './lib/toast';
import { useAppStore } from './stores/appStore';

const queryClient = new QueryClient({
Expand Down Expand Up @@ -76,7 +78,7 @@ function MainContent() {
<EmptyState
icon={<LockClosed24Regular />}
title="Select a Key Vault"
description="Choose a vault from the workspace switcher or sidebar to browse secrets, keys, and certificates."
description="Use the workspace switcher in the top bar — pick a tenant, then a subscription, then a vault — to browse its secrets, keys, and certificates. Press ⌘K / Ctrl+K to search anything."
/>
);
}
Expand Down Expand Up @@ -147,6 +149,7 @@ function App() {
<FluentProvider theme={themeMode === 'dark' ? webDarkTheme : webLightTheme}>
<QueryClientProvider client={queryClient}>
{isSignedIn ? <AppLayout /> : <SignIn />}
<Toaster toasterId={APP_TOASTER_ID} position="bottom-end" />
</QueryClientProvider>
</FluentProvider>
);
Expand Down
1 change: 1 addition & 0 deletions src/components/auth/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const useStyles = makeStyles({
},
card: {
width: '580px',
maxWidth: '90vw',
padding: '28px 32px',
},
headerIcon: {
Expand Down
2 changes: 1 addition & 1 deletion src/components/certificates/CertificateDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function CertificateDetails({ item, onClose }: CertificateDetailsProps) {
<div className={classes.statusRow}>
<span
className="azv-status-dot"
style={{ background: item.enabled ? 'var(--azv-success)' : 'var(--azv-danger)' }}
style={{ background: item.enabled ? 'var(--azv-success)' : 'var(--azv-scroll-thumb)' }}
/>
<Text size={200}>{item.enabled ? 'Active' : 'Disabled'}</Text>
</div>
Expand Down
5 changes: 2 additions & 3 deletions src/components/certificates/CertificatesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ const useStyles = makeStyles({

export function CertificatesList() {
const classes = useStyles();
const { selectedVaultUri, searchQuery, detailPanelOpen, splitRatio, setSplitRatio } =
useAppStore();
const { selectedVaultUri, detailPanelOpen, splitRatio, setSplitRatio } = useAppStore();
const [visibleCount, setVisibleCount] = useState(50);
const [selectedCert, setSelectedCert] = useState<CertificateItem | null>(null);
const [localFilter, setLocalFilter] = useState('');
Expand All @@ -83,7 +82,7 @@ export function CertificatesList() {
enabled: !!selectedVaultUri,
});

const filterText = localFilter || searchQuery;
const filterText = localFilter;
const allCerts = certsQuery.data || [];
const filteredCerts = allCerts.filter((c) =>
c.name.toLowerCase().includes(filterText.toLowerCase()),
Expand Down
21 changes: 16 additions & 5 deletions src/components/common/ItemTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ const useStyles = makeStyles({
fontSize: '11px',
},
dimText: {
opacity: 0.5,
opacity: 0.65,
},
dimmerText: {
opacity: 0.4,
opacity: 0.55,
},
tagWrap: {
display: 'flex',
Expand Down Expand Up @@ -134,6 +134,15 @@ export function ItemTable<T>({
<TableRow
key={id}
onClick={() => onSelect?.(item)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
onSelect?.(item);
}
}}
tabIndex={onSelect ? 0 : undefined}
role="button"
aria-selected={selectedId === id}
className={classes.row}
style={{
background: selectedId === id ? tokens.colorBrandBackground2 : undefined,
Expand Down Expand Up @@ -172,9 +181,11 @@ export function renderEnabled(enabled: boolean) {
<span className="azv-status-row">
<span
className="azv-status-dot"
style={{ background: enabled ? 'var(--azv-success)' : 'var(--azv-danger)' }}
style={{ background: enabled ? 'var(--azv-success)' : 'var(--azv-scroll-thumb)' }}
/>
<Text size={200}>{enabled ? 'Active' : 'Disabled'}</Text>
<Text size={200} style={enabled ? undefined : { opacity: 0.7 }}>
{enabled ? 'Active' : 'Disabled'}
</Text>
</span>
);
}
Expand All @@ -183,7 +194,7 @@ export function renderEnabled(enabled: boolean) {
export function renderDate(dateStr: string | null) {
if (!dateStr)
return (
<Text size={200} style={{ opacity: 0.5 }}>
<Text size={200} style={{ opacity: 0.6 }}>
</Text>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/keys/KeyDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export function KeyDetails({ item, onClose }: KeyDetailsProps) {
<div className={classes.statusRow}>
<span
className="azv-status-dot"
style={{ background: item.enabled ? 'var(--azv-success)' : 'var(--azv-danger)' }}
style={{ background: item.enabled ? 'var(--azv-success)' : 'var(--azv-scroll-thumb)' }}
/>
<Text size={200}>{item.enabled ? 'Active' : 'Disabled'}</Text>
</div>
Expand Down
5 changes: 2 additions & 3 deletions src/components/keys/KeysList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ const columns: Column<KeyItem>[] = [

export function KeysList() {
const classes = useStyles();
const { selectedVaultUri, searchQuery, detailPanelOpen, splitRatio, setSplitRatio } =
useAppStore();
const { selectedVaultUri, detailPanelOpen, splitRatio, setSplitRatio } = useAppStore();
const [visibleCount, setVisibleCount] = useState(50);
const [selectedKey, setSelectedKey] = useState<KeyItem | null>(null);
const [localFilter, setLocalFilter] = useState('');
Expand All @@ -152,7 +151,7 @@ export function KeysList() {
enabled: !!selectedVaultUri,
});

const filterText = localFilter || searchQuery;
const filterText = localFilter;
const allKeys = keysQuery.data || [];
const filteredKeys = allKeys.filter((k) =>
k.name.toLowerCase().includes(filterText.toLowerCase()),
Expand Down
39 changes: 35 additions & 4 deletions src/components/layout/ContentTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { makeStyles, Tab, TabList, tokens } from '@fluentui/react-components';
import { Badge, makeStyles, Tab, TabList, tokens } from '@fluentui/react-components';
import {
Certificate24Regular,
ClipboardTextLtr24Regular,
Key24Regular,
LockClosed24Regular,
TextBulletListSquare24Regular,
} from '@fluentui/react-icons';
import { useQuery } from '@tanstack/react-query';
import { listCertificates, listKeys, listSecrets } from '../../services/tauri';
import { useAppStore } from '../../stores/appStore';
import type { ItemTab } from '../../types';

Expand All @@ -19,14 +21,40 @@ const useStyles = makeStyles({
padding: '0 8px',
gap: '6px',
},
count: {
marginLeft: '6px',
},
});

export function ContentTabs() {
const { activeTab, setActiveTab, selectedVaultName } = useAppStore();
const { activeTab, setActiveTab, selectedVaultName, selectedVaultUri } = useAppStore();
const classes = useStyles();

const secretsQuery = useQuery({
queryKey: ['secrets', selectedVaultUri],
queryFn: () => listSecrets(selectedVaultUri!),
enabled: !!selectedVaultUri,
});
const keysQuery = useQuery({
queryKey: ['keys', selectedVaultUri],
queryFn: () => listKeys(selectedVaultUri!),
enabled: !!selectedVaultUri,
});
const certsQuery = useQuery({
queryKey: ['certificates', selectedVaultUri],
queryFn: () => listCertificates(selectedVaultUri!),
enabled: !!selectedVaultUri,
});

if (!selectedVaultName) return null;

const renderCount = (n: number | undefined) =>
n === undefined ? null : (
<Badge size="small" appearance="outline" className={classes.count}>
{n}
</Badge>
);

return (
<div className={classes.root}>
<TabList
Expand All @@ -38,14 +66,17 @@ export function ContentTabs() {
<Tab value="dashboard" icon={<TextBulletListSquare24Regular />}>
Dashboard
</Tab>
<Tab value="secrets" icon={<Key24Regular />}>
<Tab value="secrets" icon={<LockClosed24Regular />}>
Secrets
{renderCount(secretsQuery.data?.length)}
</Tab>
<Tab value="keys" icon={<LockClosed24Regular />}>
<Tab value="keys" icon={<Key24Regular />}>
Keys
{renderCount(keysQuery.data?.length)}
</Tab>
<Tab value="certificates" icon={<Certificate24Regular />}>
Certs
{renderCount(certsQuery.data?.length)}
</Tab>
<Tab value="logs" icon={<ClipboardTextLtr24Regular />}>
Audit Log
Expand Down
Loading
Loading