26
26
<EntityFilter
27
27
v-model =" filterQuery"
28
28
:config =" filterConfig"
29
+ @update:fuzzy-filters =" fuzzyFilters = $event"
29
30
/>
30
31
</template >
31
32
<!-- Create action -->
189
190
{{ formatUnixTimeStamp(rowValue ?? row.created_at) }}
190
191
</template >
191
192
193
+ <!-- Declarative columns -->
194
+ <template #matchPath =" { row } " >
195
+ <span class =" route-list-cell-match-path" >
196
+ {{ row.match.path }}
197
+ </span >
198
+ </template >
199
+
200
+ <template #policies =" { row } " >
201
+ {{ row.policies.length }}
202
+ </template >
203
+
192
204
<!-- Row actions -->
193
205
<template #actions =" { row } " >
194
- <KClipboardProvider v-slot =" { copyToClipboard }" >
206
+ <KClipboardProvider
207
+ v-if =" !props.config.declarative"
208
+ v-slot =" { copyToClipboard }"
209
+ >
195
210
<KDropdownItem
196
211
data-testid =" action-entity-copy-id"
197
212
@click =" copyId(row, copyToClipboard)"
207
222
{{ t('actions.copy_json') }}
208
223
</KDropdownItem >
209
224
</KClipboardProvider >
210
- <PermissionsWrapper :auth-function =" () => canRetrieve(row)" >
225
+ <PermissionsWrapper
226
+ v-if =" !props.config.declarative"
227
+ :auth-function =" () => canRetrieve(row)"
228
+ >
211
229
<KDropdownItem
212
230
data-testid =" action-entity-view"
213
231
has-divider
214
232
:item =" getViewDropdownItem(row.id)"
215
233
/>
216
234
</PermissionsWrapper >
217
- <PermissionsWrapper :auth-function =" () => canEdit(row)" >
235
+ <PermissionsWrapper
236
+ v-if =" !props.config.declarative"
237
+ :auth-function =" () => canEdit(row)"
238
+ >
218
239
<KDropdownItem
219
240
data-testid =" action-entity-edit"
220
241
:item =" getEditDropdownItem(row.id)"
221
242
/>
222
243
</PermissionsWrapper >
223
- <PermissionsWrapper :auth-function =" () => canDelete(row)" >
244
+ <PermissionsWrapper
245
+ v-if =" !props.config.declarative"
246
+ :auth-function =" () => canDelete(row)"
247
+ >
224
248
<KDropdownItem
225
249
danger
226
250
data-testid =" action-entity-delete"
248
272
</template >
249
273
250
274
<script setup lang="ts">
251
- import type { PropType } from ' vue'
252
- import { computed , ref , watch , onBeforeMount } from ' vue'
253
- import type { AxiosError } from ' axios'
254
- import { useRouter } from ' vue-router'
255
-
256
- import { BadgeMethodAppearances } from ' @kong/kongponents'
257
- import type { BadgeMethodAppearance , HeaderTag } from ' @kong/kongponents'
258
- import { AddIcon , ForwardIcon , BookIcon } from ' @kong/icons'
275
+ import type {
276
+ BaseTableHeaders ,
277
+ DeclarativeRoute ,
278
+ EmptyStateOptions ,
279
+ ExactMatchFilterConfig ,
280
+ FilterFields ,
281
+ FuzzyMatchFilterConfig ,
282
+ FuzzyMatchFilters ,
283
+ TableErrorMessage ,
284
+ } from ' @kong-ui-public/entities-shared'
259
285
import {
260
286
EntityBaseTable ,
261
287
EntityDeleteModal ,
288
+ EntityEmptyState ,
262
289
EntityFilter ,
263
290
EntityTypes ,
264
291
FetcherStatus ,
265
- EntityEmptyState ,
266
292
PermissionsWrapper ,
293
+ TableTags ,
267
294
useAxios ,
295
+ useDeclarativeRoutesFetcher ,
296
+ useDeleteUrlBuilder ,
268
297
useFetcher ,
269
298
useTableState ,
270
- useDeleteUrlBuilder ,
271
- TableTags ,
272
299
} from ' @kong-ui-public/entities-shared'
300
+ import { KUI_COLOR_TEXT_DECORATIVE_AQUA , KUI_ICON_SIZE_50 } from ' @kong/design-tokens'
301
+ import { AddIcon , BookIcon , ForwardIcon } from ' @kong/icons'
302
+ import type { BadgeMethodAppearance , HeaderTag } from ' @kong/kongponents'
303
+ import { BadgeMethodAppearances } from ' @kong/kongponents'
304
+ import type { AxiosError } from ' axios'
305
+ import type { PropType } from ' vue'
306
+ import { computed , onBeforeMount , ref , watch } from ' vue'
307
+ import { useRouter } from ' vue-router'
308
+ import composables from ' ../composables'
309
+ import endpoints from ' ../routes-endpoints'
273
310
import type {
311
+ CopyEventPayload ,
312
+ EntityRow ,
274
313
KongManagerRouteListConfig ,
275
314
KonnectRouteListConfig ,
276
- EntityRow ,
277
- CopyEventPayload ,
278
315
} from ' ../types'
279
- import type {
280
- BaseTableHeaders ,
281
- EmptyStateOptions ,
282
- ExactMatchFilterConfig ,
283
- FilterFields ,
284
- FuzzyMatchFilterConfig ,
285
- TableErrorMessage ,
286
- } from ' @kong-ui-public/entities-shared'
287
- import ' @kong-ui-public/entities-shared/dist/style.css'
288
316
289
- import composables from ' ../composables'
290
- import endpoints from ' ../routes-endpoints'
291
- import { KUI_COLOR_TEXT_DECORATIVE_AQUA , KUI_ICON_SIZE_50 } from ' @kong/design-tokens'
317
+ import ' @kong-ui-public/entities-shared/dist/style.css'
292
318
293
319
const emit = defineEmits <{
294
320
(e : ' error' , error : AxiosError ): void
@@ -392,18 +418,23 @@ const disableSorting = computed((): boolean => props.config.app !== 'kongManager
392
418
const fields: BaseTableHeaders = {
393
419
// the Name column is non-hidable
394
420
name: { label: t (' routes.list.table_headers.name' ), searchable: true , sortable: true , hidable: false },
395
- protocols: { label: t (' routes.list.table_headers.protocols' ), searchable: true },
396
- ... ! props .hideTraditionalColumns && {
397
- hosts: { label: t (' routes.list.table_headers.hosts' ), searchable: true },
398
- methods: { label: t (' routes.list.table_headers.methods' ), searchable: true },
399
- paths: { label: t (' routes.list.table_headers.paths' ), searchable: true },
400
- },
401
- ... props .hasExpressionColumn && {
402
- expression: { label: t (' routes.list.table_headers.expression' ), tooltip: true },
421
+ ... props .config .declarative ? {
422
+ matchPath: { label: ' Match Path' , searchable: true },
423
+ policies: { label: ' Policies' , searchable: false , sortable: true },
424
+ } : {
425
+ protocols: { label: t (' routes.list.table_headers.protocols' ), searchable: true },
426
+ ... ! props .hideTraditionalColumns && {
427
+ hosts: { label: t (' routes.list.table_headers.hosts' ), searchable: true },
428
+ methods: { label: t (' routes.list.table_headers.methods' ), searchable: true },
429
+ paths: { label: t (' routes.list.table_headers.paths' ), searchable: true },
430
+ },
431
+ ... props .hasExpressionColumn && {
432
+ expression: { label: t (' routes.list.table_headers.expression' ), tooltip: true },
433
+ },
434
+ tags: { label: t (' routes.list.table_headers.tags' ), sortable: false },
435
+ updated_at: { label: t (' routes.list.table_headers.updated_at' ), sortable: true },
436
+ created_at: { label: t (' routes.list.table_headers.created_at' ), sortable: true },
403
437
},
404
- tags: { label: t (' routes.list.table_headers.tags' ), sortable: false },
405
- updated_at: { label: t (' routes.list.table_headers.updated_at' ), sortable: true },
406
- created_at: { label: t (' routes.list.table_headers.created_at' ), sortable: true },
407
438
}
408
439
const defaultTablePreferences = {
409
440
columnVisibility: {
@@ -433,7 +464,17 @@ const fetcherBaseUrl = computed<string>(() => {
433
464
434
465
const filterQuery = ref <string >(' ' )
435
466
const filterConfig = computed <InstanceType <typeof EntityFilter >[' $props' ][' config' ]>(() => {
436
- const isExactMatch = (props .config .app === ' konnect' || props .config .isExactMatch )
467
+ if (props .config .declarative ) {
468
+ const { name, matchPath } = fields
469
+
470
+ return {
471
+ isExactMatch: false ,
472
+ fields: { name , matchPath },
473
+ schema: props .config .declarative .filterSchema ,
474
+ } as FuzzyMatchFilterConfig
475
+ }
476
+
477
+ const isExactMatch = props .config .app === ' konnect' || props .config .isExactMatch
437
478
438
479
if (isExactMatch ) {
439
480
return {
@@ -455,11 +496,34 @@ const filterConfig = computed<InstanceType<typeof EntityFilter>['$props']['confi
455
496
} as FuzzyMatchFilterConfig
456
497
})
457
498
499
+ // This is only used by the Declarative PoC
500
+ // FIXME: This is not optimal as the filterSchema is passed in from the host app
501
+ // This might lead to troublesome type mismatches
502
+ const fuzzyFilters = ref <FuzzyMatchFilters <' name' | ' matchPath' >>()
503
+
504
+ const declarativeFilterFn = (route : DeclarativeRoute ): boolean => {
505
+ if (! fuzzyFilters .value ) {
506
+ return true
507
+ }
508
+
509
+ const { name, matchPath } = fuzzyFilters .value
510
+ if (name && ! route .name .toLowerCase ().includes (name .toLowerCase ())) {
511
+ return false
512
+ }
513
+ if (matchPath && ! route .match .path .toLowerCase ().includes (matchPath .toLowerCase ())) {
514
+ return false
515
+ }
516
+
517
+ return true
518
+ }
519
+
458
520
const {
459
521
fetcher,
460
522
fetcherState,
461
523
fetcherCacheKey,
462
- } = useFetcher (computed (() => ({ ... props .config , cacheIdentifier: props .cacheIdentifier })), fetcherBaseUrl )
524
+ } = props .config .declarative
525
+ ? useDeclarativeRoutesFetcher (() => props .config .declarative ?.config , props .cacheIdentifier , declarativeFilterFn )
526
+ : useFetcher (computed (() => ({ ... props .config , cacheIdentifier: props .cacheIdentifier })), fetcherBaseUrl )
463
527
464
528
const getCellAttrs = (params : Record <string , any >): Record <string , any > => {
465
529
if (params .headerKey === ' expression' ) {
@@ -681,5 +745,9 @@ onBeforeMount(async () => {
681
745
.route-list-cell-expression {
682
746
font-family : $kui-font-family-code ;
683
747
}
748
+
749
+ .route-list-cell-match-path {
750
+ font-family : $kui-font-family-code ;
751
+ }
684
752
}
685
753
</style >
0 commit comments