Skip to content

Commit

Permalink
Work on AASList / AASListDetails / AASTreeview / SubmodelList (#135)
Browse files Browse the repository at this point in the history
* Not closeable DetailsCard anymore

* Add ENV variable singleAasRedirect

* Add redirect if no existing aas path in URL

* Adapt AASList/AASListDetails for ENV singleAasRedirect

* Harmonize AASUpload button with AASListRefresh button

* Avoid nested v-card for AASListDetails

* Add check for valid URL

* Fix background color of v-main

* Fix initial config.json

* delete console.logs

* Simplify dispatching AAS

* Add missing this.aasStore.dispatchLoadingState(false);

* Fixes height calculations in AASLIst

* Introduce ENV variable singleAas + integrate PR #147

* Fix response data error in App.vue

* Add ReferenceType to ReferenceElement.vue

* Adaption AASListDetails for missing assetKind of assetInformation

* Work on Reference checks and jumps

* Harmonize globalAssetId design of Entity with design of AssetInformation

* Add TODO regarding checkReference

* Comment console.log

* Precises variable names

* Comment console.logs

* Harmonize/Update ReferenceElement & RelationshipElement

* Adapt .length checks

* Functions for AAS and SM handling

* Adds mobile support to 404 page

* Fix jumping to SME in SML

* Add check for available SME in SMC für jumping to SME in SMC

* Fixes error in SMEHandling were CDRepoURL wasn't accessible

* Fix checkReference, fix jumps

---------

Co-authored-by: aaron Zielstorff <[email protected]>
  • Loading branch information
seicke and aaronzi authored Dec 17, 2024
1 parent 4cee279 commit 568949e
Show file tree
Hide file tree
Showing 37 changed files with 1,638 additions and 926 deletions.
8 changes: 8 additions & 0 deletions aas-web-ui/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ if [ -n "$ENDPOINT_CONFIG_AVAILABLE" ]; then
jq '.endpointConfigAvailable = env.ENDPOINT_CONFIG_AVAILABLE' /usr/src/app/dist/config.json > /tmp/config.json && mv /tmp/config.json /usr/src/app/dist/config.json
fi

if [ -n "$SINGLE_AAS" ]; then
jq '.singleAas = env.SINGLE_AAS' /usr/src/app/dist/config.json > /tmp/config.json && mv /tmp/config.json /usr/src/app/dist/config.json
fi

if [ -n "$SINGLE_AAS_REDIRECT" ]; then
jq '.singleAasRedirect = env.SINGLE_AAS_REDIRECT' /usr/src/app/dist/config.json > /tmp/config.json && mv /tmp/config.json /usr/src/app/dist/config.json
fi

if [ -n "$BASE_PATH" ]; then
echo "====================="
echo "BASE_PATH: $BASE_PATH"
Expand Down
4 changes: 3 additions & 1 deletion aas-web-ui/public/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@
"keycloakUrl": "",
"keycloakRealm": "",
"keycloakClientId": "",
"endpointConfigAvailable": true
"endpointConfigAvailable": true,
"singleAas": false,
"singleAasRedirect": ""
}
37 changes: 20 additions & 17 deletions aas-web-ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,9 @@
import RequestHandling from '@/mixins/RequestHandling';
import SubmodelElementHandling from '@/mixins/SubmodelElementHandling';
import { useAASStore } from '@/store/AASDataStore';
import { useEnvStore } from '@/store/EnvironmentStore';
import { useNavigationStore } from '@/store/NavigationStore';
interface AASType {
endpoints: Array<{
protocolInformation: {
href: string;
};
interface: string;
}>;
}
export default defineComponent({
name: 'App',
components: {
Expand All @@ -46,16 +38,18 @@
const aasStore = useAASStore();
const route = useRoute();
const router = useRouter();
const envStore = useEnvStore();
return {
navigationStore, // NavigationStore Object
aasStore, // AASStore Object
route, // Route Object
router, // Router Object
envStore, // EnvironmentStore Object
};
},
mounted() {
async mounted() {
let mobile = this.$vuetify.display.mobile;
// include IPad as mobile device
if (this.$vuetify.display.platform.mac && this.$vuetify.display.platform.touch) {
Expand All @@ -76,6 +70,20 @@
const aasEndpoint = searchParams.get('aas');
const submodelElementPath = searchParams.get('path');
// Ensure available aasEndpoint query parameter
if (
this.envStore.singleAas &&
(aasEndpoint === null || aasEndpoint === undefined || aasEndpoint.trim() === '')
) {
if (this.envStore.getSingleAasRedirect) {
window.location.replace(this.envStore.getSingleAasRedirect);
return;
} else if (this.route.name !== '404NotFound404') {
this.router.push({ name: 'NotFound404' });
return;
}
}
// check which platform is used and change the fitting view
if (mobile) {
if (this.route.name === 'MainWindow') {
Expand Down Expand Up @@ -117,12 +125,7 @@
if (aasEndpoint) {
// console.log('AAS Query is set: ', aasEndpoint);
let aas = {} as AASType;
let endpoints = [];
endpoints.push({ protocolInformation: { href: aasEndpoint }, interface: 'AAS-3.0' });
aas.endpoints = endpoints;
// dispatch the AAS set by the URL to the store
this.aasStore.dispatchSelectedAAS(aas);
await this.fetchAndDispatchAas(aasEndpoint);
}
if (aasEndpoint && submodelElementPath) {
Expand All @@ -142,7 +145,7 @@
this.aasStore.dispatchNode(response.data); // set the updatedNode in the AASStore
} else {
// execute if the Request failed
if (Object.keys(response.data).length == 0) {
if (response?.data && Object.keys(response?.data).length === 0) {
// don't copy the static SubmodelElement Data if no Node is selected or Node is invalid
this.navigationStore.dispatchSnackbar({
status: true,
Expand Down
2 changes: 1 addition & 1 deletion aas-web-ui/src/UserPlugins/HelloWorldPlugin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
methods: {
// Function to initialize the HelloWorld-Plugin
initializePlugin() {
if (Object.keys(this.submodelElementData).length == 0) {
if (Object.keys(this.submodelElementData).length === 0) {
this.pluginData = {}; // Reset the Plugin Data when no Node is selected
return;
}
Expand Down
127 changes: 43 additions & 84 deletions aas-web-ui/src/components/AASTreeview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
<v-col cols="auto">
<span>AAS Treeview</span>
</v-col>
<v-col v-if="nameToDisplay(SelectedAAS)" cols="auto" class="pl-1 pt-2">
<v-col v-if="nameToDisplay(selectedAAS)" cols="auto" class="pl-1 pt-2">
<v-chip size="x-small" color="primary" label border>{{
'AAS: ' + nameToDisplay(SelectedAAS)
'AAS: ' + nameToDisplay(selectedAAS)
}}</v-chip>
</v-col>
</v-row>
Expand All @@ -29,14 +29,20 @@
</template>
</v-list-item>
</div>
<!-- TODO: Replace with Vuetify Treeview Component when it get's released in Q1 2023 -->
<VTreeview
v-for="item in submodelData"
v-else
:key="item.id"
class="root"
:item="item"
:depth="0"></VTreeview>
<template v-else>
<v-empty-state
v-if="selectedAAS && Object.keys(selectedAAS).length > 0 && submodelData.length === 0"
title="No existing Submodels"
text="The selected AAS does not contain any Submodels"
class="text-divider"></v-empty-state>
<!-- TODO: Replace with Vuetify Treeview Component when it get's released in Q1 2023 -->
<VTreeview
v-for="item in submodelData"
:key="item.id"
class="root"
:item="item"
:depth="0"></VTreeview>
</template>
</v-card-text>
</v-card>
</v-container>
Expand Down Expand Up @@ -81,15 +87,10 @@
computed: {
// get selected AAS from Store
SelectedAAS() {
selectedAAS() {
return this.aasStore.getSelectedAAS;
},
// get the trigger for AAS selection from Store
triggerAAS() {
return this.navigationStore.getTriggerAASSelected;
},
// gets loading State from Store
loading() {
return this.aasStore.getLoadingState;
Expand All @@ -116,8 +117,7 @@
},
watch: {
// initialize Treeview when AAS gets selected
triggerAAS() {
selectedAAS() {
this.initializeTree();
},
Expand Down Expand Up @@ -154,74 +154,32 @@
},
methods: {
// Function to get the Submodels from the selected AAS (retrieved from the AAS with the provided endpoint)
initializeTree() {
// console.log('Initialize Treeview', this.initialUpdate, this.initialNode);
async initializeTree() {
// console.log('Initialize Treeview', this.SelectedAAS, this.initialUpdate, this.initialNode);
// return if no endpoints are available
if (!this.SelectedAAS || !this.SelectedAAS.endpoints || this.SelectedAAS.endpoints.length === 0) {
// TODO: this seems to get executed on reload with a selected AAS
if (!this.selectedAAS || !this.selectedAAS.endpoints || this.selectedAAS.endpoints.length === 0) {
// this.navigationStore.dispatchSnackbar({ status: true, timeout: 4000, color: 'error', btnColor: 'buttonText', text: 'AAS with no (valid) Endpoint selected!' });
this.submodelData = [];
return;
}
if (this.loading && !this.initialUpdate) return; // return if loading state is true -> prevents multiple requests
this.aasStore.dispatchLoadingState(true); // set loading state to true
this.submodelData = []; // reset Treeview Data
// retrieve AAS from endpoint
const shellHref = this.extractEndpointHref(this.selectedAAS, 'AAS-3.0');
let path = shellHref;
let context = 'retrieving AAS Data';
let disableMessage = false;
this.getRequest(path, context, disableMessage)
.then(async (response: any) => {
if (response.success) {
// execute if the Request was successful
try {
let AAS = response.data;
AAS.endpoints = this.SelectedAAS.endpoints;
this.aasStore.dispatchSelectedAAS(AAS); // dispatch the selected AAS to the Store
if (!AAS.submodels) {
throw new Error('No Submodels found in AAS!');
}
// request submodels from the retrieved AAS (top layer of the Treeview)
let submodelData = await this.requestSubmodels(AAS.submodels);
// set the isActive prop of the initialNode if it exists and the initialUpdate flag is set
if (this.initialUpdate && this.initialNode) {
let expandedSubmodelData = this.expandTree(submodelData, this.initialNode); // Update the Treeview to expand until the initially set node is reached
// this.updateNode(this.initialNode); // set the isActive prop of the initialNode to true
this.initialUpdate = false;
this.initialNode = {};
// console.log('Expanded Treeview Data: ', expandedSubmodelData)
this.submodelData = expandedSubmodelData; // set the Treeview Data
} else {
this.submodelData = submodelData; // set the Treeview Data
// console.log('Treeview Data: ', this.submodelData)
}
} catch (error: any) {
// console.error('Error while parsing the Submodel References: ', error);
const errorMessage = error.message;
const errorStack = error.stack;
const errorLocation = errorStack ? errorStack.split('\n')[1] : '';
this.navigationStore.dispatchSnackbar({
status: true,
timeout: 60000,
color: 'error',
btnColor: 'buttonText',
baseError: 'Error while parsing the Submodel References!',
extendedError: `Error: ${errorMessage}\nLocation: ${errorLocation.trim()}`,
});
} finally {
this.aasStore.dispatchLoadingState(false);
}
} else {
// execute if the Request failed
this.submodelData = [];
this.aasStore.dispatchLoadingState(false);
}
})
.catch(() => {
this.aasStore.dispatchLoadingState(false);
});
if (this.selectedAAS.submodels) {
let submodelData = await this.requestSubmodels(this.selectedAAS.submodels);
// set the isActive prop of the initialNode if it exists and the initialUpdate flag is set
if (this.initialUpdate && this.initialNode) {
let expandedSubmodelData = this.expandTree(submodelData, this.initialNode); // Update the Treeview to expand until the initially set node is reached
// this.updateNode(this.initialNode); // set the isActive prop of the initialNode to true
this.initialUpdate = false;
this.initialNode = {};
this.submodelData = expandedSubmodelData;
} else {
this.submodelData = submodelData;
}
} else {
this.submodelData = [];
}
this.aasStore.dispatchLoadingState(false);
},
// Function to request all Submodels for the selected AAS
Expand All @@ -231,8 +189,9 @@
// retrieve endpoint for submodel from submodel registry
// console.log('SubmodelRef: ', submodelRef, ' Submodel Registry: ', this.submodelRegistryServerURL);
// check if submodelRegistryURL includes "/submodel-descriptors" and add id if not (backward compatibility)
if (!this.submodelRegistryURL.includes('/submodel-descriptors')) {
this.submodelRegistryURL += '/submodel-descriptors';
let submodelRegistryURL = this.submodelRegistryURL;
if (!submodelRegistryURL.includes('/submodel-descriptors')) {
submodelRegistryURL += '/submodel-descriptors';
}
const submodelId = submodelRef.keys[0].value;
let path = this.submodelRegistryURL + '/' + this.URLEncode(submodelId);
Expand Down Expand Up @@ -439,9 +398,9 @@
// Function to initialize the treeview with route params
initTreeWithRouteParams() {
// check if the SelectedAAS is already set in the Store and initialize the Treeview if so
if (this.SelectedAAS && this.SelectedAAS.endpoints && this.SelectedAAS.endpoints.length > 0) {
// console.log('init Tree from Route Params: ', this.SelectedAAS);
// check if the selectedAAS is already set in the Store and initialize the Treeview if so
if (this.selectedAAS && this.selectedAAS.endpoints && this.selectedAAS.endpoints.length > 0) {
// console.log('init Tree from Route Params: ', this.selectedAAS);
this.initializeTree();
}
Expand Down
Loading

0 comments on commit 568949e

Please sign in to comment.