| 1 | <template> |
| 2 | <div class="flex flex-col gap-4"> |
| 3 | <div class="flex flex-wrap items-center justify-between gap-3"> |
| 4 | <div class="flex min-w-0 items-center gap-2"> |
| 5 | <div |
| 6 | v-if="categoryMeta" |
| 7 | class="flex shrink-0 items-center justify-center" |
| 8 | :style="{ color: categoryMeta.color }" |
| 9 | > |
| 10 | <Icon :name="getDashboardIcon(categoryMeta.icon)" :size="19" /> |
| 11 | </div> |
| 12 | <div v-if="category"> |
| 13 | {{ category.templates.length }} template{{ category.templates.length !== 1 ? "s" : "" }} |
| 14 | </div> |
| 15 | </div> |
| 16 | |
| 17 | <div class="flex items-center justify-end gap-3"> |
| 18 | <p v-if="!selectedEventSourceId" class="text-xs">select event source to add a template</p> |
| 19 | <n-select |
| 20 | v-model:value="selectedEventSourceId" |
| 21 | :options="eventSourceOptions" |
| 22 | placeholder="Select Event Source" |
| 23 | filterable |
| 24 | :loading="loadingEventSources" |
| 25 | :disabled="!selectedCustomerCode" |
| 26 | clearable |
| 27 | size="small" |
| 28 | :consistent-menu-width="false" |
| 29 | class="w-48! shrink-0" |
| 30 | /> |
| 31 | </div> |
| 32 | </div> |
| 33 | |
| 34 | <n-spin :show="loadingTemplates"> |
| 35 | <div v-if="category?.templates.length" class="grid grid-cols-1 gap-3 @xl:grid-cols-2 @3xl:grid-cols-3"> |
| 36 | <DashboardTemplateCard |
| 37 | v-for="tpl in category.templates" |
| 38 | :key="tpl.id" |
| 39 | :template="tpl" |
| 40 | :selected-customer-code |
| 41 | :selected-event-source-id |
| 42 | :selected-category-id |
| 43 | :enabled-dashboards |
| 44 | @refresh-enabled-dashboards="emit('refreshEnabledDashboards')" |
| 45 | /> |
| 46 | </div> |
| 47 | <n-empty v-else-if="!loadingTemplates" description="No templates in this category" /> |
| 48 | </n-spin> |
| 49 | </div> |
| 50 | </template> |
| 51 | |
| 52 | <script setup lang="ts"> |
| 53 | import type { DashboardCategory, DashboardCategoryWithTemplates, EnabledDashboard } from "@/types/dashboards.d" |
| 54 | import type { EventSource } from "@/types/eventSources.d" |
| 55 | import { NEmpty, NSelect, NSpin } from "naive-ui" |
| 56 | import { computed } from "vue" |
| 57 | import Icon from "@/components/common/Icon.vue" |
| 58 | import DashboardTemplateCard from "./DashboardTemplateCard.vue" |
| 59 | import { getDashboardIcon } from "./utils" |
| 60 | |
| 61 | const props = defineProps<{ |
| 62 | category: DashboardCategoryWithTemplates | null |
| 63 | categoryMeta: DashboardCategory | null |
| 64 | loadingTemplates: boolean |
| 65 | selectedCustomerCode: string | null |
| 66 | loadingEventSources: boolean |
| 67 | eventSourcesList: EventSource[] |
| 68 | selectedCategoryId: string | null |
| 69 | enabledDashboards: EnabledDashboard[] |
| 70 | }>() |
| 71 | |
| 72 | const emit = defineEmits<{ |
| 73 | refreshEnabledDashboards: [] |
| 74 | }>() |
| 75 | |
| 76 | const selectedEventSourceId = defineModel<number | null>("selectedEventSourceId", { default: null }) |
| 77 | |
| 78 | const eventSourceOptions = computed(() => |
| 79 | props.eventSourcesList |
| 80 | .filter(source => source.enabled) |
| 81 | .map(source => ({ |
| 82 | label: `${source.name} (${source.event_type})`, |
| 83 | value: source.id |
| 84 | })) |
| 85 | ) |
| 86 | </script> |