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 @@
+
+
+
+
+
+
+
+
+
+
+
+
Administration
+
+
+
+
+
+
Active users
+
+ {#if users !== null && users.length > 0}
+
+ {#each users as user}
+ -
+
+
{user.username}
+
+
+ {#if $currentUser !== null && user.id === $currentUser.id}
+
+ {:else}
+
+ {/if}
+
+
+ {user.id}
+
+
+ Created: {formatDateShort(user.createdAt)}, Updated: {formatDateShort(
+ user.updatedAt
+ )}
+
+
+ {/each}
+
+ {/if}
+
+
+
+
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 @@
Username |
- {userData?.username} |
+ {$currentUser?.username} |
Account created |
{userData?.createdAt !== undefined ? formatDateLong(userData?.createdAt) : ""} | {$currentUser?.createdAt !== undefined
+ ? formatDateLong($currentUser?.createdAt)
+ : ""}
Password updated |
{userData?.createdAt !== undefined ? formatDateLong(userData?.updatedAt) : ""} | {$currentUser?.createdAt !== undefined
+ ? formatDateLong($currentUser?.updatedAt)
+ : ""}
- {#if userData?.isAdmin}
+ {#if $currentUser?.isAdmin}
Admin permissions |
- {userData?.isAdmin} |
+ {$currentUser?.isAdmin} |
{/if}
@@ -233,7 +235,7 @@
-
+
Danger Zone
{#if deleteUserModalError}
diff --git a/web/src/lib/components/Sidebar.svelte b/web/src/lib/components/Sidebar.svelte
index 86e4ec4..31d2bbe 100644
--- a/web/src/lib/components/Sidebar.svelte
+++ b/web/src/lib/components/Sidebar.svelte
@@ -6,7 +6,6 @@
import User from "$lib/icons/sidebar/User.svelte"
import ChevronDown from "$lib/icons/ChevronDown.svelte"
import ChevronUp from "$lib/icons/ChevronUp.svelte"
- import Tag from "$lib/icons/sidebar/Tag.svelte"
import WebhookTruck from "$lib/icons/sidebar/WebhookTruck.svelte"
import Search from "$lib/icons/sidebar/Search.svelte"
import SettingsGear from "$lib/icons/sidebar/SettingsGear.svelte"
@@ -25,7 +24,6 @@
export let toggleSettingsModal: () => void
export let toggleAdminModal: () => void
export let toggleWebhookModal: () => void
- export let toggleTagModal: () => void
export let logout: () => Promise
export let createNewNote: () => Promise
export let selectNote: (
@@ -66,7 +64,7 @@
: notes
-
+
{/if}
@@ -129,7 +119,14 @@
@@ -174,7 +166,7 @@
{#each filteredNotes as note}