Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Signed-off-by: Frank Jogeleit <[email protected]>
  • Loading branch information
Frank Jogeleit committed Dec 23, 2023
1 parent 71ddf53 commit 5774ce3
Show file tree
Hide file tree
Showing 27 changed files with 782 additions and 241 deletions.
38 changes: 38 additions & 0 deletions frontend/components/PageLayout.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<v-container fluid class="py-4 px-4 main-height">
<v-row>
<v-col>
<v-card>
<v-toolbar color="indigo-darken-4" elevation="2">
<v-toolbar-title>{{ title }}</v-toolbar-title>
<template #append>
<FormKindAutocomplete style="min-width: 300px; max-width: 100%; margin-right: 15px;" v-model="kinds" :source="source" />
<FormClusterKindAutocomplete v-if="!nsScoped" style="min-width: 300px;" v-model="clusterKinds" :source="source" />
</template>
</v-toolbar>
</v-card>
</v-col>
</v-row>
<slot />
</v-container>
</template>

<script setup lang="ts">
import { ClusterKinds, NamespacedKinds } from "~/modules/core/provider/dashboard";
const props = defineProps<{ title?: string; source?: string; nsScoped?: boolean; kinds?: string[]; clusterKinds?: string[] }>()
const kinds = ref<string[]>(props.kinds ?? [])
const clusterKinds = ref<string[]>(props.clusterKinds ?? [])
provide(NamespacedKinds, kinds)
provide(ClusterKinds, clusterKinds)
const emit = defineEmits<{
'update:kinds': [kinds: string[]];
'update:clusterKinds': [kinds: string[]];
}>()
watch(kinds, (k) => emit('update:kinds', [...k]))
watch(clusterKinds, (k) => emit('update:clusterKinds', [...k]))
</script>
3 changes: 2 additions & 1 deletion frontend/layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<v-layout>
<v-app-bar elevation="1" prominent>
<v-app-bar-nav-icon color="white" icon="mdi-menu" @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
<v-app-bar-nav-icon icon="mdi-menu" @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
<v-toolbar-title>Policy Reporter</v-toolbar-title>
<template #append>
<cluster-select />
Expand Down Expand Up @@ -65,6 +65,7 @@ const { data: customBoards } = useAPI((api) => api.customBoards(), { default: ()
const navigation = [
{ title: 'Dashboard', path: '/', exact: true },
{ title: 'Policies', path: '/policies', exact: true },
];
const boards = computed(() => (customBoards.value || []).map(b => ({
Expand Down
22 changes: 16 additions & 6 deletions frontend/modules/core/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import {
type Pagination,
type FindingCounts,
type ResourceResultList,
type ResourceResult, type ResourceStatusCount, type Resource, type Source, type CustomBoard, type CustomBoardDetails
type ResourceResult,
type ResourceStatusCount,
type Resource,
type Source,
type CustomBoard,
type CustomBoardDetails,
type PolicyResult
} from './types'

type APIConfig = { baseURL: string; prefix?: string; };
Expand Down Expand Up @@ -45,8 +51,8 @@ export class CoreAPI {
return $fetch<string[]>('/proxy/'+this.cluster+'/core/v1/categories', { baseURL: this.baseURL, params: { sources: [source], kinds: kind ? [kind] : undefined } })
}

namespaces (source?: string) {
return $fetch<string[]>('/proxy/'+this.cluster+'/core/v1/namespaces', { baseURL: this.baseURL, params: { sources: source ? [source] : undefined } })
namespaces (source?: string, filter?: Filter) {
return $fetch<string[]>('/proxy/'+this.cluster+'/core/v1/namespaces', { baseURL: this.baseURL, params: { ...filter, sources: source ? [source] : undefined } })
}

ruleStatusCount (policy: string, rule: string) {
Expand Down Expand Up @@ -126,11 +132,15 @@ export class CoreAPI {
}

results (id: string, pagination?: Pagination, filter?: Filter) {
return $fetch<ResultList>('/proxy/'+this.cluster+'/core/v1/results', { baseURL: this.baseURL, params: { id, ...pagination, filter } })
return $fetch<ResultList>('/proxy/'+this.cluster+'/core/v1/results', { baseURL: this.baseURL, params: { id, ...pagination, ...filter } })
}

sources (id?: string) {
return $fetch<Source[]>('/proxy/'+this.cluster+'/core/v1/sources', { baseURL: this.baseURL, params: { id } })
sources (id?: string, filter?: Filter) {
return $fetch<Source[]>('/proxy/'+this.cluster+'/core/v1/sources', { baseURL: this.baseURL, params: { id, ...applyExcludes(filter, [...this.nsExcludes, ...this.clusterExcludes]) } })
}

policies (filter?: Filter) {
return $fetch<PolicyResult[]>('/proxy/'+this.cluster+'/core/v1/policies', { baseURL: this.baseURL, params: applyExcludes(filter, this.nsExcludes)})
}

customBoards () {
Expand Down
31 changes: 16 additions & 15 deletions frontend/modules/core/components/CategoryTables.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,30 @@
<v-row>
<v-col cols="12">
<v-card>
<v-card-title class="py-4">
<span class="text-h5">
{{ capilize(source.name) }}
</span>
</v-card-title>
<v-toolbar color="primary">
<v-toolbar-title>{{ capilize(source.name) }}</v-toolbar-title>
<template #append>
<CollapseBtn v-model="open" />
</template>
</v-toolbar>
<div v-show="open">
<v-divider />
<v-card-text>
<ChartStatusPerCategory :source="source" />
</v-card-text>
<result-table :source="source.name" :resource="resource.id" v-for="category in source.categories" :key="category.name" :category="category.name" />
</div>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-card>
<v-card-text>
<ChartStatusPerCategory :source="source" />
</v-card-text>
</v-card>
</v-col>
</v-row>
<result-table :source="source.name" :resource="resource.id" v-for="category in source.categories" :key="category.name" :category="category.name" />
</template>

<script setup lang="ts">
import { capilize } from "~/modules/core/layouthHelper";
import type { Resource, Source } from "~/modules/core/types";
import CollapseBtn from "~/components/CollapseBtn.vue";
const open = ref(true)
const props = defineProps<{
source: Source;
Expand Down
33 changes: 29 additions & 4 deletions frontend/modules/core/components/ResourceResultList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
<CollapseBtn v-model="open" :disabled="!data.items.length" />
</template>
</v-toolbar>
<v-list v-if="data?.items?.length && open" lines="two">
<v-list v-if="data?.items?.length && open" lines="two" class="pt-0">
<ResourceResultItem v-for="item in data.items" :key="item.id" :item="item" :details="details" :filter="filter" />
</v-list>
<template v-if="data.count > options.offset">
<v-divider />
<v-pagination v-model="options.page" :length="length" class="my-4" />
</template>
<template v-if="!pending && !(data.items.length)">
<v-divider />
<v-card-text>
Expand All @@ -23,7 +27,7 @@

<script setup lang="ts">
import CollapseBtn from "~/components/CollapseBtn.vue";
import type { Filter } from "~/modules/core/types";
import type { Filter, Pagination } from "~/modules/core/types";
import type { Ref } from "vue";
import { NamespacedKinds, ResourceFilter } from "~/modules/core/provider/dashboard";
import { execOnChange } from "~/helper/compare";
Expand All @@ -46,12 +50,33 @@ const combinedFilter = computed(() => ({
search: search.value,
}))
const options = reactive<Pagination>({
page: 1,
offset: 8,
})
const length = computed(() => {
return Math.ceil((data.value?.count || 0) / options.offset)
})
const { data, refresh, pending } = useAPI(
(api) => api.namespacedResourceResults(combinedFilter.value),
(api) => api.namespacedResourceResults(combinedFilter.value, options),
{
default: () => ({ items: [], count: 0 }),
}
);
watch(combinedFilter, (n, o) => execOnChange(n, o, refresh))
watch(combinedFilter, (o, n) =>
execOnChange(o, n, () => {
if (options.page !== 1) {
options.page = 1
return
}
refresh()
})
)
watch(options, () => refresh())
</script>
2 changes: 1 addition & 1 deletion frontend/modules/core/components/ResourceScroller.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<v-infinite-scroll :onLoad="load" class="no-scrollbar">
<v-infinite-scroll :onLoad="load" class="no-scrollbar" v-if="loaded.length">
<template v-for="item in loaded" :key="item">
<v-row>
<v-col>
Expand Down
4 changes: 2 additions & 2 deletions frontend/modules/core/components/ResultChip.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<v-chip :prepend-icon="`mdi-${icons[status]}`" :color="mapStatus(status)" variant="flat">
<div class="text-right" style="min-width: 40px;">{{ count }}</div>
<div class="text-right" style="min-width: 40px;">{{ count || 0 }}</div>
<v-tooltip :text="tooltip" location="top" activator="parent" />
</v-chip>
</template>
Expand All @@ -11,7 +11,7 @@ import { mapStatus } from '../mapper'
defineProps<{
status: string;
count: number;
count?: number;
tooltip: string;
}>()
Expand Down
116 changes: 57 additions & 59 deletions frontend/modules/core/components/ResultTable.vue
Original file line number Diff line number Diff line change
@@ -1,63 +1,61 @@
<template>
<v-row v-if="data.count > 0 || !!searchText">
<v-col cols="12">
<v-card>
<template #title>
<span v-if="category">{{ category }}</span>
<span v-else>Results for {{ capilize(source) }}</span>
</template>
<template #append>
<search v-model="searchText" class="mr-4" style="min-width: 400px; float: left; height: 48px;" />
<v-btn :icon="open ? 'mdi-chevron-up' : 'mdi-chevron-down'" @click="open = !open" variant="text" />
</template>
<v-expand-transition>
<div v-show="open">
<v-divider />
<v-data-table-server
:items="results.results"
:items-length="results.count"
:headers="headers"
item-value="id"
show-expand
v-model:items-per-page="options.itemsPerPage"
v-model:page="options.page"
>
<template #item.status="{ value }">
<chip-status @click="searchText = value" :status="value" />
</template>
<template #item.severity="{ value }">
<chip-severity v-if="value" @click="searchText = value" :severity="value" />
</template>
<template #expanded-row="{ columns, item }">
<tr class="table-expand-text">
<td :colspan="columns.length" class="py-3">
<div v-if="item.hasProps">
<v-card v-if="item.message" variant="flat">
<v-alert type="info" variant="flat">
{{ item.message }}
</v-alert>
</v-card>
<div>
<template v-for="(value, label) in item.chips" :key="label">
<property-chip :label="label as string" :value="value" class="mr-2 mt-2 rounded-xl" />
</template>
<template v-for="(value, label) in item.cards" :key="label">
<property-card :label="label as string" :value="value" class="mt-2" />
</template>
</div>
</div>
<div v-else>
<div v-if="data.count > 0 || !!searchText">
<v-toolbar color="secondary">
<template #title>
<span v-if="category">{{ category }}</span>
<span v-else>Results for {{ capilize(source) }}</span>
</template>
<template #append>
<search v-model="searchText" class="mr-4" style="min-width: 400px; float: left;" />
<v-btn :icon="open ? 'mdi-chevron-up' : 'mdi-chevron-down'" @click="open = !open" variant="text" />
</template>
</v-toolbar>
<v-expand-transition>
<div v-show="open">
<v-divider />
<v-data-table-server
:items="results.results"
:items-length="results.count"
:headers="headers"
item-value="id"
show-expand
v-model:items-per-page="options.itemsPerPage"
v-model:page="options.page"
>
<template #item.status="{ value }">
<chip-status @click="searchText = value" :status="value" />
</template>
<template #item.severity="{ value }">
<chip-severity v-if="value" @click="searchText = value" :severity="value" />
</template>
<template #expanded-row="{ columns, item }">
<tr class="table-expand-text">
<td :colspan="columns.length" class="py-3">
<div v-if="item.hasProps">
<v-card v-if="item.message" variant="flat">
<v-alert type="info" variant="flat">
{{ item.message }}
</div>
</td>
</tr>
</template>
</v-data-table-server>
</div>
</v-expand-transition>
</v-card>
</v-col>
</v-row>
</v-alert>
</v-card>
<div>
<template v-for="(value, label) in item.chips" :key="label">
<property-chip :label="label as string" :value="value" class="mr-2 mt-2 rounded-xl" />
</template>
<template v-for="(value, label) in item.cards" :key="label">
<property-card :label="label as string" :value="value" class="mt-2" />
</template>
</div>
</div>
<div v-else>
{{ item.message }}
</div>
</td>
</tr>
</template>
</v-data-table-server>
</div>
</v-expand-transition>
</div>
</template>

<script lang="ts" setup>
Expand Down Expand Up @@ -93,7 +91,7 @@ const { data, refresh } = useAPI(
}, {
sources: props.source ? [props.source] : undefined,
categories: props.category ? [props.category] : undefined,
search: searchText.value,
search: !!searchText.value ? searchText.value : undefined,
}),
{
default: () => ({ items: [], count: 0 }),
Expand Down
Loading

0 comments on commit 5774ce3

Please sign in to comment.