Skip to content

Commit b3f69a6

Browse files
authored
Adds Qualifiers to the AAS Editor (eclipse-basyx#1066)
1 parent 0bcd4bc commit b3f69a6

File tree

15 files changed

+408
-13
lines changed

15 files changed

+408
-13
lines changed

aas-web-ui/src/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ declare module 'vue' {
9999
Property: typeof import('./components/SubmodelElements/Property.vue')['default']
100100
PropertyForm: typeof import('./components/EditorComponents/SubmodelElements/PropertyForm.vue')['default']
101101
QualifierElement: typeof import('./components/UIComponents/QualifierElement.vue')['default']
102+
QualifierInput: typeof import('./components/EditorComponents/InputTypes/QualifierInput.vue')['default']
102103
Range: typeof import('./components/SubmodelElements/Range.vue')['default']
103104
RangeForm: typeof import('./components/EditorComponents/SubmodelElements/RangeForm.vue')['default']
104105
RangeInput: typeof import('./components/EditorComponents/InputTypes/RangeInput.vue')['default']
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<template>
2+
<v-sheet v-for="(qualifier, index) in qualifiersValue ?? []" :key="index" class="mb-4" border rounded>
3+
<v-card-actions class="bg-cardHeader">
4+
<div class="ml-2">Qualifier {{ index + 1 }}</div>
5+
<v-spacer></v-spacer>
6+
<v-btn
7+
prepend-icon="mdi-delete"
8+
variant="text"
9+
text="Remove Qualifier"
10+
class="text-none"
11+
@click="removeQualifier(index)"></v-btn>
12+
</v-card-actions>
13+
<v-divider></v-divider>
14+
<v-card-text class="pt-7">
15+
<v-row align="center">
16+
<v-col class="py-0">
17+
<TextInput v-model="qualifier.type" label="Type" />
18+
</v-col>
19+
</v-row>
20+
21+
<v-row align="center">
22+
<v-col class="py-0">
23+
<SelectInput v-model="qualifier.valueType" label="Value Type" type="dataType" :clearable="false" />
24+
</v-col>
25+
</v-row>
26+
27+
<v-row align="center">
28+
<v-col class="py-0">
29+
<TextInput v-model="qualifier.value" label="Value" />
30+
</v-col>
31+
</v-row>
32+
33+
<v-row align="center">
34+
<v-col class="py-0">
35+
<SelectInput v-model="qualifier.kind" label="Kind" type="qualifierKind" :clearable="true" />
36+
</v-col>
37+
</v-row>
38+
39+
<v-row align="center">
40+
<v-col class="py-0">
41+
<v-divider></v-divider>
42+
<v-list-item class="pl-0 pt-0">
43+
<template #title>
44+
<div class="text-subtitle-2">Semantic ID</div>
45+
</template>
46+
</v-list-item>
47+
<v-btn
48+
v-if="qualifier.semanticId === null"
49+
color="primary"
50+
prepend-icon="mdi-plus"
51+
variant="outlined"
52+
text="Add Semantic ID"
53+
class="text-none mt-1 mb-4"
54+
@click="addSemanticId(index)"></v-btn>
55+
<ReferenceInput v-else v-model="qualifier.semanticId" label="Semantic ID" :no-header="true" />
56+
</v-col>
57+
</v-row>
58+
59+
<v-row align="center">
60+
<v-col class="py-0">
61+
<v-divider></v-divider>
62+
<v-list-item class="pl-0 pt-0">
63+
<template #title>
64+
<div class="text-subtitle-2">Value ID</div>
65+
</template>
66+
</v-list-item>
67+
<v-btn
68+
v-if="qualifier.valueId === null"
69+
color="primary"
70+
prepend-icon="mdi-plus"
71+
variant="outlined"
72+
text="Add Value ID"
73+
class="text-none mt-1 mb-4"
74+
@click="addValueId(index)"></v-btn>
75+
<ReferenceInput v-else v-model="qualifier.valueId" label="Value ID" :no-header="true" />
76+
</v-col>
77+
</v-row>
78+
</v-card-text>
79+
</v-sheet>
80+
81+
<v-btn
82+
color="primary"
83+
prepend-icon="mdi-plus"
84+
variant="outlined"
85+
text="Add Qualifier"
86+
class="text-none mt-1 mb-4"
87+
@click="addQualifier"></v-btn>
88+
</template>
89+
90+
<script setup lang="ts">
91+
import { types as aasTypes } from '@aas-core-works/aas-core3.1-typescript';
92+
import { ref, watch } from 'vue';
93+
94+
const props = defineProps<{
95+
modelValue: Array<aasTypes.Qualifier> | null;
96+
}>();
97+
98+
const emit = defineEmits<{
99+
(event: 'update:modelValue', value: Array<aasTypes.Qualifier> | null): void;
100+
}>();
101+
102+
const qualifiersValue = ref<Array<aasTypes.Qualifier> | null>(props.modelValue);
103+
104+
watch(
105+
qualifiersValue,
106+
(newValue) => {
107+
emit('update:modelValue', newValue);
108+
},
109+
{ deep: true }
110+
);
111+
112+
watch(
113+
() => props.modelValue,
114+
(newValue) => {
115+
qualifiersValue.value = newValue;
116+
}
117+
);
118+
119+
function addQualifier(): void {
120+
if (qualifiersValue.value === null) {
121+
qualifiersValue.value = [];
122+
}
123+
qualifiersValue.value.push(new aasTypes.Qualifier('', aasTypes.DataTypeDefXsd.String));
124+
}
125+
126+
function removeQualifier(index: number): void {
127+
if (qualifiersValue.value === null) {
128+
return;
129+
}
130+
131+
qualifiersValue.value.splice(index, 1);
132+
if (qualifiersValue.value.length === 0) {
133+
qualifiersValue.value = null;
134+
}
135+
}
136+
137+
function addSemanticId(index: number): void {
138+
if (qualifiersValue.value === null || !qualifiersValue.value[index]) {
139+
return;
140+
}
141+
142+
qualifiersValue.value[index].semanticId = new aasTypes.Reference(aasTypes.ReferenceTypes.ExternalReference, [
143+
new aasTypes.Key(aasTypes.KeyTypes.GlobalReference, ''),
144+
]);
145+
}
146+
147+
function addValueId(index: number): void {
148+
if (qualifiersValue.value === null || !qualifiersValue.value[index]) {
149+
return;
150+
}
151+
152+
qualifiersValue.value[index].valueId = new aasTypes.Reference(aasTypes.ReferenceTypes.ExternalReference, [
153+
new aasTypes.Key(aasTypes.KeyTypes.GlobalReference, ''),
154+
]);
155+
}
156+
</script>

aas-web-ui/src/components/EditorComponents/InputTypes/SelectInput.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
dataType: aasTypes.DataTypeDefXsd;
2222
elementType: aasTypes.AasSubmodelElements;
2323
entityType: aasTypes.EntityType;
24+
qualifierKind: aasTypes.QualifierKind;
2425
};
2526
2627
type ValueType<T extends keyof ValueMap> = ValueMap[T];
@@ -96,6 +97,12 @@
9697
{ title: 'Co-Managed Entity', value: aasTypes.EntityType.CoManagedEntity },
9798
{ title: 'Self-Managed Entity', value: aasTypes.EntityType.SelfManagedEntity },
9899
];
100+
case 'qualifierKind':
101+
return [
102+
{ title: 'ValueQualifier', value: aasTypes.QualifierKind.ValueQualifier },
103+
{ title: 'ConceptQualifier', value: aasTypes.QualifierKind.ConceptQualifier },
104+
{ title: 'TemplateQualifier', value: aasTypes.QualifierKind.TemplateQualifier },
105+
];
99106
default:
100107
return [];
101108
}

