diff --git a/web/src/app.css b/web/src/app.css index e9597bd..9520983 100644 --- a/web/src/app.css +++ b/web/src/app.css @@ -294,11 +294,11 @@ } .sidebar-button { - @apply flex h-8 w-8 items-center justify-center rounded-lg border border-[var(--light-accent)] bg-transparent p-0 text-[var(--light-text)] hover:bg-[var(--light-background)]/80; + @apply flex h-8 w-8 items-center justify-center rounded-lg border border-[var(--light-accent)] bg-transparent p-0 text-[var(--light-text)] enabled:hover:bg-[var(--light-background)]/80 disabled:cursor-not-allowed; } .dark .sidebar-button { - @apply border-[var(--dark-accent)]/50 text-[var(--dark-text)] hover:bg-[var(--dark-background)]/80; + @apply border-[var(--dark-accent)]/50 text-[var(--dark-text)] enabled:hover:bg-[var(--dark-background)]/80; } .sidebar { @@ -383,11 +383,11 @@ @apply text-[var(--dark-text)]/60; } - .sidebar-list { + .sidebar-list-item { @apply flex cursor-pointer flex-col rounded-lg border border-[var(--light-text)]/10 bg-transparent px-3 py-2 text-sm text-[var(--light-text)] hover:bg-[var(--light-background)]/50; } - .dark .sidebar-list { + .dark .sidebar-list-item { @apply border-[var(--dark-text)]/10 bg-transparent text-[var(--dark-text)] hover:bg-[var(--dark-background)]/80; } @@ -408,11 +408,11 @@ } .sidebar-list-item-delete-button { - @apply ml-1 h-5.5 w-5.5 flex-shrink-0 border-[var(--light-accent)]/40 hover:bg-[var(--light-accent)]/20; + @apply ml-1 h-5.5 w-5.5 flex-shrink-0 border-[var(--light-accent)]/40 enabled:hover:bg-[var(--light-accent)]/20; } .dark .sidebar-list-item-delete-button { - @apply border-[var(--dark-accent)]/40 hover:bg-[var(--dark-accent)]/20; + @apply border-[var(--dark-accent)]/40 enabled:hover:bg-[var(--dark-accent)]/20; } .sidebar-list-item-metadata { @@ -943,14 +943,30 @@ } .modal-table-row-item { - @apply overflow-x-auto px-4 py-3 text-wrap; + @apply overflow-x-auto px-4 py-3 font-light text-wrap; } .modal-table-head { - @apply text-left font-semibold text-[var(--light-text)]/80; + @apply text-left font-medium text-[var(--light-text)]/80; } .dark .modal-table-head { @apply text-[var(--dark-text)]/80; } + + .modal-list-item { + @apply flex w-[90%] flex-col rounded-lg border border-[var(--light-text)]/10 bg-transparent px-3 py-2 text-sm text-[var(--light-text)] hover:bg-[var(--light-foreground)]/50; + } + + .dark .modal-list-item { + @apply border-[var(--dark-text)]/10 bg-transparent text-[var(--dark-text)] hover:bg-[var(--dark-foreground)]/80; + } + + .modal-list-item-metadata { + @apply mt-1 truncate text-xs text-[var(--light-text)]/40; + } + + .dark .modal-list-item-metadata { + @apply text-[var(--dark-text)]/40; + } } diff --git a/web/src/lib/components/AdminModal.svelte b/web/src/lib/components/AdminModal.svelte new file mode 100644 index 0000000..b2935f5 --- /dev/null +++ b/web/src/lib/components/AdminModal.svelte @@ -0,0 +1,142 @@ + + + + + + + diff --git a/web/src/lib/components/NoteEditor.svelte b/web/src/lib/components/NoteEditor.svelte index 9d5402d..e138196 100644 --- a/web/src/lib/components/NoteEditor.svelte +++ b/web/src/lib/components/NoteEditor.svelte @@ -191,7 +191,7 @@ {/if} - +
diff --git a/web/src/lib/components/NoteView.svelte b/web/src/lib/components/NoteView.svelte index 646fd11..c4fb2c9 100644 --- a/web/src/lib/components/NoteView.svelte +++ b/web/src/lib/components/NoteView.svelte @@ -11,11 +11,13 @@ availableNotes, versionHistory, cError, - cSuccess + cSuccess, + availableUsers } from "$lib/logic/client" import Close from "$lib/icons/Close.svelte" import { generateGreeting } from "$lib/util/greetMessage" import { hashContent } from "$lib/util/contentValidation" + import AdminModal from "./AdminModal.svelte" // error/success notification display durations const ERR_NOTIFICATION_DUR = 8 * 1000 // 8 s. @@ -23,7 +25,8 @@ // local state let isComponentReady = false - let showSettings = false + let isSettingsVisible = false + let isAdminViewVisible = false let isSidebarOpen = window.innerWidth > 768 let isSidebarUserMenuOpen = false let isVersionDropdownOpen = false @@ -46,7 +49,9 @@ return } + await adminLoadUsers() // will do nothing if the user isn't an admin await loadNotes() + username = $currentUser.username greetMessage = generateGreeting( // capitalization for the message @@ -104,6 +109,16 @@ keysPressed.clear() } + const adminLoadUsers = async () => { + if ($currentUser !== null && $currentUser.isAdmin) { + const users = await apiClient.adminListAll() + + if (users) { + availableUsers.set(users) + } + } + } + const loadNotes = async () => { const notes = await apiClient.listNotes() @@ -114,12 +129,12 @@ const toggleSettingsModal = () => { isSidebarUserMenuOpen = false - showSettings = !showSettings + isSettingsVisible = !isSettingsVisible } const toggleAdminModal = () => { isSidebarUserMenuOpen = false - console.log("[DBG] Admin view is not implemented yet") + isAdminViewVisible = !isAdminViewVisible } const toggleWebhookModal = () => { @@ -127,11 +142,6 @@ console.log("[DBG] Webhooks aren't implemented yet") } - const toggleTagModal = () => { - isSidebarUserMenuOpen = false - console.log("[DBG] Tags aren't implemented yet") - } - const createNewNote = async () => { const newNote = await apiClient.createNote() @@ -221,6 +231,15 @@ } } + const adminDeleteUser = async (userID: string) => { + await apiClient.adminDeleteUser(userID) + + // refresh the list due to updates being pushed to server + await adminLoadUsers() + + $cSuccess = "User deleted successfully." + } + const deleteNote = async (noteID: string) => { await apiClient.deleteNote(noteID) @@ -321,7 +340,6 @@ {toggleSettingsModal} {toggleAdminModal} {toggleWebhookModal} - {toggleTagModal} {logout} {createNewNote} {selectNote} @@ -358,8 +376,13 @@
- {#if showSettings} + {#if isSettingsVisible} {/if} + + + {#if isAdminViewVisible} + + {/if} {/if} diff --git a/web/src/lib/components/SettingsModal.svelte b/web/src/lib/components/SettingsModal.svelte index b4b1325..805906d 100644 --- a/web/src/lib/components/SettingsModal.svelte +++ b/web/src/lib/components/SettingsModal.svelte @@ -8,8 +8,6 @@ // props export let onClose: () => void - const userData = $currentUser - let currentPassword = "" let newPassword = "" let confirmPassword = "" @@ -113,7 +111,7 @@ } } - const handleModalContentKeydown = (event: KeyboardEvent) => { + const handleModalContentKeydown = (_event: KeyboardEvent) => { // accessibility compliance handler, actual handling is done by the global keydown handler } @@ -137,7 +135,7 @@ -