|
|
@@ -1,51 +1,66 @@
|
|
|
<template>
|
|
|
- <Section class = "with-header-and-content" v-if="entityDefinitions.length === 0" title="Loading entity definitions...">
|
|
|
- <div class = "section-header">
|
|
|
- <h2 class="loading-message">
|
|
|
- Loading entity definitions...
|
|
|
- </h2>
|
|
|
- </div>
|
|
|
+ <Section v-if="!definitionsLoaded" title="Loading entity definitions..." />
|
|
|
+ <Section
|
|
|
+ v-else-if="totalInstances === 0"
|
|
|
+ title="There are no entities to show yet."
|
|
|
+ >
|
|
|
+ <p>
|
|
|
+ When OliveTin has registered entity instances (for example from entity files or your setup), they will be listed here.
|
|
|
+ </p>
|
|
|
</Section>
|
|
|
<template v-else>
|
|
|
<Section v-for="def in entityDefinitions" :key="def.title" :title="'Entity: ' + def.title ">
|
|
|
- <div class = "section-content">
|
|
|
- <p>{{ def.instances.length }} instances.</p>
|
|
|
+ <p>{{ def.instances.length }} instances.</p>
|
|
|
|
|
|
- <ul>
|
|
|
- <li v-for="inst in def.instances" :key="inst.uniqueKey">
|
|
|
- <router-link :to="{ name: 'EntityDetails', params: { entityType: inst.type, entityKey: inst.uniqueKey } }">
|
|
|
- {{ inst.title }}
|
|
|
- </router-link>
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
+ <ul>
|
|
|
+ <li v-for="inst in def.instances" :key="inst.uniqueKey">
|
|
|
+ <router-link :to="{ name: 'EntityDetails', params: { entityType: inst.type, entityKey: inst.uniqueKey } }">
|
|
|
+ {{ inst.title }}
|
|
|
+ </router-link>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
|
|
|
- <h3>Used on Dashboards:</h3>
|
|
|
- <ul>
|
|
|
- <li v-for="dash in filteredDashboards(def.usedOnDashboards)" :key="dash">
|
|
|
- <template v-if="isEntityDirectory(dash)">
|
|
|
- {{ getDashboardTitle(dash) }} <span class="entity-directory-label">[Entity Directory]</span>
|
|
|
- </template>
|
|
|
- <router-link v-else-if="!dash.includes('entity:')" :to="{ name: 'Dashboard', params: { title: getDashboardTitle(dash) } }">
|
|
|
- {{ getDashboardTitle(dash) }}
|
|
|
- </router-link>
|
|
|
- <span v-else>{{ dash }}</span>
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
+ <h3>Used on Dashboards:</h3>
|
|
|
+ <ul>
|
|
|
+ <li v-for="dash in filteredDashboards(def.usedOnDashboards)" :key="dash">
|
|
|
+ <template v-if="isEntityDirectory(dash)">
|
|
|
+ {{ getDashboardTitle(dash) }} <span class="entity-directory-label">[Entity Directory]</span>
|
|
|
+ </template>
|
|
|
+ <router-link v-else-if="!dash.includes('entity:')" :to="{ name: 'Dashboard', params: { title: getDashboardTitle(dash) } }">
|
|
|
+ {{ getDashboardTitle(dash) }}
|
|
|
+ </router-link>
|
|
|
+ <span v-else>{{ dash }}</span>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
</Section>
|
|
|
</template>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import { ref, onMounted } from 'vue'
|
|
|
+ import { ref, computed, onMounted } from 'vue'
|
|
|
import Section from 'picocrank/vue/components/Section.vue'
|
|
|
|
|
|
+ const definitionsLoaded = ref(false)
|
|
|
const entityDefinitions = ref([])
|
|
|
|
|
|
- async function fetchEntities() {
|
|
|
- const ret = await window.client.getEntities()
|
|
|
+ const totalInstances = computed(() =>
|
|
|
+ entityDefinitions.value.reduce(
|
|
|
+ (sum, def) => sum + (def.instances?.length ?? 0),
|
|
|
+ 0,
|
|
|
+ ),
|
|
|
+ )
|
|
|
|
|
|
- entityDefinitions.value = ret.entityDefinitions
|
|
|
+ async function fetchEntities() {
|
|
|
+ try {
|
|
|
+ const ret = await window.client.getEntities()
|
|
|
+ entityDefinitions.value = ret.entityDefinitions ?? []
|
|
|
+ } catch (err) {
|
|
|
+ console.error('Failed to fetch entities:', err)
|
|
|
+ window.showBigError('fetch-entities', 'getting entities', err, false)
|
|
|
+ entityDefinitions.value = []
|
|
|
+ } finally {
|
|
|
+ definitionsLoaded.value = true
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
function filteredDashboards(dashboards) {
|