aas-web-ui/src/components/EditorComponents/SubmodelElements/AnnotatedRelationshipElementForm.vue

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,15 @@
107107
</v-row>
108108
</v-expansion-panel-text>
109109
</v-expansion-panel>
110+
<!-- Qualifiers -->
111+
<v-expansion-panel class="border-s-thin border-e-thin" :class="bordersToShow(3)">
112+
<v-expansion-panel-title>Qualifiers</v-expansion-panel-title>
113+
<v-expansion-panel-text>
114+
<QualifierInput v-model="qualifiers" />
115+
</v-expansion-panel-text>
116+
</v-expansion-panel>
110117
<!-- Data Specification -->
111-
<v-expansion-panel class="border-b-thin border-s-thin border-e-thin" :class="bordersToShow(3)">
118+
<v-expansion-panel class="border-b-thin border-s-thin border-e-thin" :class="bordersToShow(4)">
112119
<v-expansion-panel-title>Data Specification</v-expansion-panel-title>
113120
<v-expansion-panel-text>
114121
<span class="text-subtitleText text-subtitle-2">Coming soon!</span>
@@ -168,6 +175,7 @@
168175
const annotatedRelationshipElementCategory = ref<string | null>(null);
169176
170177
const semanticId = ref<aasTypes.Reference | null>(null);
178+
const qualifiers = ref<Array<aasTypes.Qualifier> | null>(null);
171179
const firstReference = ref<aasTypes.Reference | null>(null);
172180
const secondReference = ref<aasTypes.Reference | null>(null);
173181
@@ -228,6 +236,14 @@
228236
if (openPanels.value.includes(2) || openPanels.value.includes(3)) {
229237
border += ' border-t-thin';
230238
}
239+
if (openPanels.value.includes(3) || openPanels.value.includes(4)) {
240+
border += ' border-b-thin';
241+
}
242+
break;
243+
case 4:
244+
if (openPanels.value.includes(3) || openPanels.value.includes(4)) {
245+
border += ' border-t-thin';
246+
}
231247
break;
232248
}
233249
return border;
@@ -278,6 +294,7 @@
278294
}
279295
280296
annotatedRelationshipElementObject.value.category = annotatedRelationshipElementCategory.value;
297+
annotatedRelationshipElementObject.value.qualifiers = qualifiers.value;
281298
282299
const verificationResult = verifyForEditor(annotatedRelationshipElementObject.value, { maxErrors: 10 });
283300
if (!verificationResult.isValid) {
@@ -378,6 +395,7 @@
378395
description.value = null;
379396
annotatedRelationshipElementCategory.value = null;
380397
semanticId.value = null;
398+
qualifiers.value = null;
381399
firstReference.value = null;
382400
secondReference.value = null;
383401
openPanels.value = [0, 1];
@@ -404,6 +422,7 @@
404422
description.value = annotatedRelationshipElementObject.value.description ?? null;
405423
annotatedRelationshipElementCategory.value = annotatedRelationshipElementObject.value.category ?? null;
406424
semanticId.value = annotatedRelationshipElementObject.value.semanticId ?? null;
425+
qualifiers.value = annotatedRelationshipElementObject.value.qualifiers ?? null;
407426
firstReference.value = annotatedRelationshipElementObject.value.first ?? null;
408427
secondReference.value = annotatedRelationshipElementObject.value.second ?? null;
409428
}

