Skip to content

Commit

Permalink
TechnicalData Plugin: Add switch for table view of technical properties
Browse files Browse the repository at this point in the history
  • Loading branch information
seicke committed Nov 5, 2024
1 parent e1b677f commit d921ca5
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 9 deletions.
55 changes: 51 additions & 4 deletions aas-web-ui/src/components/SubmodelPlugins/TechnicalData.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,36 @@
<v-container fluid class="pa-0">
<!-- Header -->
<v-card class="mb-4">
<v-card-title>
<div class="text-subtitle-1">{{ 'Technical Data:' }}</div>
<v-card-title class="pb-0 d-flex justify-space-between align-center">
<span>{{ nameToDisplay(submodelElementData) }}</span>
<v-switch
v-model="tableView"
color="primary"
label="Table View"
hide-details
density="compact"
class="pa-0"></v-switch>
</v-card-title>
<v-card-subtitle>
<SemanticID
v-if="
submodelElementData.semanticId &&
submodelElementData.semanticId.keys &&
submodelElementData.semanticId.keys.length > 0
"
:semantic-id-object="submodelElementData.semanticId"></SemanticID>
</v-card-subtitle>
<v-card-text class="pt-0">
{{ descriptionToDisplay(submodelElementData) }}
</v-card-text>
</v-card>
<!-- Technical Data Collections -->
<v-card v-if="loading">
<v-skeleton-loader
type="list-item-avatar, divider, list-item-avatar, divider, list-item-avatar, divider, list-item-avatar"
:height="288"></v-skeleton-loader>
</v-card>
<v-expansion-panels v-else v-model="panel" multiple>
<v-expansion-panels v-model="panel" multiple>
<!-- General Information -->
<v-expansion-panel>
<v-expansion-panel-title>
Expand Down Expand Up @@ -149,7 +168,30 @@
</v-expansion-panel-title>
<v-divider v-if="panel.includes(2)"></v-divider>
<v-expansion-panel-text>
<GenericDataVisu class="mt-3" :submodel-element-data="technicalProperties"></GenericDataVisu>
<GenericDataVisu
v-if="!tableView"
class="mt-3"
:submodel-element-data="technicalProperties"></GenericDataVisu>
<template v-else>
<v-card variant="outlined" class="mt-3">
<v-table density="comfortable">
<thead>
<tr>
<th>SubmodelElement</th>
<th>Description</th>
<th>Semantics</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<GenericDataTableView
class="mt-3"
:submodel-element-data="technicalProperties"
:level="0"></GenericDataTableView>
</tbody>
</v-table>
</v-card>
</template>
</v-expansion-panel-text>
</v-expansion-panel>
<!-- Further Information -->
Expand Down Expand Up @@ -214,15 +256,19 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { useTheme } from 'vuetify';
import GenericDataTableView from '@/components/UIComponents/GenericDataTableView.vue';
import GenericDataVisu from '@/components/UIComponents/GenericDataVisu.vue';
import SemanticID from '@/components/UIComponents/SemanticID.vue';
import RequestHandling from '@/mixins/RequestHandling';
import SubmodelElementHandling from '@/mixins/SubmodelElementHandling';
import { useAASStore } from '@/store/AASDataStore';
export default defineComponent({
name: 'TechnicalData',
components: {
SemanticID,
GenericDataVisu,
GenericDataTableView,
},
mixins: [RequestHandling, SubmodelElementHandling],
props: ['submodelElementData'],
Expand All @@ -248,6 +294,7 @@
ManufacturerLogoUrl: '',
ProductImageUrl: '',
loading: false,
tableView: false,
};
},
Expand Down
94 changes: 94 additions & 0 deletions aas-web-ui/src/components/UIComponents/GenericDataTableView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<template>
<template v-if="submodelElementData && Array.isArray(submodelElementData) && submodelElementData.length > 0">
<template v-for="(submodelElement, index) in submodelElementData" :key="index">
<template v-if="['SubmodelElementCollection', 'SubmodelElementList'].includes(submodelElement.modelType)">
<tr>
<td colspan="4">
<p class="font-weight-bold py-4" :class="'pl-' + level * 3">
<v-icon class="mr-2" size="small">mdi-folder</v-icon>
<span>{{ nameToDisplay(submodelElement) }}</span>
</p>
</td>
</tr>
<GenericDataTableView
:submodel-element-data="submodelElement.value"
:level="Number(level) + 1"></GenericDataTableView>
</template>
<template v-else-if="['Property', 'MultiLanguageProperty'].includes(submodelElement.modelType)">
<tr>
<td>
<p>
<v-tooltip
location="bottom start"
open-delay="250"
:text="descriptionToDisplay(submodelElement)">
<template #activator="{ props }">
<span v-bind="props">
{{ nameToDisplay(submodelElement) }}
</span>
</template>
</v-tooltip>
</p>
</td>
<td>
<p>{{ descriptionToDisplay(submodelElement) }}</p>
</td>
<td>
<SemanticID
v-if="
submodelElement.semanticId &&
submodelElement.semanticId.keys &&
submodelElement.semanticId.keys.length > 0
"
:semantic-id-object="submodelElement.semanticId"></SemanticID>
</td>
<td>
<p>
{{ valueToDisplay(submodelElement) }}
</p>
</td>
</tr>
</template>
</template>
</template>
<template v-else>
<tr style="border: 0 !important'">
<td colspan="4" style="border: 0 !important">-</td>
</tr>
</template>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { useTheme } from 'vuetify';
import SemanticID from '@/components/UIComponents/SemanticID.vue';
import SubmodelElementHandling from '@/mixins/SubmodelElementHandling';
export default defineComponent({
name: 'GenericDataTableView',
components: { SemanticID },
mixins: [SubmodelElementHandling],
inheritAttrs: false,
props: {
submodelElementData: {
type: Object,
default() {
return {};
},
required: true,
},
level: {
type: Number,
default: 0,
},
},
setup() {
const theme = useTheme();
return {
theme, // Theme Object
};
},
});
</script>
10 changes: 5 additions & 5 deletions aas-web-ui/src/components/UIComponents/SemanticID.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<v-container fluid class="pa-0">
<v-list-item>
<v-list-item :class="semanticTitle && semanticTitle.trim().length > 0 ? '' : 'pa-0'">
<!-- Tooltip with SemanticId -->
<v-tooltip activator="parent" open-delay="600" transition="slide-x-transition">
<div v-for="(semanticId, i) in semanticIdObject.keys" :key="i" class="text-caption">
Expand All @@ -9,14 +9,14 @@
</div>
</v-tooltip>
<!-- SemanticIId Title -->
<template #title>
<div class="text-subtitle-2 mt-2" v-html="semanticTitle + ':'"></div>
<template v-if="semanticTitle && semanticTitle.trim().length > 0" #title>
<div class="text-subtitle-2 mt-2">{{ semanticTitle + ':' }}</div>
</template>
<!-- SemanticId List -->
<v-list-item-subtitle v-for="(semanticId, i) in semanticIdObject.keys" :key="i">
<div class="pt-2">
<div :class="semanticTitle && semanticTitle.trim().length > 0 ? 'pt-2' : ''">
<v-chip label size="x-small" border class="mr-2">{{ semanticId.type }}</v-chip>
<span v-html="semanticId.value"></span>
<span>{{ semanticId.value }}</span>
</div>
</v-list-item-subtitle>
</v-list-item>
Expand Down
48 changes: 48 additions & 0 deletions aas-web-ui/src/mixins/SubmodelElementHandling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,54 @@ export default defineComponent({
return sme.idShort ? sme.idShort : '';
},

descriptionToDisplay(referable: any) {
if (referable && referable?.description) {
const descriptionEn = referable.description.find(
(description: any) => description && description.language === 'en' && description.text !== ''
);
if (descriptionEn && descriptionEn.text) return descriptionEn.text;
}
return '';
},

valueToDisplay(submodelElement: any) {
if (submodelElement && submodelElement.modelType) {
switch (submodelElement.modelType) {
case 'Property':
if (!submodelElement.value) return '';
return (
submodelElement.value +
(this.unitSuffix(submodelElement) ? ' ' + this.unitSuffix(submodelElement) : '')
);
case 'MultiLanguageProperty': {
const valueEn = submodelElement.value.find((value: any) => {
return value && value.language === 'en' && value.text !== '';
});
const valueDe = submodelElement.value.find((value: any) => {
return value && value.language === 'de' && value.text !== '';
});
if (valueEn && valueEn.text) return valueEn.text;
if (valueDe && valueDe.text) return valueDe.text;
return '';
}
case 'File':
case 'Blob':
if (submodelElement.value.startsWith('http')) return submodelElement.value;
return submodelElement.path + '/attachment';
case 'Operation': // TODO
case 'ReferenceElement': // TODO
case 'Range': // TODO
case 'Entity': // TODO
case 'RelationshipElement': // TODO
case 'AnnotatedRelationshipElement': // TODO
return '';
default:
return '';
}
}
return '';
},

// Extract the right endpoints href from a descriptor
extractEndpointHref(descriptor: any, interfaceShortName: string): string {
const interfaceShortNames = [
Expand Down

0 comments on commit d921ca5

Please sign in to comment.