11<template >
22 <AddDialogContainer :elementType =" element_type" @close =" $emit('close')" >
33 <form class =" dialog-form" >
4- <span >Select MTP/AAS: </span >
4+ <span >Select MTP/AAS:</span >
55 <div class =" row-flex" >
66 <select v-model =" current_file_type" name =" FileType" id =" fileTypeSelect"
7- @change =" readServerFiles(current_file_type)" >
8- <option value =" " >Select file type</option >
7+ :disabled = " isProcessingFile " @change =" readServerFiles(current_file_type)" >
8+ <!-- < option value="">Select file type</option> -- >
99 <option value =" mtp" >MTP Files</option >
1010 <option value =" aas" >AAS Files</option >
1111 </select >
12- <button type =" button" class =" icon-btn" @click =" readServerFiles(current_file_type)" title =" Reload files" >
12+ <button type =" button" class =" icon-btn" @click =" readServerFiles(current_file_type)" title =" Reload files"
13+ :disabled =" isProcessingFile || isLoadingFiles" >
1314 <span class =" reload" >↻ ; </span >
1415 </button >
1516 </div >
1617 <div v-if =" current_file_type && serverFiles.length > 0" >
1718 <label for =" file_select" >Select File: </label >
18- <select id =" file_select" v-model =" current_file_name" name =" file" >
19+ <select id =" file_select" v-model =" current_file_name" name =" file" :disabled = " isProcessingFile " >
1920 <option v-for =" item in serverFiles" :value =" item" :key =" item" >{{ item }}</option >
2021 </select >
2122 <div class =" row-flex" >
2627 </button >
2728 </div >
2829 <div v-if =" isProcessingFile" class =" processing-progress" >
29- <div class =" progress-bar" >
30- <div class =" progress-fill" ></div >
30+ <div class =" progress-bar" role =" progressbar" aria-valuemin =" 0" aria-valuemax =" 100"
31+ :aria-valuenow =" progressPercent" >
32+ <div class =" progress-fill" :style =" { width: `${progressPercent}%` }" ></div >
3133 </div >
3234 <p >{{ processingProgress }}</p >
35+ <div class =" progress-meta" >
36+ <span >{{ progressCounterText }}</span >
37+ <span >{{ progressPercent }}%</span >
38+ </div >
3339 </div >
3440 </div >
3541 <div v-if =" current_file_type" class =" uploader-section" >
3642 <span >Upload new {{ current_file_type.toUpperCase() }} file:</span >
3743 <div >
3844 <input ref =" fileInput" @change =" onFileChange" type =" file"
39- :accept =" getFileAcceptTypes(current_file_type)" style =" width :100% ;" />
45+ :accept =" getFileAcceptTypes(current_file_type)" style =" width :100% ;"
46+ :disabled =" isProcessingFile || isLoadingFiles" />
4047 <div class =" row-flex" style =" margin-top : 8px ;" >
4148 <button class =" button" type =" button" @click =" uploadFileToServer(current_file_type)"
42- :disabled =" isLoadingFiles" >
49+ :disabled =" isLoadingFiles || isProcessingFile " >
4350 <span v-if =" isLoadingFiles" >Uploading...</span >
4451 <span v-else >Upload {{ current_file_type.toUpperCase() }} to Server</span >
4552 </button >
5158</template >
5259
5360<script setup>
54- import { ref , toRefs } from ' vue' ;
61+ import { computed , onMounted , ref , toRefs } from ' vue' ;
5562import axios from ' axios' ;
5663import AddDialogContainer from ' @/shell/ui/sidebar/AddDialogContainer.vue' ;
5764
@@ -62,25 +69,71 @@ const { element_type } = toRefs(props);
6269
6370const emit = defineEmits ([' close' , ' add' ]);
6471
65- const current_file_type = ref (' ' );
72+ const current_file_type = ref (' mtp ' );
6673const current_file_name = ref (' ' );
6774const serverFiles = ref ([]);
6875const fileInput = ref (null );
6976
7077const isLoadingFiles = ref (false );
7178const isProcessingFile = ref (false );
7279const processingProgress = ref (' ' );
80+ const progressTotalProcedures = ref (0 );
81+ const progressLoadedProcedures = ref (0 );
82+ const progressParseDone = ref (false );
7383
7484const client = axios .create ({
7585 baseURL: ' '
7686});
7787
88+ const progressPercent = computed (() => {
89+ const totalUnits = progressTotalProcedures .value + 1 ;
90+ const doneUnits = (progressParseDone .value ? 1 : 0 ) + progressLoadedProcedures .value ;
91+ const rawPercent = Math .round ((doneUnits / totalUnits) * 100 );
92+ if (! Number .isFinite (rawPercent)) return 0 ;
93+ return Math .max (0 , Math .min (100 , rawPercent));
94+ });
95+
96+ const progressCounterText = computed (
97+ () => ` ${ progressLoadedProcedures .value } /${ progressTotalProcedures .value } `
98+ );
99+
100+ onMounted (() => {
101+ readServerFiles (current_file_type .value );
102+ });
103+
78104function getFileNameWithoutExtension (name ) {
79105 if (! name || typeof name !== ' string' ) return ' Imported Elements' ;
80106 const normalized = name .replace (/ \\ / g , ' /' ).split (' /' ).pop () || ' ' ;
81107 return normalized .replace (/ \. [^ /. ] + $ / , ' ' ) || normalized || ' Imported Elements' ;
82108}
83109
110+ function resetProgressState () {
111+ progressTotalProcedures .value = 0 ;
112+ progressLoadedProcedures .value = 0 ;
113+ progressParseDone .value = false ;
114+ processingProgress .value = ' ' ;
115+ }
116+
117+ function initializeProgress (totalProcedures ) {
118+ progressTotalProcedures .value = Math .max (0 , Number (totalProcedures) || 0 );
119+ progressLoadedProcedures .value = 0 ;
120+ progressParseDone .value = false ;
121+ }
122+
123+ function markParseDone () {
124+ progressParseDone .value = true ;
125+ }
126+
127+ function markProcedureLoaded () {
128+ if (progressLoadedProcedures .value < progressTotalProcedures .value ) {
129+ progressLoadedProcedures .value += 1 ;
130+ }
131+ }
132+
133+ function setProgressMessage (message ) {
134+ processingProgress .value = message || ' ' ;
135+ }
136+
84137async function readServerFiles (fileType ) {
85138 if (! fileType) {
86139 serverFiles .value = [];
@@ -146,20 +199,25 @@ async function addElementsFromFile(fileType, fileName) {
146199 }
147200
148201 isProcessingFile .value = true ;
149- processingProgress .value = ' Parsing file...' ;
202+ initializeProgress (0 );
203+ setProgressMessage (' Parsing file...' );
150204
151205 try {
152- processingProgress . value = ' Fetching process data...' ;
206+ setProgressMessage ( ' Fetching process data...' ) ;
153207 const response = await client .get (` /${ fileType} /${ encodeURIComponent (fileName)} /parse` );
154208 console .log (` Parsed ${ fileType} result:` , response .data );
155209
156210 if (fileType === ' mtp' && Array .isArray (response .data .procs )) {
157- const mtpProcesses = [];
158-
159- processingProgress .value = ' Processing processes and equipment data...' ;
211+ const procedures = response .data .procs ;
212+ initializeProgress (procedures .length );
213+ markParseDone ();
214+ if (procedures .length > 0 ) {
215+ setProgressMessage (` Loading procedures ${ progressCounterText .value } ...` );
216+ } else {
217+ setProgressMessage (' No procedures found.' );
218+ }
160219
161- const equipmentPromises = response .data .procs .map (async (proc , index ) => {
162- processingProgress .value = ` Fetching equipment data for ${ proc .name } (${ index + 1 } /${ response .data .procs .length } )...` ;
220+ const equipmentPromises = procedures .map (async (proc ) => {
163221 try {
164222 const equipmentResponse = await client .get (` /${ fileType} /${ encodeURIComponent (fileName)} /master-recipe-equipment/${ encodeURIComponent (proc .name )} ` );
165223 return {
@@ -172,14 +230,16 @@ async function addElementsFromFile(fileType, fileName) {
172230 proc,
173231 equipmentData: null
174232 };
233+ } finally {
234+ markProcedureLoaded ();
235+ setProgressMessage (` Loading procedures ${ progressCounterText .value } ...` );
175236 }
176237 });
177238
178239 const results = await Promise .all (equipmentPromises);
179240
180- processingProgress .value = ' Building process objects...' ;
181- results .forEach (({ proc, equipmentData }) => {
182- mtpProcesses .push ({
241+ setProgressMessage (' Building process objects...' );
242+ const mtpProcesses = results .map (({ proc, equipmentData }) => ({
183243 name: proc .name ,
184244 type: ' procedure' ,
185245 processElementType: ' MTP Operation' ,
@@ -196,10 +256,9 @@ async function addElementsFromFile(fileType, fileName) {
196256 dataType: p .paramElem ? .Type ,
197257 })),
198258 equipmentInfo: equipmentData
199- });
200- });
259+ }));
201260
202- processingProgress . value = ' Adding processes to sidebar...' ;
261+ setProgressMessage ( ' Adding processes to sidebar...' ) ;
203262 console .log (' Adding parsed MTP processes:' , mtpProcesses);
204263 emit (' add' , {
205264 title: getFileNameWithoutExtension (fileName),
@@ -208,20 +267,33 @@ async function addElementsFromFile(fileType, fileName) {
208267 }
209268
210269 if (fileType === ' aas' && Array .isArray (response .data )) {
211- processingProgress .value = ' Processing AAS capabilities...' ;
270+ const importableCapabilities = response .data
271+ .filter (item => item .realized_by && item .realized_by .length > 0 );
272+
273+ initializeProgress (importableCapabilities .length );
274+ setProgressMessage (' Fetching equipment info...' );
212275 const equipmentResponse = await client .get (` /${ fileType} /${ encodeURIComponent (fileName)} /equipment-info` );
213276 console .log (` Equipment info for ${ fileType} :` , equipmentResponse .data );
214277
215- const parsedProcesses = response .data
216- .filter (item => item .realized_by && item .realized_by .length > 0 )
217- .map (item => ({
278+ markParseDone ();
279+ if (importableCapabilities .length > 0 ) {
280+ setProgressMessage (` Loading procedures ${ progressCounterText .value } ...` );
281+ } else {
282+ setProgressMessage (' No procedures found.' );
283+ }
284+
285+ const parsedProcesses = importableCapabilities .map (item => {
286+ markProcedureLoaded ();
287+ setProgressMessage (` Loading procedures ${ progressCounterText .value } ...` );
288+ return {
218289 name: item .capability [0 ].capability_name ,
219290 type: ' procedure' ,
220291 processElementType: ' AAS Capability' ,
221292 equipmentInfo: equipmentResponse .data
222- }));
293+ };
294+ });
223295
224- processingProgress . value = ' Adding processes to sidebar...' ;
296+ setProgressMessage ( ' Adding processes to sidebar...' ) ;
225297 console .log (' Adding parsed AAS processes:' , parsedProcesses);
226298 emit (' add' , {
227299 title: getFileNameWithoutExtension (fileName),
@@ -231,15 +303,10 @@ async function addElementsFromFile(fileType, fileName) {
231303
232304 } catch (error) {
233305 console .error (` Error parsing ${ fileType} file:` , error);
234- processingProgress .value = ` Error: ${ error .response ? .data ? .message || error .message || ' Unknown error occurred' }` ;
235- setTimeout(() => {
236- if (isProcessingFile.value) {
237- processingProgress.value = '';
238- }
239- }, 3000);
306+ setProgressMessage (` Error: ${ error .response ? .data ? .message || error .message || ' Unknown error occurred' }` );
240307 } finally {
241308 isProcessingFile.value = false;
242- processingProgress.value = '' ;
309+ resetProgressState() ;
243310 }
244311}
245312
0 commit comments