aas-web-ui/src/components/EditorComponents/SubmodelElements/BlobForm.vue

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,15 @@
9494
</v-row>
9595
</v-expansion-panel-text>
9696
</v-expansion-panel>
97+
<!-- Qualifiers -->
98+
<v-expansion-panel class="border-s-thin border-e-thin" :class="bordersToShow(3)">
99+
<v-expansion-panel-title>Qualifiers</v-expansion-panel-title>
100+
<v-expansion-panel-text>
101+
<QualifierInput v-model="qualifiers" />
102+
</v-expansion-panel-text>
103+
</v-expansion-panel>
97104
<!-- Data Specification -->
98-
<v-expansion-panel class="border-b-thin border-s-thin border-e-thin" :class="bordersToShow(3)">
105+
<v-expansion-panel class="border-b-thin border-s-thin border-e-thin" :class="bordersToShow(4)">
99106
<v-expansion-panel-title>Data Specification</v-expansion-panel-title>
100107
<v-expansion-panel-text>
101108
<span class="text-subtitleText text-subtitle-2">Coming soon!</span>
@@ -166,6 +173,7 @@ usage of the 'Enter' key, make sure to edit the keyDown/keyUp method to not exec
166173
const contentType = ref<string>('application/unknown');
167174
168175
const semanticId = ref<aasTypes.Reference | null>(null);
176+
const qualifiers = ref<Array<aasTypes.Qualifier> | null>(null);
169177
170178
const errors = ref<Map<string, string>>(new Map());
171179
@@ -222,6 +230,14 @@ usage of the 'Enter' key, make sure to edit the keyDown/keyUp method to not exec
222230
break;
223231
case 3:
224232
if (openPanels.value.includes(2) || openPanels.value.includes(3)) {
233+
border += ' border-t-thin';
234+
}
235+
if (openPanels.value.includes(3) || openPanels.value.includes(4)) {
236+
border += ' border-b-thin';
237+
}
238+
break;
239+
case 4:
240+
if (openPanels.value.includes(3) || openPanels.value.includes(4)) {
225241
border += 'border-t-thin';
226242
}
227243
break;
@@ -237,6 +253,7 @@ usage of the 'Enter' key, make sure to edit the keyDown/keyUp method to not exec
237253
blobContent.value = null;
238254
contentType.value = 'application/unknown';
239255
semanticId.value = null;
256+
qualifiers.value = null;
240257
openPanels.value = [0, 1];
241258
}
242259
@@ -262,6 +279,7 @@ usage of the 'Enter' key, make sure to edit the keyDown/keyUp method to not exec
262279
blobContent.value = blobObject.value.value ?? null;
263280
contentType.value = blobObject.value.contentType ?? 'application/unknown';
264281
semanticId.value = blobObject.value.semanticId ?? null;
282+
qualifiers.value = blobObject.value.qualifiers ?? null;
265283
}
266284
}
267285
@@ -317,6 +335,7 @@ usage of the 'Enter' key, make sure to edit the keyDown/keyUp method to not exec
317335
}
318336
319337
blobObject.value.category = blobCategory.value;
338+
blobObject.value.qualifiers = qualifiers.value;
320339
321340
const verificationResult = verifyForEditor(blobObject.value, { maxErrors: 10 });
322341
if (!verificationResult.isValid) {

aas-web-ui/src/components/EditorComponents/SubmodelElements/CollectionForm.vue

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,15 @@
7676
</v-row>
7777
</v-expansion-panel-text>
7878
</v-expansion-panel>
79+
<!-- Qualifiers -->
80+
<v-expansion-panel class="border-s-thin border-e-thin" :class="bordersToShow(2)">
81+
<v-expansion-panel-title>Qualifiers</v-expansion-panel-title>
82+
<v-expansion-panel-text>
83+
<QualifierInput v-model="qualifiers" />
84+
</v-expansion-panel-text>
85+
</v-expansion-panel>
7986
<!-- Data Specification -->
80-
<v-expansion-panel class="border-b-thin border-s-thin border-e-thin" :class="bordersToShow(2)">
87+
<v-expansion-panel class="border-b-thin border-s-thin border-e-thin" :class="bordersToShow(3)">
8188
<v-expansion-panel-title>Data Specification</v-expansion-panel-title>
8289
<v-expansion-panel-text>
8390
<span class="text-subtitleText text-subtitle-2">Coming soon!</span>
@@ -138,6 +145,7 @@
138145
const smcCategory = ref<string | null>(null);
139146
140147
const semanticId = ref<aasTypes.Reference | null>(null);
148+
const qualifiers = ref<Array<aasTypes.Qualifier> | null>(null);
141149
//const smcValue = ref<string | null>(null);
142150
143151
const errors = ref<Map<string, string>>(new Map());
@@ -189,6 +197,14 @@
189197
if (openPanels.value.includes(1) || openPanels.value.includes(2)) {
190198
border += ' border-t-thin';
191199
}
200+
if (openPanels.value.includes(2) || openPanels.value.includes(3)) {
201+
border += ' border-b-thin';
202+
}
203+
break;
204+
case 3:
205+
if (openPanels.value.includes(2) || openPanels.value.includes(3)) {
206+
border += ' border-t-thin';
207+
}
192208
break;
193209
}
194210
return border;
@@ -235,6 +251,7 @@
235251
}
236252
237253
smcObject.value.category = smcCategory.value;
254+
smcObject.value.qualifiers = qualifiers.value;
238255
239256
const verificationResult = verifyForEditor(smcObject.value, { maxErrors: 10 });
240257
if (!verificationResult.isValid) {
@@ -331,6 +348,7 @@
331348
description.value = null;
332349
smcCategory.value = null;
333350
semanticId.value = null;
351+
qualifiers.value = null;
334352
openPanels.value = [0];
335353
}
336354
@@ -353,6 +371,7 @@
353371
description.value = smcObject.value.description ?? null;
354372
smcCategory.value = smcObject.value.category ?? null;
355373
semanticId.value = smcObject.value.semanticId ?? null;
374+
qualifiers.value = smcObject.value.qualifiers ?? null;
356375
}
357376
}
358377
</script>

0 commit comments

Comments
 (0)