@abi-software/simulationvuer 3.0.10-beta.1 → 3.0.11
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/dist/simulationvuer.js +71726 -2
- package/dist/simulationvuer.umd.cjs +1472 -2019
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/App.vue +1 -1
- package/src/components/SimulationVuer.vue +386 -305
- package/src/components.d.ts +2 -0
- package/dist/index-V4cGn7hp.js +0 -71337
- package/dist/quill-CCULFmEg-DZGnRXBL.js +0 -7524
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="simulation-vuer" v-loading="showUserMessage" :element-loading-text="userMessage">
|
|
3
3
|
<div class="container" v-if="opencorOmexFile === null">
|
|
4
|
-
<p v-if="!hasValidSimulationUiInfo && !showUserMessage" class="default error">
|
|
5
|
-
<span class="error">Error:</span> {{ errorMessage }}.
|
|
6
|
-
</p>
|
|
4
|
+
<p v-if="!hasValidSimulationUiInfo && !showUserMessage" class="default error"><span class="error">Error:</span> {{ errorMessage }}.</p>
|
|
7
5
|
<div class="main" v-if="hasValidSimulationUiInfo">
|
|
8
|
-
<div class="main-left" :class="{
|
|
6
|
+
<div class="main-left" :class="{'with-buttons': uuid}">
|
|
9
7
|
<p class="default name">{{ name }}</p>
|
|
10
8
|
<el-divider></el-divider>
|
|
11
9
|
<p class="default input-parameters">Input parameters</p>
|
|
12
10
|
<div class="input scrollbar">
|
|
13
|
-
<SimulationVuerInput
|
|
14
|
-
v-for="(input, index) in simulationUiInfo.input"
|
|
11
|
+
<SimulationVuerInput v-for="(input, index) in simulationUiInfo.input"
|
|
15
12
|
ref="simInput"
|
|
16
13
|
:defaultValue="input.defaultValue"
|
|
17
14
|
:key="`input-${index}`"
|
|
@@ -36,8 +33,7 @@
|
|
|
36
33
|
</div>
|
|
37
34
|
</div>
|
|
38
35
|
<div class="main-right" ref="output" v-show="isSimulationValid">
|
|
39
|
-
<PlotVuer
|
|
40
|
-
v-for="(_outputPlot, index) in simulationUiInfo.output.plots"
|
|
36
|
+
<PlotVuer v-for="(_outputPlot, index) in simulationUiInfo.output.plots"
|
|
41
37
|
:key="`output-${index}`"
|
|
42
38
|
:metadata="plotMetadata(index)"
|
|
43
39
|
:data-source="{ data: simulationResults[index] }"
|
|
@@ -47,155 +43,51 @@
|
|
|
47
43
|
/>
|
|
48
44
|
</div>
|
|
49
45
|
<div class="main-right" v-show="!isSimulationValid">
|
|
50
|
-
<p class="default error">
|
|
51
|
-
<span class="error">Error:</span>
|
|
52
|
-
<span v-html="errorMessage"></span>.
|
|
53
|
-
</p>
|
|
46
|
+
<p class="default error"><span class="error">Error:</span> <span v-html="errorMessage"></span>.</p>
|
|
54
47
|
</div>
|
|
55
48
|
</div>
|
|
56
49
|
</div>
|
|
57
50
|
<div v-else class="opencor">
|
|
58
|
-
<OpenCOR
|
|
51
|
+
<OpenCOR
|
|
52
|
+
ref="opencorRef"
|
|
53
|
+
:omex="opencorOmexFile"
|
|
54
|
+
theme="light"
|
|
55
|
+
@simulationData="onSimulationData($event)"
|
|
56
|
+
/>
|
|
59
57
|
</div>
|
|
60
58
|
</div>
|
|
61
59
|
</template>
|
|
62
60
|
|
|
63
|
-
<script setup>
|
|
64
|
-
import { onMounted, onUnmounted, ref } from 'vue'
|
|
65
|
-
|
|
66
|
-
const emit = defineEmits(['data-notification'])
|
|
67
|
-
|
|
68
|
-
const activeSubscriptions = ref([])
|
|
69
|
-
// Only for demonstration purposes.
|
|
70
|
-
let intervalTimer = null
|
|
71
|
-
|
|
72
|
-
// Only for demonstration purposes.
|
|
73
|
-
function getMockValue(type, tick) {
|
|
74
|
-
if (type === 'sine') return Math.sin(tick * 0.1) * 10
|
|
75
|
-
if (type === 'linear') return tick
|
|
76
|
-
return Math.random() * 10
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Only for demonstration purposes.
|
|
80
|
-
function mockType(req) {
|
|
81
|
-
return Math.random() < 0.5 ? 'sine' : 'random'
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Only for demonstration purposes.
|
|
85
|
-
function generateMockSeries(type, length = 100) {
|
|
86
|
-
const data = []
|
|
87
|
-
for (let i = 0; i < length; i++) {
|
|
88
|
-
data.push(getMockValue(type, i))
|
|
89
|
-
}
|
|
90
|
-
return data
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function addDataSubscription(subscription) {
|
|
94
|
-
if (!subscription || typeof subscription !== 'object') {
|
|
95
|
-
console.error('addDataSubscription: Subscription must be an object.')
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const EXPECTED_ID = 'nz.ac.auckland.simulation-data-request'
|
|
100
|
-
const EXPECTED_MAJOR_VERSION = 0
|
|
101
|
-
|
|
102
|
-
if (subscription.id !== EXPECTED_ID) {
|
|
103
|
-
console.warn(`Request ignored: Invalid ID '${subscription.id}'`)
|
|
104
|
-
return
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const subscriptionMajorVersion = parseInt(subscription.version.split('.')[0])
|
|
108
|
-
if (subscriptionMajorVersion !== EXPECTED_MAJOR_VERSION) {
|
|
109
|
-
console.warn(
|
|
110
|
-
`Request ignored: Version mismatch. Expected v${EXPECTED_MAJOR_VERSION}.x, got v${subscription.version}`
|
|
111
|
-
)
|
|
112
|
-
return
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
activeSubscriptions.value.push(subscription.payload)
|
|
116
|
-
sendDataForSubscription(subscription.payload)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function sendDataForSubscription(dataSubscription) {
|
|
120
|
-
// Only for demonstration purposes.
|
|
121
|
-
const type = mockType(dataSubscription)
|
|
122
|
-
let data = {
|
|
123
|
-
y: generateMockSeries(type, 100),
|
|
124
|
-
title: `${dataSubscription.component}.${dataSubscription.variable}`,
|
|
125
|
-
}
|
|
126
|
-
if (dataSubscription.withVOI) {
|
|
127
|
-
const voi_type = 'linear'
|
|
128
|
-
data.x = generateMockSeries(voi_type, 100)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const response = {
|
|
132
|
-
id: 'nz.ac.auckland.simulation-data-response',
|
|
133
|
-
version: '0.1.0',
|
|
134
|
-
payload: {
|
|
135
|
-
windowId: dataSubscription.windowId,
|
|
136
|
-
ownerId: dataSubscription.ownerId,
|
|
137
|
-
data: data,
|
|
138
|
-
},
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
emit('data-notification', response)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function removeDataSubscription(subscriptionId) {
|
|
145
|
-
activeSubscriptions.value = activeSubscriptions.value.filter(
|
|
146
|
-
(sub) => sub.windowId !== subscriptionId
|
|
147
|
-
)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
defineExpose({ addDataSubscription, removeDataSubscription })
|
|
151
|
-
|
|
152
|
-
// Only for demonstration purposes.
|
|
153
|
-
onMounted(() => {
|
|
154
|
-
intervalTimer = setInterval(() => {
|
|
155
|
-
if (activeSubscriptions.value.length === 0) return
|
|
156
|
-
|
|
157
|
-
activeSubscriptions.value.forEach((subscription) => {
|
|
158
|
-
sendDataForSubscription(subscription)
|
|
159
|
-
})
|
|
160
|
-
}, 3000)
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
// Only for demonstration purposes.
|
|
164
|
-
onUnmounted(() => {
|
|
165
|
-
if (intervalTimer) clearInterval(intervalTimer)
|
|
166
|
-
})
|
|
167
|
-
</script>
|
|
168
|
-
|
|
169
61
|
<script>
|
|
170
|
-
import { PlotVuer } from
|
|
171
|
-
import
|
|
172
|
-
import SimulationVuerInput from
|
|
173
|
-
import { ElButton, ElDivider, ElLoading } from
|
|
174
|
-
import { evaluateValue, finaliseUi, OPENCOR_SOLVER_NAME } from
|
|
175
|
-
import { validJson } from
|
|
176
|
-
import { create, all } from
|
|
177
|
-
import OpenCOR from '@opencor/opencor'
|
|
178
|
-
import '@opencor/opencor/style.css'
|
|
62
|
+
import { PlotVuer } from "@abi-software/plotvuer";
|
|
63
|
+
import "@abi-software/plotvuer/dist/style.css";
|
|
64
|
+
import SimulationVuerInput from "./SimulationVuerInput.vue";
|
|
65
|
+
import { ElButton, ElDivider, ElLoading } from "element-plus";
|
|
66
|
+
import { evaluateValue, finaliseUi, OPENCOR_SOLVER_NAME } from "./common.js";
|
|
67
|
+
import { validJson } from "./json.js";
|
|
68
|
+
import { create, all } from "mathjs";
|
|
69
|
+
import OpenCOR from '@opencor/opencor';
|
|
70
|
+
import '@opencor/opencor/style.css';
|
|
179
71
|
|
|
180
|
-
const PMR_URL =
|
|
72
|
+
const PMR_URL = "https://models.physiomeproject.org/";
|
|
181
73
|
|
|
182
|
-
const math = create(all, {})
|
|
74
|
+
const math = create(all, {});
|
|
183
75
|
|
|
184
76
|
const IdType = Object.freeze({
|
|
185
77
|
DATASET_ID: 'dataset_id',
|
|
186
78
|
DATASET_URL: 'dataset_url',
|
|
187
79
|
PMR_PATH: 'pmr_path',
|
|
188
80
|
RAW_COMBINE_ARCHIVE: 'raw_combine_archive',
|
|
189
|
-
})
|
|
81
|
+
});
|
|
190
82
|
|
|
191
83
|
function isWebProtocol(urlString) {
|
|
192
84
|
try {
|
|
193
|
-
const url = new URL(urlString)
|
|
85
|
+
const url = new URL(urlString);
|
|
194
86
|
// Protocol property includes the colon, e.g., "https:".
|
|
195
|
-
return url.protocol ===
|
|
87
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
196
88
|
} catch (_err) {
|
|
197
89
|
// String was not a valid URL.
|
|
198
|
-
return false
|
|
90
|
+
return false;
|
|
199
91
|
}
|
|
200
92
|
}
|
|
201
93
|
|
|
@@ -203,7 +95,7 @@ function isWebProtocol(urlString) {
|
|
|
203
95
|
* SimulationVuer
|
|
204
96
|
*/
|
|
205
97
|
export default {
|
|
206
|
-
name:
|
|
98
|
+
name: "SimulationVuer",
|
|
207
99
|
components: {
|
|
208
100
|
PlotVuer,
|
|
209
101
|
SimulationVuerInput,
|
|
@@ -235,39 +127,39 @@ export default {
|
|
|
235
127
|
data: function () {
|
|
236
128
|
// Determine the ID's type.
|
|
237
129
|
|
|
238
|
-
let idType
|
|
130
|
+
let idType;
|
|
239
131
|
|
|
240
|
-
if (typeof this.id ===
|
|
241
|
-
idType = IdType.DATASET_ID
|
|
132
|
+
if (typeof this.id === "number") {
|
|
133
|
+
idType = IdType.DATASET_ID;
|
|
242
134
|
} else if (this.id instanceof Uint8Array) {
|
|
243
|
-
idType = IdType.RAW_COMBINE_ARCHIVE
|
|
135
|
+
idType = IdType.RAW_COMBINE_ARCHIVE;
|
|
244
136
|
} else if (isWebProtocol(this.id)) {
|
|
245
|
-
idType = IdType.DATASET_URL
|
|
137
|
+
idType = IdType.DATASET_URL;
|
|
246
138
|
} else {
|
|
247
|
-
idType = IdType.PMR_PATH
|
|
139
|
+
idType = IdType.PMR_PATH;
|
|
248
140
|
}
|
|
249
141
|
|
|
250
142
|
// Retrieve some information about the dataset.
|
|
251
143
|
|
|
252
144
|
if (idType === IdType.DATASET_ID) {
|
|
253
|
-
const xmlhttp = new XMLHttpRequest()
|
|
145
|
+
const xmlhttp = new XMLHttpRequest();
|
|
254
146
|
|
|
255
|
-
xmlhttp.open(
|
|
147
|
+
xmlhttp.open("GET", this.apiLocation + "/sim/dataset/" + this.id);
|
|
256
148
|
xmlhttp.onreadystatechange = () => {
|
|
257
149
|
if (xmlhttp.readyState === 4) {
|
|
258
150
|
if (xmlhttp.status === 200) {
|
|
259
|
-
const datasetInfo = JSON.parse(xmlhttp.responseText)
|
|
151
|
+
const datasetInfo = JSON.parse(xmlhttp.responseText);
|
|
260
152
|
|
|
261
|
-
this.name = datasetInfo.name
|
|
262
|
-
this.uuid = datasetInfo.study !== undefined ? datasetInfo.study.uuid : undefined
|
|
153
|
+
this.name = datasetInfo.name;
|
|
154
|
+
this.uuid = (datasetInfo.study !== undefined) ? datasetInfo.study.uuid : undefined;
|
|
263
155
|
}
|
|
264
156
|
}
|
|
265
|
-
}
|
|
266
|
-
xmlhttp.send()
|
|
157
|
+
};
|
|
158
|
+
xmlhttp.send();
|
|
267
159
|
}
|
|
268
160
|
|
|
269
161
|
return {
|
|
270
|
-
errorMessage:
|
|
162
|
+
errorMessage: "",
|
|
271
163
|
fileManager: undefined,
|
|
272
164
|
hasFinalisedUi: false,
|
|
273
165
|
hasValidSimulationUiInfo: false,
|
|
@@ -289,12 +181,210 @@ export default {
|
|
|
289
181
|
simulationResultsId: {},
|
|
290
182
|
simulationUiInfo: {},
|
|
291
183
|
solver: undefined,
|
|
292
|
-
userMessage:
|
|
184
|
+
userMessage: "",
|
|
293
185
|
ui: null,
|
|
294
186
|
uuid: null,
|
|
295
|
-
|
|
187
|
+
activeSubscriptions: [],
|
|
188
|
+
};
|
|
296
189
|
},
|
|
297
190
|
methods: {
|
|
191
|
+
/**
|
|
192
|
+
* @public
|
|
193
|
+
* Add a data subscription.
|
|
194
|
+
* @arg `subscription `
|
|
195
|
+
*/
|
|
196
|
+
addDataSubscription(subscription) {
|
|
197
|
+
// Check that the subscription is valid.
|
|
198
|
+
|
|
199
|
+
if (!subscription || typeof subscription !== 'object') {
|
|
200
|
+
console.error('addDataSubscription: subscription must be an object.');
|
|
201
|
+
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Check that the subscription has the expected ID.
|
|
206
|
+
|
|
207
|
+
const EXPECTED_ID = 'nz.ac.auckland.simulation-data-request';
|
|
208
|
+
const EXPECTED_MAJOR_VERSION = 0;
|
|
209
|
+
|
|
210
|
+
if (subscription.id !== EXPECTED_ID) {
|
|
211
|
+
console.warn(`addDataSubscription: invalid ID (expected '${EXPECTED_ID}' but got '${subscription.id}').`);
|
|
212
|
+
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Check that the version is valid and compatible with what we expect.
|
|
217
|
+
|
|
218
|
+
if (typeof subscription.version !== 'string') {
|
|
219
|
+
console.warn(`addDataSubscription: missing or non-string version ('${subscription.version}').`);
|
|
220
|
+
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const versionParts = subscription.version.split('.');
|
|
225
|
+
|
|
226
|
+
if (versionParts.length < 1 || !/^[0-9]+$/.test(versionParts[0])) {
|
|
227
|
+
console.warn(`addDataSubscription: malformed version ('${subscription.version}').`);
|
|
228
|
+
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const subscriptionMajorVersion = parseInt(versionParts[0], 10);
|
|
233
|
+
|
|
234
|
+
if (Number.isNaN(subscriptionMajorVersion)) {
|
|
235
|
+
console.warn(`addDataSubscription: could not parse the major version from ('${subscription.version}')`);
|
|
236
|
+
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (subscriptionMajorVersion !== EXPECTED_MAJOR_VERSION) {
|
|
241
|
+
console.warn(`addDataSubscription: version mismatch (expected v${EXPECTED_MAJOR_VERSION}.y.z but got v${subscription.version}).`);
|
|
242
|
+
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check that the payload contains the required fields.
|
|
247
|
+
|
|
248
|
+
const payload = subscription.payload || {};
|
|
249
|
+
const missing = [];
|
|
250
|
+
|
|
251
|
+
if (payload.windowId == null) {
|
|
252
|
+
missing.push('windowId');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (payload.ownerId == null) {
|
|
256
|
+
missing.push('ownerId');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (!payload.component) {
|
|
260
|
+
missing.push('component');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (!payload.variable) {
|
|
264
|
+
missing.push('variable');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (missing.length) {
|
|
268
|
+
console.warn(`addDataSubscription: payload missing fields: ${missing.join(', ')}.`);
|
|
269
|
+
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// The subscription is valid, so add it to our list of active subscriptions.
|
|
274
|
+
|
|
275
|
+
this.activeSubscriptions.push(payload);
|
|
276
|
+
|
|
277
|
+
// Ask OpenCOR to track the simulation data associated with the subscription's component and variable (and the
|
|
278
|
+
// VOI, if requested).
|
|
279
|
+
|
|
280
|
+
const modelParameters = [];
|
|
281
|
+
|
|
282
|
+
if (subscription.payload?.withVOI) {
|
|
283
|
+
modelParameters.push('VOI');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
modelParameters.push(`${subscription.payload?.component}/${subscription.payload?.variable}`);
|
|
287
|
+
|
|
288
|
+
this.$refs.opencorRef?.trackSimulationData(modelParameters);
|
|
289
|
+
},
|
|
290
|
+
/**
|
|
291
|
+
* @public
|
|
292
|
+
* Remove a data subscription.
|
|
293
|
+
* @arg `subscriptionId `
|
|
294
|
+
*/
|
|
295
|
+
removeDataSubscription(subscriptionId) {
|
|
296
|
+
// Ask OpenCOR to stop tracking the simulation data associated with the subscription's component and variable (and
|
|
297
|
+
// the VOI, if requested and unless it's requested by another subscription).
|
|
298
|
+
|
|
299
|
+
const subscription = this.activeSubscriptions.find((activeSubscription) => {
|
|
300
|
+
return activeSubscription.windowId === subscriptionId;
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
if (!subscription) {
|
|
304
|
+
console.warn(`removeDataSubscription: no active subscription found for id ${subscriptionId}.`);
|
|
305
|
+
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const isVoiTrackedByAnotherSubscription = this.activeSubscriptions.some((activeSubscription) => {
|
|
310
|
+
return activeSubscription.windowId !== subscriptionId && activeSubscription.withVOI;
|
|
311
|
+
});
|
|
312
|
+
const isModelParameterTrackedByAnotherSubscription = this.activeSubscriptions.some((activeSubscription) => {
|
|
313
|
+
return (
|
|
314
|
+
activeSubscription.windowId !== subscriptionId &&
|
|
315
|
+
activeSubscription.component === subscription.component &&
|
|
316
|
+
activeSubscription.variable === subscription.variable
|
|
317
|
+
);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
if (!isVoiTrackedByAnotherSubscription || !isModelParameterTrackedByAnotherSubscription) {
|
|
321
|
+
const modelParameters = [];
|
|
322
|
+
|
|
323
|
+
if (subscription.withVOI && !isVoiTrackedByAnotherSubscription) {
|
|
324
|
+
modelParameters.push('VOI');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (!isModelParameterTrackedByAnotherSubscription) {
|
|
328
|
+
modelParameters.push(`${subscription.component}/${subscription.variable}`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (modelParameters.length) {
|
|
332
|
+
this.$refs.opencorRef?.untrackSimulationData(modelParameters);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Remove the subscription from our list of active subscriptions.
|
|
337
|
+
|
|
338
|
+
this.activeSubscriptions = this.activeSubscriptions.filter((activeSubscription) => {
|
|
339
|
+
return activeSubscription.windowId !== subscriptionId;
|
|
340
|
+
});
|
|
341
|
+
},
|
|
342
|
+
/**
|
|
343
|
+
* @public
|
|
344
|
+
* Let the outside world know that we have received some simulation data from OpenCOR by emitting a `data-notification` event.
|
|
345
|
+
* @arg `event`
|
|
346
|
+
*/
|
|
347
|
+
onSimulationData(event) {
|
|
348
|
+
const simulationData = event.simulationData || {};
|
|
349
|
+
let voi;
|
|
350
|
+
|
|
351
|
+
this.activeSubscriptions.forEach((activeSubscription) => {
|
|
352
|
+
const modelParameter = `${activeSubscription.component}/${activeSubscription.variable}`;
|
|
353
|
+
|
|
354
|
+
if (simulationData[modelParameter] == null) {
|
|
355
|
+
console.warn(`onSimulationData: no data for ${modelParameter}.`);
|
|
356
|
+
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const data = {
|
|
361
|
+
y: Array.from(simulationData[modelParameter]),
|
|
362
|
+
title: `${activeSubscription.component}.${activeSubscription.variable}`,
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
if (activeSubscription.withVOI) {
|
|
366
|
+
if (simulationData.VOI == null) {
|
|
367
|
+
console.warn('onSimulationData: no data for VOI.');
|
|
368
|
+
|
|
369
|
+
return;
|
|
370
|
+
} else {
|
|
371
|
+
voi ??= Array.from(simulationData.VOI);
|
|
372
|
+
|
|
373
|
+
data.x = voi;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
this.$emit('data-notification', {
|
|
378
|
+
id: 'nz.ac.auckland.simulation-data-response',
|
|
379
|
+
version: '0.1.0',
|
|
380
|
+
payload: {
|
|
381
|
+
windowId: activeSubscription.windowId,
|
|
382
|
+
ownerId: activeSubscription.ownerId,
|
|
383
|
+
data,
|
|
384
|
+
},
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
},
|
|
298
388
|
/**
|
|
299
389
|
* @public
|
|
300
390
|
* Generate the metadata associated with the plot which `index` is given.
|
|
@@ -302,13 +392,13 @@ export default {
|
|
|
302
392
|
*/
|
|
303
393
|
plotMetadata(index) {
|
|
304
394
|
return {
|
|
305
|
-
version:
|
|
306
|
-
type:
|
|
395
|
+
version: "1.1.0",
|
|
396
|
+
type: "plot",
|
|
307
397
|
attrs: {
|
|
308
|
-
style:
|
|
398
|
+
style: "timeseries",
|
|
309
399
|
layout: this.layout[index],
|
|
310
400
|
},
|
|
311
|
-
}
|
|
401
|
+
};
|
|
312
402
|
},
|
|
313
403
|
/**
|
|
314
404
|
* @public
|
|
@@ -318,49 +408,49 @@ export default {
|
|
|
318
408
|
buildSimulationUi(simulationUiInfo) {
|
|
319
409
|
// Keep track of the simulation UI information.
|
|
320
410
|
|
|
321
|
-
this.simulationUiInfo = simulationUiInfo
|
|
411
|
+
this.simulationUiInfo = simulationUiInfo;
|
|
322
412
|
|
|
323
413
|
// Make sure that the simulation UI information is valid.
|
|
324
414
|
|
|
325
|
-
this.hasValidSimulationUiInfo = validJson(this.simulationUiInfo)
|
|
415
|
+
this.hasValidSimulationUiInfo = validJson(this.simulationUiInfo);
|
|
326
416
|
|
|
327
417
|
if (!this.hasValidSimulationUiInfo) {
|
|
328
|
-
this.errorMessage =
|
|
418
|
+
this.errorMessage = "the simulation.json file is malformed";
|
|
329
419
|
|
|
330
|
-
return
|
|
420
|
+
return;
|
|
331
421
|
}
|
|
332
422
|
|
|
333
423
|
// Retrieve and keep track of the solver to be used for the simulation.
|
|
334
424
|
|
|
335
425
|
this.simulationUiInfo.simulation.solvers.forEach((solver) => {
|
|
336
|
-
if (solver.if === undefined || evaluateValue(this, solver.if)) {
|
|
337
|
-
this.solver = solver
|
|
426
|
+
if ((solver.if === undefined) || evaluateValue(this, solver.if)) {
|
|
427
|
+
this.solver = solver;
|
|
338
428
|
}
|
|
339
|
-
})
|
|
429
|
+
});
|
|
340
430
|
|
|
341
431
|
if (this.solver === undefined) {
|
|
342
|
-
this.hasValidSimulationUiInfo = false
|
|
343
|
-
this.errorMessage =
|
|
432
|
+
this.hasValidSimulationUiInfo = false;
|
|
433
|
+
this.errorMessage = "no solver name and/or solver version specified";
|
|
344
434
|
|
|
345
|
-
return
|
|
435
|
+
return;
|
|
346
436
|
}
|
|
347
437
|
|
|
348
|
-
this.opencorBasedSimulation = this.solver.name === OPENCOR_SOLVER_NAME
|
|
438
|
+
this.opencorBasedSimulation = this.solver.name === OPENCOR_SOLVER_NAME;
|
|
349
439
|
|
|
350
440
|
// Initialise our UI.
|
|
351
441
|
|
|
352
442
|
this.simulationUiInfo.output.data.forEach((data) => {
|
|
353
|
-
this.simulationResultsId[data.id] = data.name
|
|
354
|
-
})
|
|
443
|
+
this.simulationResultsId[data.id] = data.name;
|
|
444
|
+
});
|
|
355
445
|
|
|
356
|
-
let index = -1
|
|
446
|
+
let index = -1;
|
|
357
447
|
|
|
358
448
|
this.simulationUiInfo.output.plots.forEach((outputPlot) => {
|
|
359
|
-
++index
|
|
449
|
+
++index;
|
|
360
450
|
|
|
361
451
|
this.layout[index] = {
|
|
362
|
-
paper_bgcolor:
|
|
363
|
-
plot_bgcolor:
|
|
452
|
+
paper_bgcolor: "rgba(0, 0, 0, 0)",
|
|
453
|
+
plot_bgcolor: "rgba(0, 0, 0, 0)",
|
|
364
454
|
autosize: true,
|
|
365
455
|
margin: {
|
|
366
456
|
t: 25,
|
|
@@ -374,7 +464,7 @@ export default {
|
|
|
374
464
|
responsive: true,
|
|
375
465
|
scrollZoom: true,
|
|
376
466
|
},
|
|
377
|
-
dragmode:
|
|
467
|
+
dragmode: "pan",
|
|
378
468
|
xaxis: {
|
|
379
469
|
title: {
|
|
380
470
|
text: outputPlot.xAxisTitle,
|
|
@@ -391,8 +481,8 @@ export default {
|
|
|
391
481
|
},
|
|
392
482
|
},
|
|
393
483
|
},
|
|
394
|
-
}
|
|
395
|
-
})
|
|
484
|
+
};
|
|
485
|
+
});
|
|
396
486
|
|
|
397
487
|
// Finalise our UI.
|
|
398
488
|
// Note: we try both here and in the mounted() function since we have no
|
|
@@ -400,8 +490,8 @@ export default {
|
|
|
400
490
|
// information.
|
|
401
491
|
|
|
402
492
|
this.$nextTick(() => {
|
|
403
|
-
finaliseUi(this)
|
|
404
|
-
})
|
|
493
|
+
finaliseUi(this);
|
|
494
|
+
});
|
|
405
495
|
},
|
|
406
496
|
/**
|
|
407
497
|
* @public
|
|
@@ -410,7 +500,7 @@ export default {
|
|
|
410
500
|
* method.
|
|
411
501
|
*/
|
|
412
502
|
runOnOsparc() {
|
|
413
|
-
window.open(`https://osparc.io/study/${this.uuid}`,
|
|
503
|
+
window.open(`https://osparc.io/study/${this.uuid}`, "_blank");
|
|
414
504
|
},
|
|
415
505
|
/**
|
|
416
506
|
* @public
|
|
@@ -418,7 +508,7 @@ export default {
|
|
|
418
508
|
* clicked, calls this method.
|
|
419
509
|
*/
|
|
420
510
|
viewDataset() {
|
|
421
|
-
window.open(`https://sparc.science/datasets/${this.id}?type=dataset`,
|
|
511
|
+
window.open(`https://sparc.science/datasets/${this.id}?type=dataset`, "_blank");
|
|
422
512
|
},
|
|
423
513
|
/**
|
|
424
514
|
* @public
|
|
@@ -426,22 +516,22 @@ export default {
|
|
|
426
516
|
* calls this method.
|
|
427
517
|
*/
|
|
428
518
|
viewWorkspace() {
|
|
429
|
-
const url = PMR_URL + this.id
|
|
519
|
+
const url = PMR_URL + this.id;
|
|
430
520
|
|
|
431
|
-
window.open(url.substring(0, url.lastIndexOf(
|
|
521
|
+
window.open(url.substring(0, url.lastIndexOf("/")), "_blank");
|
|
432
522
|
},
|
|
433
523
|
/**
|
|
434
524
|
* @public
|
|
435
525
|
* Data needed to set a model's parameters.
|
|
436
526
|
*/
|
|
437
527
|
parametersData() {
|
|
438
|
-
const res = {}
|
|
528
|
+
const res = {};
|
|
439
529
|
|
|
440
530
|
this.simulationUiInfo.parameters.forEach((parameter) => {
|
|
441
|
-
res[parameter.name] = evaluateValue(this, parameter.value)
|
|
442
|
-
})
|
|
531
|
+
res[parameter.name] = evaluateValue(this, parameter.value);
|
|
532
|
+
});
|
|
443
533
|
|
|
444
|
-
return res
|
|
534
|
+
return res;
|
|
445
535
|
},
|
|
446
536
|
/**
|
|
447
537
|
* @public
|
|
@@ -450,15 +540,15 @@ export default {
|
|
|
450
540
|
outputData() {
|
|
451
541
|
if (this.output === undefined) {
|
|
452
542
|
if (this.simulationUiInfo.output.data !== undefined) {
|
|
453
|
-
this.output = []
|
|
543
|
+
this.output = [];
|
|
454
544
|
|
|
455
545
|
this.simulationUiInfo.output.data.forEach((output) => {
|
|
456
|
-
this.output.push(output.name)
|
|
457
|
-
})
|
|
546
|
+
this.output.push(output.name);
|
|
547
|
+
});
|
|
458
548
|
}
|
|
459
549
|
}
|
|
460
550
|
|
|
461
|
-
return this.output
|
|
551
|
+
return this.output;
|
|
462
552
|
},
|
|
463
553
|
/**
|
|
464
554
|
* @public
|
|
@@ -466,39 +556,37 @@ export default {
|
|
|
466
556
|
*/
|
|
467
557
|
retrieveRequest() {
|
|
468
558
|
const request = {
|
|
469
|
-
solver: this.solver
|
|
470
|
-
}
|
|
559
|
+
solver: this.solver
|
|
560
|
+
};
|
|
471
561
|
|
|
472
562
|
if (this.opencorBasedSimulation) {
|
|
473
563
|
request.opencor = {
|
|
474
564
|
model_url: this.simulationUiInfo.simulation.opencor.resource,
|
|
475
565
|
json_config: {},
|
|
476
|
-
}
|
|
566
|
+
};
|
|
477
567
|
|
|
478
|
-
if (
|
|
479
|
-
this.simulationUiInfo.simulation.opencor.
|
|
480
|
-
this.simulationUiInfo.simulation.opencor.pointInterval !== undefined
|
|
481
|
-
) {
|
|
568
|
+
if ((this.simulationUiInfo.simulation.opencor.endingPoint !== undefined)
|
|
569
|
+
&& (this.simulationUiInfo.simulation.opencor.pointInterval !== undefined)) {
|
|
482
570
|
request.opencor.json_config.simulation = {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
571
|
+
"Ending point": this.simulationUiInfo.simulation.opencor.endingPoint,
|
|
572
|
+
"Point interval": this.simulationUiInfo.simulation.opencor.pointInterval,
|
|
573
|
+
};
|
|
486
574
|
}
|
|
487
575
|
|
|
488
|
-
request.opencor.json_config.parameters = this.parametersData()
|
|
576
|
+
request.opencor.json_config.parameters = this.parametersData();
|
|
489
577
|
|
|
490
|
-
const output = this.outputData()
|
|
578
|
+
const output = this.outputData();
|
|
491
579
|
|
|
492
580
|
if (output !== undefined) {
|
|
493
|
-
request.opencor.json_config.output = output
|
|
581
|
+
request.opencor.json_config.output = output;
|
|
494
582
|
}
|
|
495
583
|
} else {
|
|
496
|
-
request.osparc = {}
|
|
584
|
+
request.osparc = {};
|
|
497
585
|
|
|
498
|
-
request.osparc.job_inputs = this.parametersData()
|
|
586
|
+
request.osparc.job_inputs = this.parametersData();
|
|
499
587
|
}
|
|
500
588
|
|
|
501
|
-
return request
|
|
589
|
+
return request;
|
|
502
590
|
},
|
|
503
591
|
/**
|
|
504
592
|
* @public
|
|
@@ -510,50 +598,50 @@ export default {
|
|
|
510
598
|
// Convert, if needed, the results to a JSON format that is compatible
|
|
511
599
|
// with our OpenCOR results.
|
|
512
600
|
|
|
513
|
-
if (typeof results ===
|
|
514
|
-
const SPACES = /[ \t]+/g
|
|
515
|
-
const lines = results.trim().split(
|
|
516
|
-
const iMax = lines[0].trim().split(SPACES).length
|
|
601
|
+
if (typeof (results) === "string") {
|
|
602
|
+
const SPACES = /[ \t]+/g;
|
|
603
|
+
const lines = results.trim().split("\n");
|
|
604
|
+
const iMax = lines[0].trim().split(SPACES).length;
|
|
517
605
|
|
|
518
|
-
results = {}
|
|
606
|
+
results = {};
|
|
519
607
|
|
|
520
608
|
for (let i = 0; i < iMax; ++i) {
|
|
521
|
-
results[i] = []
|
|
609
|
+
results[i] = [];
|
|
522
610
|
}
|
|
523
611
|
|
|
524
|
-
let i = -1
|
|
612
|
+
let i = -1;
|
|
525
613
|
|
|
526
614
|
lines.forEach((line) => {
|
|
527
|
-
++i
|
|
615
|
+
++i;
|
|
528
616
|
|
|
529
|
-
let j = -1
|
|
530
|
-
const values = line.trim().split(SPACES)
|
|
617
|
+
let j = -1;
|
|
618
|
+
const values = line.trim().split(SPACES);
|
|
531
619
|
|
|
532
620
|
values.forEach((value) => {
|
|
533
|
-
results[++j][i] = Number(value)
|
|
534
|
-
})
|
|
535
|
-
})
|
|
621
|
+
results[++j][i] = Number(value);
|
|
622
|
+
});
|
|
623
|
+
});
|
|
536
624
|
}
|
|
537
625
|
|
|
538
626
|
// Get the results ready for plotting.
|
|
539
627
|
|
|
540
|
-
const parser = new math.parser()
|
|
628
|
+
const parser = new math.parser();
|
|
541
629
|
|
|
542
630
|
Object.keys(this.simulationResultsId).forEach((id) => {
|
|
543
|
-
parser.set(id, results[this.simulationResultsId[id]])
|
|
544
|
-
})
|
|
631
|
+
parser.set(id, results[this.simulationResultsId[id]]);
|
|
632
|
+
});
|
|
545
633
|
|
|
546
|
-
let index = -1
|
|
634
|
+
let index = -1;
|
|
547
635
|
|
|
548
636
|
this.simulationUiInfo.output.plots.forEach((outputPlot) => {
|
|
549
637
|
this.simulationResults[++index] = [
|
|
550
638
|
{
|
|
551
639
|
x: parser.evaluate(outputPlot.xValue),
|
|
552
640
|
y: parser.evaluate(outputPlot.yValue),
|
|
553
|
-
type:
|
|
641
|
+
type: "scatter",
|
|
554
642
|
},
|
|
555
|
-
]
|
|
556
|
-
})
|
|
643
|
+
];
|
|
644
|
+
});
|
|
557
645
|
},
|
|
558
646
|
/**
|
|
559
647
|
* @public
|
|
@@ -561,15 +649,9 @@ export default {
|
|
|
561
649
|
* @arg `xmlhttp`
|
|
562
650
|
*/
|
|
563
651
|
showHttpIssue(xmlhttp) {
|
|
564
|
-
this.isSimulationValid = false
|
|
565
|
-
this.showUserMessage = false
|
|
566
|
-
this.errorMessage =
|
|
567
|
-
xmlhttp.statusText.toLowerCase() +
|
|
568
|
-
" (<a href='https://httpstatuses.com/" +
|
|
569
|
-
xmlhttp.status +
|
|
570
|
-
"/' target='_blank'>" +
|
|
571
|
-
xmlhttp.status +
|
|
572
|
-
'</a>)'
|
|
652
|
+
this.isSimulationValid = false;
|
|
653
|
+
this.showUserMessage = false;
|
|
654
|
+
this.errorMessage = xmlhttp.statusText.toLowerCase() + " (<a href='https://httpstatuses.com/" + xmlhttp.status + "/' target='_blank'>" + xmlhttp.status + "</a>)";
|
|
573
655
|
},
|
|
574
656
|
/**
|
|
575
657
|
* @public
|
|
@@ -581,44 +663,44 @@ export default {
|
|
|
581
663
|
checkSimulation(data) {
|
|
582
664
|
// Check the simulation.
|
|
583
665
|
|
|
584
|
-
const xmlhttp = new XMLHttpRequest()
|
|
666
|
+
const xmlhttp = new XMLHttpRequest();
|
|
585
667
|
|
|
586
|
-
xmlhttp.open(
|
|
587
|
-
xmlhttp.setRequestHeader(
|
|
668
|
+
xmlhttp.open("POST", this.apiLocation + "/check_simulation");
|
|
669
|
+
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
588
670
|
xmlhttp.onreadystatechange = () => {
|
|
589
671
|
if (xmlhttp.readyState === 4) {
|
|
590
672
|
if (xmlhttp.status === 200) {
|
|
591
|
-
let response = JSON.parse(xmlhttp.responseText)
|
|
673
|
+
let response = JSON.parse(xmlhttp.responseText);
|
|
592
674
|
|
|
593
|
-
this.isSimulationValid = response.status ===
|
|
675
|
+
this.isSimulationValid = response.status === "ok";
|
|
594
676
|
|
|
595
677
|
if (this.isSimulationValid) {
|
|
596
678
|
if (response.results !== undefined) {
|
|
597
679
|
// The simulation is finished, so process its results.
|
|
598
680
|
|
|
599
|
-
this.showUserMessage = false
|
|
681
|
+
this.showUserMessage = false;
|
|
600
682
|
|
|
601
|
-
this.processSimulationResults(response.results)
|
|
683
|
+
this.processSimulationResults(response.results);
|
|
602
684
|
} else {
|
|
603
685
|
// The simulation is not yet finished, so check again in a
|
|
604
686
|
// second.
|
|
605
687
|
|
|
606
|
-
let that = this
|
|
688
|
+
let that = this;
|
|
607
689
|
|
|
608
690
|
setTimeout(function () {
|
|
609
|
-
that.checkSimulation(data)
|
|
610
|
-
}, 1000)
|
|
691
|
+
that.checkSimulation(data);
|
|
692
|
+
}, 1000);
|
|
611
693
|
}
|
|
612
694
|
} else {
|
|
613
|
-
this.showUserMessage = false
|
|
614
|
-
this.errorMessage = response.description
|
|
695
|
+
this.showUserMessage = false;
|
|
696
|
+
this.errorMessage = response.description;
|
|
615
697
|
}
|
|
616
698
|
} else {
|
|
617
|
-
this.showHttpIssue(xmlhttp)
|
|
699
|
+
this.showHttpIssue(xmlhttp);
|
|
618
700
|
}
|
|
619
701
|
}
|
|
620
|
-
}
|
|
621
|
-
xmlhttp.send(JSON.stringify(data))
|
|
702
|
+
};
|
|
703
|
+
xmlhttp.send(JSON.stringify(data));
|
|
622
704
|
},
|
|
623
705
|
/**
|
|
624
706
|
* @public
|
|
@@ -629,73 +711,72 @@ export default {
|
|
|
629
711
|
// Start the simulation (after resetting our previous simulation data, in
|
|
630
712
|
// case there were sonme).
|
|
631
713
|
|
|
632
|
-
this.userMessage =
|
|
633
|
-
this.showUserMessage = true
|
|
714
|
+
this.userMessage = "Loading simulation results...";
|
|
715
|
+
this.showUserMessage = true;
|
|
634
716
|
|
|
635
717
|
this.$nextTick(() => {
|
|
636
|
-
this.simulationResults = {}
|
|
718
|
+
this.simulationResults = {};
|
|
637
719
|
|
|
638
|
-
const xmlhttp = new XMLHttpRequest()
|
|
720
|
+
const xmlhttp = new XMLHttpRequest();
|
|
639
721
|
|
|
640
|
-
xmlhttp.open(
|
|
641
|
-
xmlhttp.setRequestHeader(
|
|
722
|
+
xmlhttp.open("POST", this.apiLocation + "/start_simulation");
|
|
723
|
+
xmlhttp.setRequestHeader("Content-type", "application/json");
|
|
642
724
|
xmlhttp.onreadystatechange = () => {
|
|
643
725
|
if (xmlhttp.readyState === 4) {
|
|
644
726
|
if (xmlhttp.status === 200) {
|
|
645
|
-
let response = JSON.parse(xmlhttp.responseText)
|
|
727
|
+
let response = JSON.parse(xmlhttp.responseText);
|
|
646
728
|
|
|
647
|
-
this.isSimulationValid = response.status ===
|
|
729
|
+
this.isSimulationValid = response.status === "ok";
|
|
648
730
|
|
|
649
731
|
if (this.isSimulationValid) {
|
|
650
|
-
this.checkSimulation(response.data)
|
|
732
|
+
this.checkSimulation(response.data);
|
|
651
733
|
} else {
|
|
652
|
-
this.showUserMessage = false
|
|
653
|
-
this.errorMessage = response.description
|
|
734
|
+
this.showUserMessage = false;
|
|
735
|
+
this.errorMessage = response.description;
|
|
654
736
|
}
|
|
655
737
|
} else {
|
|
656
|
-
this.showHttpIssue(xmlhttp)
|
|
738
|
+
this.showHttpIssue(xmlhttp);
|
|
657
739
|
}
|
|
658
740
|
}
|
|
659
|
-
}
|
|
660
|
-
xmlhttp.send(JSON.stringify(this.retrieveRequest()))
|
|
661
|
-
})
|
|
741
|
+
};
|
|
742
|
+
xmlhttp.send(JSON.stringify(this.retrieveRequest()));
|
|
743
|
+
});
|
|
662
744
|
},
|
|
663
745
|
},
|
|
664
746
|
created: function () {
|
|
665
747
|
// Try to retrieve the UI information.
|
|
666
748
|
|
|
667
749
|
if (this.idType === IdType.DATASET_ID) {
|
|
668
|
-
this.userMessage =
|
|
669
|
-
this.showUserMessage = true
|
|
750
|
+
this.userMessage = "Retrieving UI information...";
|
|
751
|
+
this.showUserMessage = true;
|
|
670
752
|
|
|
671
753
|
// Retrieve and build the simulation UI.
|
|
672
754
|
|
|
673
755
|
this.$nextTick(() => {
|
|
674
|
-
const xmlhttp = new XMLHttpRequest()
|
|
756
|
+
const xmlhttp = new XMLHttpRequest();
|
|
675
757
|
|
|
676
|
-
xmlhttp.open(
|
|
758
|
+
xmlhttp.open("GET", this.apiLocation + "/simulation_ui_file/" + this.id);
|
|
677
759
|
xmlhttp.onreadystatechange = () => {
|
|
678
760
|
if (xmlhttp.readyState === 4) {
|
|
679
|
-
this.showUserMessage = false
|
|
761
|
+
this.showUserMessage = false;
|
|
680
762
|
|
|
681
763
|
if (xmlhttp.status === 200) {
|
|
682
764
|
this.$nextTick(() => {
|
|
683
|
-
this.buildSimulationUi(JSON.parse(xmlhttp.responseText))
|
|
684
|
-
})
|
|
765
|
+
this.buildSimulationUi(JSON.parse(xmlhttp.responseText));
|
|
766
|
+
});
|
|
685
767
|
} else {
|
|
686
|
-
this.errorMessage =
|
|
768
|
+
this.errorMessage = "the simulation dataset could not be retrieved";
|
|
687
769
|
}
|
|
688
770
|
}
|
|
689
|
-
}
|
|
690
|
-
xmlhttp.send()
|
|
691
|
-
})
|
|
771
|
+
};
|
|
772
|
+
xmlhttp.send();
|
|
773
|
+
});
|
|
692
774
|
} else if (this.idType === IdType.DATASET_URL) {
|
|
693
|
-
this.opencorOmexFile = this.id
|
|
775
|
+
this.opencorOmexFile = this.id;
|
|
694
776
|
} else if (this.idType === IdType.PMR_PATH) {
|
|
695
|
-
this.opencorOmexFile = PMR_URL + this.id
|
|
696
|
-
} else {
|
|
697
|
-
|
|
698
|
-
this.opencorOmexFile = this.id
|
|
777
|
+
this.opencorOmexFile = PMR_URL + this.id;
|
|
778
|
+
} else { // IdType.RAW_COMBINE_ARCHIVE
|
|
779
|
+
this.opencorOmexFile = this.id;
|
|
699
780
|
}
|
|
700
781
|
},
|
|
701
782
|
mounted: function () {
|
|
@@ -704,20 +785,20 @@ export default {
|
|
|
704
785
|
// idea how long it's going to take to retrieve the simulation UI
|
|
705
786
|
// information.
|
|
706
787
|
|
|
707
|
-
this.isMounted = true
|
|
788
|
+
this.isMounted = true;
|
|
708
789
|
|
|
709
|
-
finaliseUi(this)
|
|
790
|
+
finaliseUi(this);
|
|
710
791
|
},
|
|
711
|
-
}
|
|
792
|
+
};
|
|
712
793
|
</script>
|
|
713
794
|
|
|
714
795
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
715
796
|
<style scoped lang="scss">
|
|
716
797
|
.simulation-vuer {
|
|
717
|
-
--el-color-primary: #
|
|
718
|
-
--el-color-primary-light-7: #
|
|
719
|
-
--el-color-primary-light-8: #
|
|
720
|
-
--el-color-primary-light-9: #
|
|
798
|
+
--el-color-primary: #8300BF;
|
|
799
|
+
--el-color-primary-light-7: #DAB3EC;
|
|
800
|
+
--el-color-primary-light-8: #E6CCF2;
|
|
801
|
+
--el-color-primary-light-9: #F3E6F9;
|
|
721
802
|
}
|
|
722
803
|
|
|
723
804
|
:deep(.el-button:hover) {
|
|
@@ -731,32 +812,29 @@ export default {
|
|
|
731
812
|
|
|
732
813
|
:deep(.el-loading-spinner) {
|
|
733
814
|
.path {
|
|
734
|
-
stroke: #
|
|
815
|
+
stroke: #8300BF;
|
|
735
816
|
}
|
|
736
817
|
|
|
737
818
|
i,
|
|
738
819
|
.el-loading-text {
|
|
739
|
-
color: #
|
|
820
|
+
color: #8300BF;
|
|
740
821
|
}
|
|
741
822
|
}
|
|
742
823
|
|
|
743
|
-
:deep(.p-floatlabel:has(input:focus)) label,
|
|
744
|
-
:
|
|
745
|
-
:deep(.p-floatlabel:has(textarea:focus)) label,
|
|
746
|
-
:deep(.p-floatlabel:has(.p-inputwrapper-focus)) label {
|
|
747
|
-
color: #8300bf;
|
|
824
|
+
:deep(.p-floatlabel:has(input:focus)) label, :deep(.p-floatlabel:has(input:-webkit-autofill)) label, :deep(.p-floatlabel:has(textarea:focus)) label, :deep(.p-floatlabel:has(.p-inputwrapper-focus)) label {
|
|
825
|
+
color: #8300BF;
|
|
748
826
|
}
|
|
749
827
|
|
|
750
828
|
:deep(.p-inputtext:enabled:focus) {
|
|
751
|
-
|
|
829
|
+
border-color: #8300BF;
|
|
752
830
|
}
|
|
753
831
|
|
|
754
832
|
:deep(.p-select:not(.p-disabled).p-focus) {
|
|
755
|
-
|
|
833
|
+
border-color: #8300BF;
|
|
756
834
|
}
|
|
757
835
|
|
|
758
836
|
:deep(.p-slider-range) {
|
|
759
|
-
background-color: #
|
|
837
|
+
background-color: #8300BF;
|
|
760
838
|
}
|
|
761
839
|
|
|
762
840
|
div.input {
|
|
@@ -958,23 +1036,26 @@ span.error {
|
|
|
958
1036
|
<style>
|
|
959
1037
|
/* Note: not sure why, but the following rules need to be global!? */
|
|
960
1038
|
|
|
1039
|
+
.p-progressbar-value {
|
|
1040
|
+
background-color: #8300BF !important;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
961
1043
|
.p-select-option:not(.p-select-option-selected):not(.p-disabled).p-focus {
|
|
962
|
-
|
|
1044
|
+
background: #F5F7FA !important;
|
|
963
1045
|
}
|
|
964
1046
|
|
|
965
1047
|
.p-select-option.p-select-option-selected.p-focus {
|
|
966
|
-
|
|
967
|
-
|
|
1048
|
+
background: #F5F7FA !important;
|
|
1049
|
+
color: #8300BF !important;
|
|
968
1050
|
}
|
|
969
1051
|
|
|
970
1052
|
.p-select-option.p-select-option-selected {
|
|
971
|
-
|
|
972
|
-
|
|
1053
|
+
background: white !important;
|
|
1054
|
+
color: #8300BF !important;
|
|
973
1055
|
}
|
|
974
1056
|
|
|
975
1057
|
.p-select-option-label {
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
font-size: 0.875rem;
|
|
1058
|
+
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
|
1059
|
+
font-size: 0.875rem;
|
|
979
1060
|
}
|
|
980
1061
|
</style>
|