mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-09 16:05:42 +00:00
feat(frontend): add filter by resource on Audit Log page (#2628)
* feat(frontend): add filter by resouce on Audit Log page * feat(frontend): fix build
This commit is contained in:
@@ -4,13 +4,21 @@
|
||||
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import CalendarPicker from '$lib/components/common/calendarPicker/CalendarPicker.svelte'
|
||||
import { AuditLog, AuditService, UserService } from '$lib/gen'
|
||||
import {
|
||||
AuditLog,
|
||||
AuditService,
|
||||
ResourceService,
|
||||
UserService,
|
||||
type ListableResource
|
||||
} from '$lib/gen'
|
||||
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { Loader2, RefreshCcw } from 'lucide-svelte'
|
||||
import { onDestroy } from 'svelte'
|
||||
import AutoComplete from 'simple-svelte-autocomplete'
|
||||
|
||||
let usernames: string[]
|
||||
let resources: ListableResource[]
|
||||
let loading: boolean = false
|
||||
|
||||
export let logs: AuditLog[] = []
|
||||
@@ -20,7 +28,7 @@
|
||||
export let after: string | undefined = undefined
|
||||
export let perPage: number | undefined = 100
|
||||
export let operation: string = 'all'
|
||||
export let resource: string | undefined = undefined
|
||||
export let resource: string | undefined = 'all'
|
||||
export let actionKind: ActionKind | 'all' = 'all'
|
||||
|
||||
async function loadLogs(
|
||||
@@ -47,6 +55,10 @@
|
||||
actionKind = undefined
|
||||
}
|
||||
|
||||
if (resource == 'all' || resource == '') {
|
||||
resource = undefined
|
||||
}
|
||||
|
||||
logs = await AuditService.listAuditLogs({
|
||||
workspace: $workspaceStore!,
|
||||
page,
|
||||
@@ -69,9 +81,16 @@
|
||||
: [$userStore?.username ?? '']
|
||||
}
|
||||
|
||||
async function loadResources() {
|
||||
resources = await ResourceService.listResource({
|
||||
workspace: $workspaceStore!
|
||||
})
|
||||
}
|
||||
|
||||
$: {
|
||||
if ($workspaceStore && refresh) {
|
||||
loadUsers()
|
||||
loadResources()
|
||||
loadLogs(username, pageIndex, perPage, before, after, operation, resource, actionKind)
|
||||
}
|
||||
}
|
||||
@@ -159,6 +178,7 @@
|
||||
perPage = Number(urlSearchParams.get('perPage')) || 100
|
||||
operation = urlSearchParams.get('operation') ?? 'all'
|
||||
resource = urlSearchParams.get('resource') ?? undefined
|
||||
|
||||
actionKind = (urlSearchParams.get('actionKind') as ActionKind) ?? 'all'
|
||||
}
|
||||
|
||||
@@ -256,7 +276,7 @@
|
||||
let refresh = 1
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col items-center gap-6 xl:gap-1 xl:flex-row mt-4 xl:mt-0">
|
||||
<div class="flex flex-col items-center gap-6 2xl:gap-1 2xl:flex-row mt-4 xl:mt-0">
|
||||
<div class="flex gap-1 relative w-full">
|
||||
<span class="text-xs absolute -top-4">After</span>
|
||||
<input type="text" value={after ?? 'After'} disabled />
|
||||
@@ -299,6 +319,18 @@
|
||||
{/if}
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex gap-1 relative w-full">
|
||||
<span class="text-xs absolute -top-4">Resource</span>
|
||||
|
||||
<AutoComplete
|
||||
items={resources?.map((r) => r.path) ?? []}
|
||||
value={resource}
|
||||
bind:selectedItem={resource}
|
||||
inputClassName="!h-[34px] py-1 !text-xs !w-48"
|
||||
hideArrow
|
||||
dropdownClassName="!text-sm !w-48 !max-w-48"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-1 relative w-full">
|
||||
<span class="text-xs absolute -top-4">Operation</span>
|
||||
@@ -334,6 +366,7 @@
|
||||
actionKind = 'all'
|
||||
pageIndex = 1
|
||||
perPage = 100
|
||||
resource = 'all'
|
||||
}}
|
||||
size="xs"
|
||||
>
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
import type { AuditLog } from '$lib/gen'
|
||||
import { displayDate } from '$lib/utils'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import Button from '../common/button/Button.svelte'
|
||||
import { ListFilter } from 'lucide-svelte'
|
||||
|
||||
export let logs: AuditLog[] = []
|
||||
export let pageIndex: number | undefined = 1
|
||||
@@ -14,6 +16,8 @@
|
||||
export let actionKind: string | undefined = undefined
|
||||
export let operation: string | undefined = undefined
|
||||
export let selectedId: number | undefined = undefined
|
||||
export let usernameFilter: string | undefined = undefined
|
||||
export let resourceFilter: string | undefined = undefined
|
||||
|
||||
function groupLogsByDay(logs: AuditLog[]): Record<string, AuditLog[]> {
|
||||
const groupedLogs = {}
|
||||
@@ -103,8 +107,19 @@
|
||||
{displayDate(timestamp)}
|
||||
</Cell>
|
||||
<Cell>
|
||||
<div class="whitespace-nowrap overflow-x-auto no-scrollbar w-20">
|
||||
{username}
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<div class="whitespace-nowrap overflow-x-auto no-scrollbar w-20">
|
||||
{username}
|
||||
</div>
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
iconOnly
|
||||
startIcon={{ icon: ListFilter }}
|
||||
on:click={() => {
|
||||
usernameFilter = username
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Cell>
|
||||
<Cell>
|
||||
@@ -125,8 +140,19 @@
|
||||
</div>
|
||||
</Cell>
|
||||
<Cell last>
|
||||
<div class="whitespace-nowrap overflow-x-auto no-scrollbar w-48">
|
||||
{resource}
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<div class="whitespace-nowrap overflow-x-auto no-scrollbar w-48">
|
||||
{resource}
|
||||
</div>
|
||||
<Button
|
||||
color="light"
|
||||
size="xs2"
|
||||
iconOnly
|
||||
startIcon={{ icon: ListFilter }}
|
||||
on:click={() => {
|
||||
resourceFilter = resource
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Cell>
|
||||
</Row>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
let perPage: number | undefined = Number($page.url.searchParams.get('perPage')) || 100
|
||||
let operation: string = $page.url.searchParams.get('operation') ?? 'all'
|
||||
let resource: string | undefined = $page.url.searchParams.get('resource') ?? undefined
|
||||
|
||||
let actionKind: ActionKind | 'all' =
|
||||
($page.url.searchParams.get('actionKind') as ActionKind) ?? 'all'
|
||||
|
||||
@@ -40,7 +41,7 @@
|
||||
You can only see your own audit logs unless you are an admin.
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="hidden xl:block">
|
||||
<div class="hidden 2xl:block">
|
||||
<AuditLogsFilters
|
||||
bind:logs
|
||||
bind:username
|
||||
@@ -53,7 +54,7 @@
|
||||
bind:perPage
|
||||
/>
|
||||
</div>
|
||||
<div class="xl:hidden">
|
||||
<div class="2xl:hidden">
|
||||
<AuditLogMobileFilters>
|
||||
<svelte:fragment slot="filters">
|
||||
<AuditLogsFilters
|
||||
@@ -87,6 +88,8 @@
|
||||
bind:perPage
|
||||
bind:actionKind
|
||||
bind:operation
|
||||
bind:usernameFilter={username}
|
||||
bind:resourceFilter={resource}
|
||||
on:select={(e) => {
|
||||
selectedId = e.detail
|
||||
}}
|
||||
@@ -105,6 +108,8 @@
|
||||
bind:perPage
|
||||
bind:actionKind
|
||||
bind:operation
|
||||
bind:usernameFilter={username}
|
||||
bind:resourceFilter={resource}
|
||||
on:select={(e) => {
|
||||
selectedId = e.detail
|
||||
|
||||
|
||||
Reference in New Issue
Block a user