@abi-software/simulationvuer 3.0.12 → 3.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -10
- package/dist/index.html +10 -6
- package/dist/simulationvuer.js +11793 -11663
- package/dist/simulationvuer.umd.cjs +103 -103
- package/dist/style.css +1 -1
- package/package.json +19 -7
- package/public/index.html +10 -6
- package/src/App.vue +161 -46
- package/src/assets/_variables.scss +13 -11
- package/src/assets/styles.scss +2 -2
- package/src/components/SimulationVuer.vue +228 -113
- package/src/components/SimulationVuerInput.vue +2 -1
- package/src/components/common.js +19 -8
- package/src/components/index.js +2 -4
- package/src/components/json.js +144 -73
- package/src/main.js +2 -1
- package/vite.config.js +11 -6
- package/vuese-generator.js +77 -80
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="simulation-vuer"
|
|
4
|
+
v-loading="showUserMessage"
|
|
5
|
+
:element-loading-text="userMessage"
|
|
6
|
+
>
|
|
3
7
|
<div class="container" v-if="opencorOmexFile === null">
|
|
4
|
-
<p
|
|
8
|
+
<p
|
|
9
|
+
v-if="!hasValidSimulationUiInfo && !showUserMessage"
|
|
10
|
+
class="default error"
|
|
11
|
+
>
|
|
12
|
+
<span class="error">Error:</span> {{ errorMessage }}.
|
|
13
|
+
</p>
|
|
5
14
|
<div class="main" v-if="hasValidSimulationUiInfo">
|
|
6
|
-
<div class="main-left" :class="{'with-buttons': uuid}">
|
|
15
|
+
<div class="main-left" :class="{ 'with-buttons': uuid }">
|
|
7
16
|
<p class="default name">{{ name }}</p>
|
|
8
17
|
<el-divider></el-divider>
|
|
9
18
|
<p class="default input-parameters">Input parameters</p>
|
|
10
19
|
<div class="input scrollbar">
|
|
11
|
-
<SimulationVuerInput
|
|
20
|
+
<SimulationVuerInput
|
|
21
|
+
v-for="(input, index) in simulationUiInfo.input"
|
|
12
22
|
ref="simInput"
|
|
13
23
|
:defaultValue="input.defaultValue"
|
|
14
24
|
:key="`input-${index}`"
|
|
@@ -21,19 +31,28 @@
|
|
|
21
31
|
</div>
|
|
22
32
|
<div class="buttons-container">
|
|
23
33
|
<div class="primary-button">
|
|
24
|
-
<el-button type="primary" size="small" @click="startSimulation()"
|
|
34
|
+
<el-button type="primary" size="small" @click="startSimulation()"
|
|
35
|
+
>Run Simulation</el-button
|
|
36
|
+
>
|
|
25
37
|
</div>
|
|
26
38
|
<div class="secondary-button" v-if="uuid">
|
|
27
|
-
<el-button size="small" @click="runOnOsparc()"
|
|
39
|
+
<el-button size="small" @click="runOnOsparc()"
|
|
40
|
+
>Run on oSPARC</el-button
|
|
41
|
+
>
|
|
28
42
|
</div>
|
|
29
43
|
<div class="secondary-button">
|
|
30
|
-
<el-button size="small" @click="viewDataset()"
|
|
44
|
+
<el-button size="small" @click="viewDataset()"
|
|
45
|
+
>View Dataset</el-button
|
|
46
|
+
>
|
|
31
47
|
</div>
|
|
32
|
-
<p class="default note" v-if="uuid">
|
|
48
|
+
<p class="default note" v-if="uuid">
|
|
49
|
+
Additional parameters are available on oSPARC
|
|
50
|
+
</p>
|
|
33
51
|
</div>
|
|
34
52
|
</div>
|
|
35
53
|
<div class="main-right" ref="output" v-show="isSimulationValid">
|
|
36
|
-
<PlotVuer
|
|
54
|
+
<PlotVuer
|
|
55
|
+
v-for="(_outputPlot, index) in simulationUiInfo.output.plots"
|
|
37
56
|
:key="`output-${index}`"
|
|
38
57
|
:metadata="plotMetadata(index)"
|
|
39
58
|
:data-source="{ data: simulationResults[index] }"
|
|
@@ -43,7 +62,19 @@
|
|
|
43
62
|
/>
|
|
44
63
|
</div>
|
|
45
64
|
<div class="main-right" v-show="!isSimulationValid">
|
|
46
|
-
<p class="default error"
|
|
65
|
+
<p class="default error">
|
|
66
|
+
<span class="error">Error:</span>
|
|
67
|
+
{{ errorMessage }}
|
|
68
|
+
<span v-if="errorStatus">
|
|
69
|
+
(<a
|
|
70
|
+
:href="`https://httpstatuses.com/${errorStatus}`"
|
|
71
|
+
target="_blank"
|
|
72
|
+
rel="noopener noreferrer"
|
|
73
|
+
>
|
|
74
|
+
{{ errorStatus }} </a
|
|
75
|
+
>) </span
|
|
76
|
+
>.
|
|
77
|
+
</p>
|
|
47
78
|
</div>
|
|
48
79
|
</div>
|
|
49
80
|
</div>
|
|
@@ -61,23 +92,25 @@
|
|
|
61
92
|
<script>
|
|
62
93
|
import { PlotVuer } from "@abi-software/plotvuer";
|
|
63
94
|
import "@abi-software/plotvuer/dist/style.css";
|
|
64
|
-
import
|
|
65
|
-
import
|
|
95
|
+
import OpenCOR from "@opencor/opencor";
|
|
96
|
+
import "@opencor/opencor/style.css";
|
|
97
|
+
|
|
98
|
+
import { ElButton, ElDivider } from "element-plus";
|
|
99
|
+
import { create, all } from "mathjs";
|
|
100
|
+
|
|
66
101
|
import { evaluateValue, finaliseUi, OPENCOR_SOLVER_NAME } from "./common.js";
|
|
67
102
|
import { validJson } from "./json.js";
|
|
68
|
-
import
|
|
69
|
-
import OpenCOR from '@opencor/opencor';
|
|
70
|
-
import '@opencor/opencor/style.css';
|
|
103
|
+
import SimulationVuerInput from "./SimulationVuerInput.vue";
|
|
71
104
|
|
|
72
105
|
const PMR_URL = "https://models.physiomeproject.org/";
|
|
73
106
|
|
|
74
107
|
const math = create(all, {});
|
|
75
108
|
|
|
76
109
|
const IdType = Object.freeze({
|
|
77
|
-
DATASET_ID:
|
|
78
|
-
DATASET_URL:
|
|
79
|
-
PMR_PATH:
|
|
80
|
-
RAW_COMBINE_ARCHIVE:
|
|
110
|
+
DATASET_ID: "dataset_id",
|
|
111
|
+
DATASET_URL: "dataset_url",
|
|
112
|
+
PMR_PATH: "pmr_path",
|
|
113
|
+
RAW_COMBINE_ARCHIVE: "raw_combine_archive",
|
|
81
114
|
});
|
|
82
115
|
|
|
83
116
|
function isWebProtocol(urlString) {
|
|
@@ -101,7 +134,6 @@ export default {
|
|
|
101
134
|
SimulationVuerInput,
|
|
102
135
|
ElButton,
|
|
103
136
|
ElDivider,
|
|
104
|
-
ElLoading,
|
|
105
137
|
OpenCOR,
|
|
106
138
|
},
|
|
107
139
|
props: {
|
|
@@ -144,14 +176,17 @@ export default {
|
|
|
144
176
|
if (idType === IdType.DATASET_ID) {
|
|
145
177
|
const xmlhttp = new XMLHttpRequest();
|
|
146
178
|
|
|
147
|
-
xmlhttp.open("GET", this.apiLocation
|
|
179
|
+
xmlhttp.open("GET", `${this.apiLocation}/sim/dataset/${this.id}`);
|
|
148
180
|
xmlhttp.onreadystatechange = () => {
|
|
149
181
|
if (xmlhttp.readyState === 4) {
|
|
150
182
|
if (xmlhttp.status === 200) {
|
|
151
183
|
const datasetInfo = JSON.parse(xmlhttp.responseText);
|
|
152
184
|
|
|
153
185
|
this.name = datasetInfo.name;
|
|
154
|
-
this.uuid =
|
|
186
|
+
this.uuid =
|
|
187
|
+
datasetInfo.study !== undefined
|
|
188
|
+
? datasetInfo.study.uuid
|
|
189
|
+
: undefined;
|
|
155
190
|
}
|
|
156
191
|
}
|
|
157
192
|
};
|
|
@@ -160,6 +195,7 @@ export default {
|
|
|
160
195
|
|
|
161
196
|
return {
|
|
162
197
|
errorMessage: "",
|
|
198
|
+
errorStatus: null,
|
|
163
199
|
fileManager: undefined,
|
|
164
200
|
hasFinalisedUi: false,
|
|
165
201
|
hasValidSimulationUiInfo: false,
|
|
@@ -191,40 +227,48 @@ export default {
|
|
|
191
227
|
/**
|
|
192
228
|
* @public
|
|
193
229
|
* Add a data subscription.
|
|
194
|
-
* @
|
|
230
|
+
* @param `subscription`
|
|
195
231
|
*/
|
|
196
232
|
addDataSubscription(subscription) {
|
|
197
233
|
// Check that the subscription is valid.
|
|
198
234
|
|
|
199
|
-
if (!subscription || typeof subscription !==
|
|
200
|
-
console.
|
|
235
|
+
if (!subscription || typeof subscription !== "object") {
|
|
236
|
+
console.warn(
|
|
237
|
+
"SimulationVuer: addDataSubscription: subscription must be an object.",
|
|
238
|
+
);
|
|
201
239
|
|
|
202
240
|
return;
|
|
203
241
|
}
|
|
204
242
|
|
|
205
243
|
// Check that the subscription has the expected ID.
|
|
206
244
|
|
|
207
|
-
const EXPECTED_ID =
|
|
245
|
+
const EXPECTED_ID = "nz.ac.auckland.simulation-data-request";
|
|
208
246
|
const EXPECTED_MAJOR_VERSION = 0;
|
|
209
247
|
|
|
210
248
|
if (subscription.id !== EXPECTED_ID) {
|
|
211
|
-
console.warn(
|
|
249
|
+
console.warn(
|
|
250
|
+
`SimulationVuer: addDataSubscription: invalid ID (expected '${EXPECTED_ID}' but got '${subscription.id}').`,
|
|
251
|
+
);
|
|
212
252
|
|
|
213
253
|
return;
|
|
214
254
|
}
|
|
215
255
|
|
|
216
256
|
// Check that the version is valid and compatible with what we expect.
|
|
217
257
|
|
|
218
|
-
if (typeof subscription.version !==
|
|
219
|
-
console.warn(
|
|
258
|
+
if (typeof subscription.version !== "string") {
|
|
259
|
+
console.warn(
|
|
260
|
+
`SimulationVuer: addDataSubscription: missing or non-string version ('${subscription.version}').`,
|
|
261
|
+
);
|
|
220
262
|
|
|
221
263
|
return;
|
|
222
264
|
}
|
|
223
265
|
|
|
224
|
-
const versionParts = subscription.version.split(
|
|
266
|
+
const versionParts = subscription.version.split(".");
|
|
225
267
|
|
|
226
268
|
if (versionParts.length < 1 || !/^[0-9]+$/.test(versionParts[0])) {
|
|
227
|
-
console.warn(
|
|
269
|
+
console.warn(
|
|
270
|
+
`SimulationVuer: addDataSubscription: malformed version ('${subscription.version}').`,
|
|
271
|
+
);
|
|
228
272
|
|
|
229
273
|
return;
|
|
230
274
|
}
|
|
@@ -232,13 +276,17 @@ export default {
|
|
|
232
276
|
const subscriptionMajorVersion = parseInt(versionParts[0], 10);
|
|
233
277
|
|
|
234
278
|
if (Number.isNaN(subscriptionMajorVersion)) {
|
|
235
|
-
console.warn(
|
|
279
|
+
console.warn(
|
|
280
|
+
`SimulationVuer: addDataSubscription: could not parse the major version from ('${subscription.version}')`,
|
|
281
|
+
);
|
|
236
282
|
|
|
237
283
|
return;
|
|
238
284
|
}
|
|
239
285
|
|
|
240
286
|
if (subscriptionMajorVersion !== EXPECTED_MAJOR_VERSION) {
|
|
241
|
-
console.warn(
|
|
287
|
+
console.warn(
|
|
288
|
+
`SimulationVuer: addDataSubscription: version mismatch (expected v${EXPECTED_MAJOR_VERSION}.y.z but got v${subscription.version}).`,
|
|
289
|
+
);
|
|
242
290
|
|
|
243
291
|
return;
|
|
244
292
|
}
|
|
@@ -249,23 +297,25 @@ export default {
|
|
|
249
297
|
const missing = [];
|
|
250
298
|
|
|
251
299
|
if (payload.windowId == null) {
|
|
252
|
-
missing.push(
|
|
300
|
+
missing.push("windowId");
|
|
253
301
|
}
|
|
254
302
|
|
|
255
303
|
if (payload.ownerId == null) {
|
|
256
|
-
missing.push(
|
|
304
|
+
missing.push("ownerId");
|
|
257
305
|
}
|
|
258
306
|
|
|
259
307
|
if (!payload.component) {
|
|
260
|
-
missing.push(
|
|
308
|
+
missing.push("component");
|
|
261
309
|
}
|
|
262
310
|
|
|
263
311
|
if (!payload.variable) {
|
|
264
|
-
missing.push(
|
|
312
|
+
missing.push("variable");
|
|
265
313
|
}
|
|
266
314
|
|
|
267
315
|
if (missing.length) {
|
|
268
|
-
console.warn(
|
|
316
|
+
console.warn(
|
|
317
|
+
`SimulationVuer: addDataSubscription: payload missing fields: ${missing.join(", ")}.`,
|
|
318
|
+
);
|
|
269
319
|
|
|
270
320
|
return;
|
|
271
321
|
}
|
|
@@ -280,52 +330,69 @@ export default {
|
|
|
280
330
|
const modelParameters = [];
|
|
281
331
|
|
|
282
332
|
if (subscription.payload?.withVOI) {
|
|
283
|
-
modelParameters.push(
|
|
333
|
+
modelParameters.push("VOI");
|
|
284
334
|
}
|
|
285
335
|
|
|
286
|
-
modelParameters.push(
|
|
336
|
+
modelParameters.push(
|
|
337
|
+
`${subscription.payload?.component}/${subscription.payload?.variable}`,
|
|
338
|
+
);
|
|
287
339
|
|
|
288
340
|
this.$refs.opencorRef?.trackSimulationData(modelParameters);
|
|
289
341
|
},
|
|
290
342
|
/**
|
|
291
343
|
* @public
|
|
292
344
|
* Remove a data subscription.
|
|
293
|
-
* @
|
|
345
|
+
* @param `subscriptionId`
|
|
294
346
|
*/
|
|
295
347
|
removeDataSubscription(subscriptionId) {
|
|
296
348
|
// Ask OpenCOR to stop tracking the simulation data associated with the subscription's component and variable (and
|
|
297
349
|
// the VOI, if requested and unless it's requested by another subscription).
|
|
298
350
|
|
|
299
|
-
const subscription = this.activeSubscriptions.find(
|
|
300
|
-
|
|
301
|
-
|
|
351
|
+
const subscription = this.activeSubscriptions.find(
|
|
352
|
+
(activeSubscription) => {
|
|
353
|
+
return activeSubscription.windowId === subscriptionId;
|
|
354
|
+
},
|
|
355
|
+
);
|
|
302
356
|
|
|
303
357
|
if (!subscription) {
|
|
304
|
-
console.warn(
|
|
358
|
+
console.warn(
|
|
359
|
+
`SimulationVuer: removeDataSubscription: no active subscription found for id ${subscriptionId}.`,
|
|
360
|
+
);
|
|
305
361
|
|
|
306
362
|
return;
|
|
307
363
|
}
|
|
308
364
|
|
|
309
|
-
const isVoiTrackedByAnotherSubscription = this.activeSubscriptions.some(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
365
|
+
const isVoiTrackedByAnotherSubscription = this.activeSubscriptions.some(
|
|
366
|
+
(activeSubscription) => {
|
|
367
|
+
return (
|
|
368
|
+
activeSubscription.windowId !== subscriptionId &&
|
|
369
|
+
activeSubscription.withVOI
|
|
370
|
+
);
|
|
371
|
+
},
|
|
372
|
+
);
|
|
373
|
+
const isModelParameterTrackedByAnotherSubscription =
|
|
374
|
+
this.activeSubscriptions.some((activeSubscription) => {
|
|
375
|
+
return (
|
|
376
|
+
activeSubscription.windowId !== subscriptionId &&
|
|
377
|
+
activeSubscription.component === subscription.component &&
|
|
378
|
+
activeSubscription.variable === subscription.variable
|
|
379
|
+
);
|
|
380
|
+
});
|
|
319
381
|
|
|
320
|
-
if (
|
|
382
|
+
if (
|
|
383
|
+
!isVoiTrackedByAnotherSubscription ||
|
|
384
|
+
!isModelParameterTrackedByAnotherSubscription
|
|
385
|
+
) {
|
|
321
386
|
const modelParameters = [];
|
|
322
387
|
|
|
323
388
|
if (subscription.withVOI && !isVoiTrackedByAnotherSubscription) {
|
|
324
|
-
modelParameters.push(
|
|
389
|
+
modelParameters.push("VOI");
|
|
325
390
|
}
|
|
326
391
|
|
|
327
392
|
if (!isModelParameterTrackedByAnotherSubscription) {
|
|
328
|
-
modelParameters.push(
|
|
393
|
+
modelParameters.push(
|
|
394
|
+
`${subscription.component}/${subscription.variable}`,
|
|
395
|
+
);
|
|
329
396
|
}
|
|
330
397
|
|
|
331
398
|
if (modelParameters.length) {
|
|
@@ -335,14 +402,16 @@ export default {
|
|
|
335
402
|
|
|
336
403
|
// Remove the subscription from our list of active subscriptions.
|
|
337
404
|
|
|
338
|
-
this.activeSubscriptions = this.activeSubscriptions.filter(
|
|
339
|
-
|
|
340
|
-
|
|
405
|
+
this.activeSubscriptions = this.activeSubscriptions.filter(
|
|
406
|
+
(activeSubscription) => {
|
|
407
|
+
return activeSubscription.windowId !== subscriptionId;
|
|
408
|
+
},
|
|
409
|
+
);
|
|
341
410
|
},
|
|
342
411
|
/**
|
|
343
412
|
* @public
|
|
344
413
|
* Let the outside world know that we have received some simulation data from OpenCOR by emitting a `data-notification` event.
|
|
345
|
-
* @
|
|
414
|
+
* @param `event`
|
|
346
415
|
*/
|
|
347
416
|
onSimulationData(event) {
|
|
348
417
|
const simulationData = event.simulationData || {};
|
|
@@ -350,33 +419,36 @@ export default {
|
|
|
350
419
|
|
|
351
420
|
this.activeSubscriptions.forEach((activeSubscription) => {
|
|
352
421
|
const modelParameter = `${activeSubscription.component}/${activeSubscription.variable}`;
|
|
422
|
+
const simData = simulationData[modelParameter];
|
|
353
423
|
|
|
354
|
-
if (
|
|
355
|
-
console.warn(
|
|
424
|
+
if (simData == null) {
|
|
425
|
+
console.warn(
|
|
426
|
+
`SimulationVuer: onSimulationData: no data for ${modelParameter}.`,
|
|
427
|
+
);
|
|
356
428
|
|
|
357
429
|
return;
|
|
358
430
|
}
|
|
359
431
|
|
|
360
432
|
const data = {
|
|
361
|
-
y:
|
|
362
|
-
title: `${activeSubscription.component}.${activeSubscription.variable}`,
|
|
433
|
+
y: simData.data,
|
|
434
|
+
title: `${activeSubscription.component}.${activeSubscription.variable} (${simData.unit})`,
|
|
363
435
|
};
|
|
364
436
|
|
|
365
437
|
if (activeSubscription.withVOI) {
|
|
366
438
|
if (simulationData.VOI == null) {
|
|
367
|
-
console.warn(
|
|
439
|
+
console.warn("SimulationVuer: onSimulationData: no data for VOI.");
|
|
368
440
|
|
|
369
441
|
return;
|
|
370
442
|
} else {
|
|
371
|
-
voi ??=
|
|
443
|
+
voi ??= simulationData.VOI;
|
|
372
444
|
|
|
373
445
|
data.x = voi;
|
|
374
446
|
}
|
|
375
447
|
}
|
|
376
448
|
|
|
377
|
-
this.$emit(
|
|
378
|
-
id:
|
|
379
|
-
version:
|
|
449
|
+
this.$emit("data-notification", {
|
|
450
|
+
id: "nz.ac.auckland.simulation-data-response",
|
|
451
|
+
version: "0.1.0",
|
|
380
452
|
payload: {
|
|
381
453
|
windowId: activeSubscription.windowId,
|
|
382
454
|
ownerId: activeSubscription.ownerId,
|
|
@@ -388,7 +460,7 @@ export default {
|
|
|
388
460
|
/**
|
|
389
461
|
* @public
|
|
390
462
|
* Generate the metadata associated with the plot which `index` is given.
|
|
391
|
-
* @
|
|
463
|
+
* @param `index`
|
|
392
464
|
*/
|
|
393
465
|
plotMetadata(index) {
|
|
394
466
|
return {
|
|
@@ -403,7 +475,7 @@ export default {
|
|
|
403
475
|
/**
|
|
404
476
|
* @public
|
|
405
477
|
* Build the simulation UI using `simulationUiInfo`, a JSON object that describes the contents of the simulation UI.
|
|
406
|
-
* @
|
|
478
|
+
* @param `simulationUiInfo`
|
|
407
479
|
*/
|
|
408
480
|
buildSimulationUi(simulationUiInfo) {
|
|
409
481
|
// Keep track of the simulation UI information.
|
|
@@ -423,7 +495,7 @@ export default {
|
|
|
423
495
|
// Retrieve and keep track of the solver to be used for the simulation.
|
|
424
496
|
|
|
425
497
|
this.simulationUiInfo.simulation.solvers.forEach((solver) => {
|
|
426
|
-
if (
|
|
498
|
+
if (solver.if === undefined || evaluateValue(this, solver.if)) {
|
|
427
499
|
this.solver = solver;
|
|
428
500
|
}
|
|
429
501
|
});
|
|
@@ -493,6 +565,25 @@ export default {
|
|
|
493
565
|
finaliseUi(this);
|
|
494
566
|
});
|
|
495
567
|
},
|
|
568
|
+
/**
|
|
569
|
+
* @private
|
|
570
|
+
* Open the given `url` in a new browser tab, making sure to do so safely.
|
|
571
|
+
* @param `url`
|
|
572
|
+
*/
|
|
573
|
+
openUrl(url) {
|
|
574
|
+
const a = document.createElement("a");
|
|
575
|
+
|
|
576
|
+
a.href = url;
|
|
577
|
+
a.target = "_blank";
|
|
578
|
+
a.rel = "noopener noreferrer";
|
|
579
|
+
a.style.display = "none";
|
|
580
|
+
|
|
581
|
+
document.body.appendChild(a);
|
|
582
|
+
|
|
583
|
+
a.click();
|
|
584
|
+
|
|
585
|
+
document.body.removeChild(a);
|
|
586
|
+
},
|
|
496
587
|
/**
|
|
497
588
|
* @public
|
|
498
589
|
* Run the simulation-based dataset directly on oSPARC. Not all simulation-based datasets can be run directly on
|
|
@@ -500,7 +591,7 @@ export default {
|
|
|
500
591
|
* method.
|
|
501
592
|
*/
|
|
502
593
|
runOnOsparc() {
|
|
503
|
-
|
|
594
|
+
this.openUrl(`https://osparc.io/study/${this.uuid}`);
|
|
504
595
|
},
|
|
505
596
|
/**
|
|
506
597
|
* @public
|
|
@@ -508,7 +599,7 @@ export default {
|
|
|
508
599
|
* clicked, calls this method.
|
|
509
600
|
*/
|
|
510
601
|
viewDataset() {
|
|
511
|
-
|
|
602
|
+
this.openUrl(`https://sparc.science/datasets/${this.id}?type=dataset`);
|
|
512
603
|
},
|
|
513
604
|
/**
|
|
514
605
|
* @public
|
|
@@ -517,8 +608,7 @@ export default {
|
|
|
517
608
|
*/
|
|
518
609
|
viewWorkspace() {
|
|
519
610
|
const url = PMR_URL + this.id;
|
|
520
|
-
|
|
521
|
-
window.open(url.substring(0, url.lastIndexOf("/")), "_blank");
|
|
611
|
+
this.openUrl(url.substring(0, url.lastIndexOf("/")));
|
|
522
612
|
},
|
|
523
613
|
/**
|
|
524
614
|
* @public
|
|
@@ -556,7 +646,7 @@ export default {
|
|
|
556
646
|
*/
|
|
557
647
|
retrieveRequest() {
|
|
558
648
|
const request = {
|
|
559
|
-
solver: this.solver
|
|
649
|
+
solver: this.solver,
|
|
560
650
|
};
|
|
561
651
|
|
|
562
652
|
if (this.opencorBasedSimulation) {
|
|
@@ -565,11 +655,15 @@ export default {
|
|
|
565
655
|
json_config: {},
|
|
566
656
|
};
|
|
567
657
|
|
|
568
|
-
if (
|
|
569
|
-
|
|
658
|
+
if (
|
|
659
|
+
this.simulationUiInfo.simulation.opencor.endingPoint !== undefined &&
|
|
660
|
+
this.simulationUiInfo.simulation.opencor.pointInterval !== undefined
|
|
661
|
+
) {
|
|
570
662
|
request.opencor.json_config.simulation = {
|
|
571
|
-
"Ending point":
|
|
572
|
-
|
|
663
|
+
"Ending point":
|
|
664
|
+
this.simulationUiInfo.simulation.opencor.endingPoint,
|
|
665
|
+
"Point interval":
|
|
666
|
+
this.simulationUiInfo.simulation.opencor.pointInterval,
|
|
573
667
|
};
|
|
574
668
|
}
|
|
575
669
|
|
|
@@ -592,13 +686,13 @@ export default {
|
|
|
592
686
|
* @public
|
|
593
687
|
* Process the simulation results retrieved by `checkSimulation`. The simulation results are post-processed, if
|
|
594
688
|
* needed, and then readied for use by `PlotVuer`.
|
|
595
|
-
* @
|
|
689
|
+
* @param `results`
|
|
596
690
|
*/
|
|
597
691
|
processSimulationResults(results) {
|
|
598
692
|
// Convert, if needed, the results to a JSON format that is compatible
|
|
599
693
|
// with our OpenCOR results.
|
|
600
694
|
|
|
601
|
-
if (typeof
|
|
695
|
+
if (typeof results === "string") {
|
|
602
696
|
const SPACES = /[ \t]+/g;
|
|
603
697
|
const lines = results.trim().split("\n");
|
|
604
698
|
const iMax = lines[0].trim().split(SPACES).length;
|
|
@@ -646,26 +740,27 @@ export default {
|
|
|
646
740
|
/**
|
|
647
741
|
* @public
|
|
648
742
|
* Show an HTTP issue using the given `xmlhttp`.
|
|
649
|
-
* @
|
|
743
|
+
* @param `xmlhttp`
|
|
650
744
|
*/
|
|
651
745
|
showHttpIssue(xmlhttp) {
|
|
652
746
|
this.isSimulationValid = false;
|
|
653
747
|
this.showUserMessage = false;
|
|
654
|
-
this.errorMessage = xmlhttp.statusText.toLowerCase()
|
|
748
|
+
this.errorMessage = xmlhttp.statusText.toLowerCase();
|
|
749
|
+
this.errorStatus = xmlhttp.status;
|
|
655
750
|
},
|
|
656
751
|
/**
|
|
657
752
|
* @public
|
|
658
753
|
* Check the progress of the simulation using the given `data`, a JSON object that contains the simulation job ID,
|
|
659
754
|
* as well as the solver name and version. This method is first called by `startSimulation` and then every second by
|
|
660
755
|
* itself until the simulation is finished.
|
|
661
|
-
* @
|
|
756
|
+
* @param `data`
|
|
662
757
|
*/
|
|
663
758
|
checkSimulation(data) {
|
|
664
759
|
// Check the simulation.
|
|
665
760
|
|
|
666
761
|
const xmlhttp = new XMLHttpRequest();
|
|
667
762
|
|
|
668
|
-
xmlhttp.open("POST", this.apiLocation
|
|
763
|
+
xmlhttp.open("POST", `${this.apiLocation}/check_simulation`);
|
|
669
764
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
670
765
|
xmlhttp.onreadystatechange = () => {
|
|
671
766
|
if (xmlhttp.readyState === 4) {
|
|
@@ -687,13 +782,14 @@ export default {
|
|
|
687
782
|
|
|
688
783
|
let that = this;
|
|
689
784
|
|
|
690
|
-
setTimeout(
|
|
785
|
+
setTimeout(() => {
|
|
691
786
|
that.checkSimulation(data);
|
|
692
787
|
}, 1000);
|
|
693
788
|
}
|
|
694
789
|
} else {
|
|
695
790
|
this.showUserMessage = false;
|
|
696
791
|
this.errorMessage = response.description;
|
|
792
|
+
this.errorStatus = null;
|
|
697
793
|
}
|
|
698
794
|
} else {
|
|
699
795
|
this.showHttpIssue(xmlhttp);
|
|
@@ -719,7 +815,7 @@ export default {
|
|
|
719
815
|
|
|
720
816
|
const xmlhttp = new XMLHttpRequest();
|
|
721
817
|
|
|
722
|
-
xmlhttp.open("POST", this.apiLocation
|
|
818
|
+
xmlhttp.open("POST", `${this.apiLocation}/start_simulation`);
|
|
723
819
|
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
724
820
|
xmlhttp.onreadystatechange = () => {
|
|
725
821
|
if (xmlhttp.readyState === 4) {
|
|
@@ -733,6 +829,7 @@ export default {
|
|
|
733
829
|
} else {
|
|
734
830
|
this.showUserMessage = false;
|
|
735
831
|
this.errorMessage = response.description;
|
|
832
|
+
this.errorStatus = null;
|
|
736
833
|
}
|
|
737
834
|
} else {
|
|
738
835
|
this.showHttpIssue(xmlhttp);
|
|
@@ -755,7 +852,10 @@ export default {
|
|
|
755
852
|
this.$nextTick(() => {
|
|
756
853
|
const xmlhttp = new XMLHttpRequest();
|
|
757
854
|
|
|
758
|
-
xmlhttp.open(
|
|
855
|
+
xmlhttp.open(
|
|
856
|
+
"GET",
|
|
857
|
+
`${this.apiLocation}/simulation_ui_file/${this.id}`,
|
|
858
|
+
);
|
|
759
859
|
xmlhttp.onreadystatechange = () => {
|
|
760
860
|
if (xmlhttp.readyState === 4) {
|
|
761
861
|
this.showUserMessage = false;
|
|
@@ -765,7 +865,9 @@ export default {
|
|
|
765
865
|
this.buildSimulationUi(JSON.parse(xmlhttp.responseText));
|
|
766
866
|
});
|
|
767
867
|
} else {
|
|
768
|
-
this.errorMessage =
|
|
868
|
+
this.errorMessage =
|
|
869
|
+
"the simulation dataset could not be retrieved";
|
|
870
|
+
this.errorStatus = null;
|
|
769
871
|
}
|
|
770
872
|
}
|
|
771
873
|
};
|
|
@@ -774,8 +876,9 @@ export default {
|
|
|
774
876
|
} else if (this.idType === IdType.DATASET_URL) {
|
|
775
877
|
this.opencorOmexFile = this.id;
|
|
776
878
|
} else if (this.idType === IdType.PMR_PATH) {
|
|
777
|
-
this.opencorOmexFile = PMR_URL
|
|
778
|
-
} else {
|
|
879
|
+
this.opencorOmexFile = `${PMR_URL}${this.id}`;
|
|
880
|
+
} else {
|
|
881
|
+
// IdType.RAW_COMBINE_ARCHIVE
|
|
779
882
|
this.opencorOmexFile = this.id;
|
|
780
883
|
}
|
|
781
884
|
},
|
|
@@ -795,10 +898,10 @@ export default {
|
|
|
795
898
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
796
899
|
<style scoped lang="scss">
|
|
797
900
|
.simulation-vuer {
|
|
798
|
-
--el-color-primary: #
|
|
799
|
-
--el-color-primary-light-7: #
|
|
800
|
-
--el-color-primary-light-8: #
|
|
801
|
-
--el-color-primary-light-9: #
|
|
901
|
+
--el-color-primary: #8300bf;
|
|
902
|
+
--el-color-primary-light-7: #dab3ec;
|
|
903
|
+
--el-color-primary-light-8: #e6ccf2;
|
|
904
|
+
--el-color-primary-light-9: #f3e6f9;
|
|
802
905
|
}
|
|
803
906
|
|
|
804
907
|
:deep(.el-button:hover) {
|
|
@@ -812,12 +915,12 @@ export default {
|
|
|
812
915
|
|
|
813
916
|
:deep(.el-loading-spinner) {
|
|
814
917
|
.path {
|
|
815
|
-
stroke: #
|
|
918
|
+
stroke: #8300bf;
|
|
816
919
|
}
|
|
817
920
|
|
|
818
921
|
i,
|
|
819
922
|
.el-loading-text {
|
|
820
|
-
color: #
|
|
923
|
+
color: #8300bf;
|
|
821
924
|
}
|
|
822
925
|
}
|
|
823
926
|
|
|
@@ -825,23 +928,23 @@ export default {
|
|
|
825
928
|
:deep(.p-floatlabel:has(input:-webkit-autofill)) label,
|
|
826
929
|
:deep(.p-floatlabel:has(textarea:focus)) label,
|
|
827
930
|
:deep(.p-floatlabel:has(.p-inputwrapper-focus)) label {
|
|
828
|
-
color: #
|
|
931
|
+
color: #8300bf;
|
|
829
932
|
}
|
|
830
933
|
|
|
831
934
|
:deep(.p-inputtext:enabled:focus) {
|
|
832
|
-
|
|
935
|
+
border-color: #8300bf;
|
|
833
936
|
}
|
|
834
937
|
|
|
835
938
|
:deep(.p-progressbar-value) {
|
|
836
|
-
background-color: #
|
|
939
|
+
background-color: #8300bf !important;
|
|
837
940
|
}
|
|
838
941
|
|
|
839
942
|
:deep(.p-select:not(.p-disabled).p-focus) {
|
|
840
|
-
|
|
943
|
+
border-color: #8300bf;
|
|
841
944
|
}
|
|
842
945
|
|
|
843
946
|
:deep(.p-slider-range) {
|
|
844
|
-
background-color: #
|
|
947
|
+
background-color: #8300bf;
|
|
845
948
|
}
|
|
846
949
|
|
|
847
950
|
div.input {
|
|
@@ -1045,21 +1148,33 @@ span.error {
|
|
|
1045
1148
|
|
|
1046
1149
|
.p-contextmenu-item-label,
|
|
1047
1150
|
.p-select-option-label {
|
|
1048
|
-
|
|
1049
|
-
|
|
1151
|
+
font-family:
|
|
1152
|
+
Inter,
|
|
1153
|
+
-apple-system,
|
|
1154
|
+
BlinkMacSystemFont,
|
|
1155
|
+
"Segoe UI",
|
|
1156
|
+
Roboto,
|
|
1157
|
+
Oxygen,
|
|
1158
|
+
Ubuntu,
|
|
1159
|
+
Cantarell,
|
|
1160
|
+
"Fira Sans",
|
|
1161
|
+
"Droid Sans",
|
|
1162
|
+
"Helvetica Neue",
|
|
1163
|
+
sans-serif;
|
|
1164
|
+
font-size: 0.875rem;
|
|
1050
1165
|
}
|
|
1051
1166
|
|
|
1052
1167
|
.p-select-option:not(.p-select-option-selected):not(.p-disabled).p-focus {
|
|
1053
|
-
|
|
1168
|
+
background: #f5f7fa !important;
|
|
1054
1169
|
}
|
|
1055
1170
|
|
|
1056
1171
|
.p-select-option.p-select-option-selected.p-focus {
|
|
1057
|
-
|
|
1058
|
-
|
|
1172
|
+
background: #f5f7fa !important;
|
|
1173
|
+
color: #8300bf !important;
|
|
1059
1174
|
}
|
|
1060
1175
|
|
|
1061
1176
|
.p-select-option.p-select-option-selected {
|
|
1062
|
-
|
|
1063
|
-
|
|
1177
|
+
background: white !important;
|
|
1178
|
+
color: #8300bf !important;
|
|
1064
1179
|
}
|
|
1065
1180
|
</style>
|