@abi-software/scaffoldvuer 0.1.1 → 0.1.5-1.beta.0

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/package.json CHANGED
@@ -1,6 +1,18 @@
1
1
  {
2
2
  "name": "@abi-software/scaffoldvuer",
3
- "version": "0.1.1",
3
+ "version": "0.1.51.beta.0",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/ABI-Software/scaffoldvuer.git"
8
+ },
9
+ "scripts": {
10
+ "serve": "vue-cli-service serve --port 8081",
11
+ "lint": "vue-cli-service lint --ext .js,.vue src",
12
+ "build-bundle": "vue-cli-service build --target lib --name scaffoldvuer ./src/components/index.js",
13
+ "styleguide": "vue-cli-service styleguidist",
14
+ "styleguide:build": "vue-cli-service styleguidist:build"
15
+ },
4
16
  "main": "./dist/scaffoldvuer.common.js",
5
17
  "files": [
6
18
  "dist/*",
@@ -9,26 +21,37 @@
9
21
  "*.json",
10
22
  "*.js"
11
23
  ],
12
- "scripts": {
13
- "serve": "vue-cli-service serve",
14
- "build": "vue-cli-service build",
15
- "build-bundle": "vue-cli-service build --target lib --name scaffoldvuer ./src/components/index.js",
16
- "lint": "vue-cli-service lint"
17
- },
18
24
  "dependencies": {
25
+ "@abi-software/svg-sprite": "^0.1.13",
26
+ "axios": "^0.21.2",
19
27
  "core-js": "^3.3.2",
20
- "physiomeportal": "^0.4.9",
21
- "vue": "^2.6.10"
28
+ "current-script-polyfill": "^1.0.0",
29
+ "element-ui": "^2.13.0",
30
+ "google-spreadsheet": "^3.1.15",
31
+ "lodash": "^4.17.21",
32
+ "physiomeportal": "^0.4.27",
33
+ "query-string": "^6.11.1",
34
+ "vue": "^2.6.10",
35
+ "vue-drag-resize": "^1.3.2",
36
+ "vue-router": "^3.5.1",
37
+ "zincjs": "^0.40.0"
22
38
  },
23
39
  "devDependencies": {
24
40
  "@vue/cli-plugin-babel": "^4.0.0",
25
41
  "@vue/cli-plugin-eslint": "^4.0.0",
26
- "@vue/cli-service": "^4.0.0",
42
+ "@vue/cli-service": "^4.5.13",
27
43
  "babel-eslint": "^10.0.3",
44
+ "babel-plugin-component": "^1.1.1",
45
+ "base64-inline-loader": "^1.1.1",
28
46
  "eslint": "^5.16.0",
29
47
  "eslint-plugin-vue": "^5.0.0",
48
+ "node-sass": "^4.14.1",
49
+ "raw-loader": "^0.5.1",
50
+ "sass-loader": "^8.0.2",
51
+ "vue-cli-plugin-styleguidist": "^4.32.2",
52
+ "vue-styleguidist": "^4.38.1",
30
53
  "vue-template-compiler": "^2.6.10",
31
- "raw-loader": "^0.5.1"
54
+ "webpack-node-externals": "^2.5.2"
32
55
  },
33
56
  "eslintConfig": {
34
57
  "root": true,
package/src/App.vue CHANGED
@@ -1,29 +1,390 @@
1
1
  <template>
2
2
  <div id="app">
3
- <ScaffoldVuer url="https://mapcore-bucket1.s3-us-west-2.amazonaws.com/ISAN/scaffold/use_case4/rat_heart_metadata.json"/>
3
+ <link
4
+ rel="stylesheet"
5
+ href="https://fonts.googleapis.com/css?family=Asap:400,400i,500,600,700&display=swap"
6
+ >
7
+ <ScaffoldVuer
8
+ ref="scaffold"
9
+ class="vuer"
10
+ :display-u-i="displayUI"
11
+ :url="url"
12
+ :help-mode="helpMode"
13
+ :display-minimap="displayMinimap"
14
+ :display-markers="displayMarkers"
15
+ :minimap-settings="minimapSettings"
16
+ :show-colour-picker="showColourPicker"
17
+ :render="render"
18
+ :region="region"
19
+ :view-u-r-l="viewURL"
20
+ @scaffold-selected="onSelected"
21
+ @timeChanged="updateCurrentTime"
22
+ />
23
+ <el-popover
24
+ placement="bottom"
25
+ trigger="click"
26
+ width="500"
27
+ class="popover"
28
+ :append-to-body="false"
29
+ >
30
+ <div class="options-container">
31
+ <el-row :gutter="20">
32
+ <p>{{ selectedCoordinates }}</p>
33
+ </el-row>
34
+ <el-row
35
+ class="app-row"
36
+ :gutter="20"
37
+ >
38
+ <p v-if="currentTime!==0">
39
+ time emited is: {{ currentTime.toFixed(2) }}
40
+ </p>
41
+ </el-row>
42
+ <el-row :gutter="20">
43
+ <el-col
44
+ :span="6"
45
+ :offset="2"
46
+ >
47
+ <el-switch
48
+ v-model="displayMarkers"
49
+ active-text="Markers"
50
+ active-icon-class="el-icon-location"
51
+ active-color="#8300bf"
52
+ />
53
+ </el-col>
54
+ <el-col
55
+ :span="6"
56
+ :offset="2"
57
+ >
58
+ <el-switch
59
+ v-model="displayMinimap"
60
+ active-text="Minimap"
61
+ active-icon-class="el-icon-discover"
62
+ active-color="#8300bf"
63
+ />
64
+ </el-col>
65
+ <el-col
66
+ :span="6"
67
+ :offset="2"
68
+ >
69
+ <el-switch
70
+ v-model="tumbleOn"
71
+ active-text="Tumble"
72
+ active-color="#8300bf"
73
+ />
74
+ </el-col>
75
+ </el-row>
76
+ <el-row :gutter="20">
77
+ <el-button
78
+ size="mini"
79
+ @click="helpMode = !helpMode"
80
+ >
81
+ Help Mode
82
+ </el-button>
83
+ <el-button
84
+ size="mini"
85
+ @click="screenCapture()"
86
+ >
87
+ Capture
88
+ </el-button>
89
+ </el-row>
90
+ <el-row :gutter="20">
91
+ <el-button
92
+ size="mini"
93
+ @click="saveSettings()"
94
+ >
95
+ Save Settings
96
+ </el-button>
97
+ <el-button
98
+ size="mini"
99
+ @click="restoreSettings()"
100
+ >
101
+ Restore Settings
102
+ </el-button>
103
+ <el-button
104
+ size="mini"
105
+ @click="exportGLB()"
106
+ >
107
+ Export GLTF
108
+ </el-button>
109
+ </el-row>
110
+ <el-row :gutter="20">
111
+ <el-row :gutter="20">
112
+ <el-switch
113
+ v-model="render"
114
+ active-text="Rendering"
115
+ active-color="#8300bf"
116
+ />
117
+ </el-row>
118
+ </el-row>
119
+ <el-input
120
+ v-model="input"
121
+ type="textarea"
122
+ autosize
123
+ placeholder="Please input"
124
+ style="padding-left:5%;width:90%;"
125
+ />
126
+ </div>
127
+ <el-button
128
+ slot="reference"
129
+ icon="el-icon-setting"
130
+ >
131
+ Options
132
+ </el-button>
133
+ </el-popover>
134
+ <el-popover
135
+ placement="bottom"
136
+ trigger="click"
137
+ width="800"
138
+ class="models-popover"
139
+ popper-class="table-popover"
140
+ :append-to-body="false"
141
+ >
142
+ <ModelsTable @viewModelClicked="viewModelClicked" />
143
+ <el-button
144
+ slot="reference"
145
+ icon="el-icon-folder-opened"
146
+ >
147
+ Models
148
+ </el-button>
149
+ </el-popover>
4
150
  </div>
5
151
  </template>
6
152
 
7
153
  <script>
8
- import ScaffoldVuer from './components/ScaffoldVuer.vue'
154
+ /* eslint-disable no-alert, no-console */
155
+ import { ScaffoldVuer } from "./components/index.js";
156
+ import ModelsTable from "./components/ModelsTable.vue";
157
+ import Vue from "vue";
158
+ import { Button, Col, Icon, Input, Popover, Row, Switch } from "element-ui";
159
+ import lang from "element-ui/lib/locale/lang/en";
160
+ import locale from "element-ui/lib/locale";
9
161
 
162
+ locale.use(lang);
163
+ Vue.use(Button);
164
+ Vue.use(Col);
165
+ Vue.use(Icon);
166
+ Vue.use(Input);
167
+ Vue.use(Popover);
168
+ Vue.use(Row);
169
+ Vue.use(Switch);
170
+
171
+ /*
172
+ const alignToObject = function(cameracontrol, scene) {
173
+ var object = scene.findGeometriesWithGroupName("Endocardium of left atrium")[0];
174
+ const boundingBox = object.getBoundingBox();
175
+ if (boundingBox) {
176
+ const radius = boundingBox.min.distanceTo(boundingBox.max)/2.0;
177
+ const centreX = (boundingBox.min.x + boundingBox.max.x) / 2.0;
178
+ const centreY = (boundingBox.min.y + boundingBox.max.y) / 2.0;
179
+ const centreZ = (boundingBox.min.z + boundingBox.max.z) / 2.0;
180
+ const clip_factor = 8.0;
181
+ const endingViewport = cameracontrol.getViewportFromCentreAndRadius(centreX, centreY, centreZ, radius, 40, radius * clip_factor );
182
+ const startingViewport = cameracontrol.getCurrentViewport();
183
+ cameracontrol.cameraTransition(startingViewport, endingViewport, 1500);
184
+ cameracontrol.enableCameraTransition();
185
+ }
186
+ setTimeout(function(){ tumble(cameracontrol) }, 2000);
187
+ }
188
+
189
+ const tumble = function(cameracontrol) {
190
+ cameracontrol.enableAutoTumble();
191
+ cameracontrol.autoTumble([1.0, 0.0], Math.PI / 2, true);
192
+ }
193
+ */
10
194
  export default {
11
- name: 'app',
195
+ name: "App",
12
196
  components: {
13
- ScaffoldVuer
197
+ ScaffoldVuer,
198
+ ModelsTable
199
+ },
200
+ data: function() {
201
+ return {
202
+ url: undefined,
203
+ input: undefined,
204
+ displayUI: true,
205
+ selectedCoordinates: undefined,
206
+ helpMode: false,
207
+ displayMarkers: true,
208
+ currentTime: 0,
209
+ displayMinimap: true,
210
+ tumbleOn: false,
211
+ showColourPicker: true,
212
+ minimapSettings: {
213
+ x_offset: 16,
214
+ y_offset: 50,
215
+ width: 128,
216
+ height: 128,
217
+ align: "top-right"
218
+ },
219
+ render: true,
220
+ region: "",
221
+ viewURL: ""
222
+ };
223
+ },
224
+ watch: {
225
+ input: function() {
226
+ this.parseInput();
227
+ },
228
+ tumbleOn: function(val) {
229
+ this.autoTumble(val);
230
+ },
231
+ "$route.query": {
232
+ handler: "parseQuery",
233
+ deep: true,
234
+ immediate: true
235
+ }
236
+ },
237
+
238
+ mounted: function() {
239
+ this._sceneSettings = [];
240
+ this.selectedCoordinates = this.$refs.scaffold.getDynamicSelectedCoordinates();
241
+ },
242
+ methods: {
243
+ exportGLTF: function() {
244
+ this.$refs.scaffold.exportGLTF(false)
245
+ .then(data =>{
246
+ let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data));
247
+ let hrefElement = document.createElement("a");
248
+ document.body.append(hrefElement);
249
+ hrefElement.download = `export.gltf`;
250
+ hrefElement.href = dataStr;
251
+ hrefElement.click();
252
+ hrefElement.remove();
253
+ })
254
+ },
255
+ exportGLB: function() {
256
+ this.$refs.scaffold.exportGLTF(true)
257
+ .then(data =>{
258
+ let blob = new Blob([data], {type: "octet/stream"});
259
+ let url = window.URL.createObjectURL(blob);
260
+ let hrefElement = document.createElement("a");
261
+ document.body.append(hrefElement);
262
+ hrefElement.download = `export.glb`;
263
+ hrefElement.href = url;
264
+ hrefElement.click();
265
+ hrefElement.remove();
266
+ })
267
+ },
268
+ saveSettings: function() {
269
+ this._sceneSettings.push(this.$refs.scaffold.getState());
270
+ },
271
+ restoreSettings: function() {
272
+ if (this._sceneSettings.length > 0)
273
+ this.$refs.scaffold.setState(this._sceneSettings.pop());
274
+ },
275
+ viewModelClicked: function(location) {
276
+ this.input = location;
277
+ },
278
+ screenCapture: function() {
279
+ this.$refs.scaffold.captureScreenshot("capture.png");
280
+ },
281
+ autoTumble: function(flag) {
282
+ let cameracontrol = this.$refs.scaffold.$module.scene.getZincCameraControls();
283
+ if (flag) {
284
+ this.displayUI = false;
285
+ cameracontrol.enableAutoTumble();
286
+ cameracontrol.autoTumble([1.0, 0.0], Math.PI / 2, true);
287
+ } else {
288
+ this.displayUI = true;
289
+ cameracontrol.stopAutoTumble();
290
+ }
291
+ },
292
+ onSelected: function(data) {
293
+ if (data && data[0].data.group) {
294
+ delete this.$route.query["viewURL"];
295
+ this.$router.replace({
296
+ query: { ...this.$route.query, region: data[0].data.group }
297
+ });
298
+ }
299
+ },
300
+ parseInput: function() {
301
+ if (this.$route.query.url !== this.input)
302
+ this.$router.replace({
303
+ query: { ...this.$route.query, url: this.input }
304
+ });
305
+ },
306
+ updateCurrentTime: function(val) {
307
+ this.currentTime = val;
308
+ },
309
+ parseQuery: function(query) {
310
+ if (query.url) {
311
+ this.url = query.url;
312
+ } else {
313
+ this.url =
314
+ "https://mapcore-bucket1.s3-us-west-2.amazonaws.com/others/29_Jan_2020/heartICN_metadata.json";
315
+ }
316
+ this.input = this.url;
317
+ if (query.region) {
318
+ this.region = query.region;
319
+ } else {
320
+ this.region = "";
321
+ }
322
+ if (query.viewURL) {
323
+ this.viewURL = query.viewURL;
324
+ } else {
325
+ this.viewURL = "";
326
+ }
327
+ }
14
328
  }
15
- }
329
+ };
16
330
  </script>
17
331
 
18
- <style>
332
+ <style lang="scss">
333
+ @import "~element-ui/packages/theme-chalk/src/button";
334
+ @import "~element-ui/packages/theme-chalk/src/col";
335
+ @import "~element-ui/packages/theme-chalk/src/icon";
336
+ @import "~element-ui/packages/theme-chalk/src/input";
337
+ @import "~element-ui/packages/theme-chalk/src/switch";
338
+ @import "~element-ui/packages/theme-chalk/src/popover";
339
+ @import "~element-ui/packages/theme-chalk/src/row";
340
+
19
341
  #app {
20
- font-family: 'Avenir', Helvetica, Arial, sans-serif;
342
+ font-family: "Asap", sans-serif;
21
343
  -webkit-font-smoothing: antialiased;
22
344
  -moz-osx-font-smoothing: grayscale;
23
345
  text-align: center;
24
346
  color: #2c3e50;
25
- height:100%;
347
+ height: 100%;
26
348
  width: 100%;
27
- position:absolute;
349
+ position: absolute;
350
+ overflow: hidden;
351
+ }
352
+
353
+ body {
354
+ margin: 0px;
355
+ }
356
+
357
+ .options-container {
358
+ text-align: center;
359
+ }
360
+
361
+ .vuer {
362
+ position: absolute;
363
+ width: 100%;
364
+ height: 100%;
365
+ }
366
+
367
+ .popover {
368
+ top: 5px;
369
+ right: 10px;
370
+ position: absolute;
371
+ }
372
+
373
+ .app-row {
374
+ .el-row {
375
+ margin-bottom: 5px;
376
+ &:last-child {
377
+ margin-bottom: 0;
378
+ }
379
+ }
380
+ }
381
+
382
+ .models-popover {
383
+ top: 5px;
384
+ position: absolute;
385
+ }
386
+
387
+ .table-popover {
388
+ opacity: 0.9;
28
389
  }
29
390
  </style>
@@ -0,0 +1,43 @@
1
+ // Primary colors
2
+ $purple: #8300BF;
3
+ $darkBlue: #24245B;
4
+ $grey: #303133;
5
+
6
+ // Secondary colors
7
+ $lightPurple: #BC00FC;
8
+ $blue: #0026FF;
9
+
10
+ // Status colors
11
+ $success: #5e9f69;
12
+ $warning: #FF8400;
13
+ $danger: #b51d09;
14
+
15
+ // Text colors
16
+ $neutralGrey: #616161;
17
+ $mediumGrey: #606266;
18
+ $lightGrey: #909399;
19
+
20
+ // Line colors
21
+ $lineColor1: #DCDFE6;
22
+ $lineColor2: #E4E7ED;
23
+
24
+ // Background colors
25
+ $background: #F5F7FA;
26
+ $cochlear: #FFFFFF;
27
+
28
+ //Search box colors
29
+ $darkGrey: #606266;
30
+
31
+ $app-primary-color: $purple;
32
+ $app-secondary-color: $darkBlue;
33
+ $text-color: $grey;
34
+ $input-text: $grey;
35
+
36
+ $system-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
37
+ $font-family: 'Asap', sans-serif;
38
+
39
+ // Viewport Sizes
40
+ $viewport-sm: 20rem;
41
+ $viewport-md: 47rem;
42
+ $viewport-lg: 64rem;
43
+ $viewport-xlg: 120rem;
@@ -0,0 +1,7 @@
1
+ @import url('https://fonts.googleapis.com/css?family=Asap:400,400i,500,600,700&display=swap');
2
+
3
+ @import '_variables';
4
+
5
+ /* icon font path, required */
6
+ $--color-primary: $app-primary-color !default;
7
+ $--font-path: '~element-ui/lib/theme-chalk/fonts';
@@ -0,0 +1,35 @@
1
+ const { GoogleSpreadsheet } = require('google-spreadsheet');
2
+
3
+ /* eslint-disable no-alert, no-console */
4
+ export default {
5
+ data: function() {
6
+ return {
7
+ tableData: [],
8
+ };
9
+ },
10
+ methods: {
11
+ createTable: async function(sheetRows, keywords) {
12
+ for (let i = 0; i < sheetRows.length; i++) {
13
+ let mappedData = {};
14
+ for (let j = 0; j < keywords.length; j++) {
15
+ let keyword = keywords[j];
16
+ mappedData[keyword] = sheetRows[i][keyword];
17
+ }
18
+ this.tableData.push(mappedData);
19
+ }
20
+ },
21
+ getModelsInformation: async function() {
22
+ const doc = new GoogleSpreadsheet(process.env.VUE_APP_GOOGLE_SPREADSHEET_ID);
23
+ await doc.useServiceAccountAuth({
24
+ client_email: process.env.VUE_APP_GOOGLE_SERVICE_SCAFFOLDVUER_EMAIL,
25
+ private_key: process.env.VUE_APP_GOOGLE_PRIVATE_SCAFFOLDVUER_KEY,
26
+ });
27
+ await doc.loadInfo(); // loads document properties and worksheets
28
+ const sheet = doc.sheetsByIndex[0];
29
+ const sheetRows = await sheet.getRows();
30
+ const keys = ["Organ", "Species", "Note", "Location",
31
+ "Last modified","Blackfynn dataset", "Published", "Discover"];
32
+ this.createTable(sheetRows, keys);
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,113 @@
1
+ <template>
2
+ <div>
3
+ <el-input
4
+ v-model="search"
5
+ size="mini"
6
+ placeholder="Type to search"
7
+ />
8
+ <el-table
9
+ :data="tableData.filter(
10
+ data => !search ||
11
+ data.Organ.toLowerCase().includes(search.toLowerCase()) ||
12
+ data.Species.toLowerCase().includes(search.toLowerCase()) ||
13
+ data.Note.toLowerCase().includes(search.toLowerCase()))"
14
+ style="width: 100%;"
15
+ height="600"
16
+ >
17
+ <el-table-column
18
+ prop="Organ"
19
+ label="Organ"
20
+ width="100"
21
+ />
22
+ <el-table-column
23
+ prop="Species"
24
+ label="Species"
25
+ width="100"
26
+ />
27
+ <el-table-column
28
+ prop="Note"
29
+ label="Note"
30
+ width="200"
31
+ />
32
+ <el-table-column
33
+ prop="Last modified"
34
+ label="Last modified"
35
+ width="250"
36
+ />
37
+ <el-table-column
38
+ fixed="right"
39
+ label="Action"
40
+ width="300"
41
+ >
42
+ <template slot-scope="scope">
43
+ <el-button
44
+ size="mini"
45
+ @click="handleView(scope.row)"
46
+ >
47
+ View
48
+ </el-button>
49
+ <el-button
50
+ v-if="scope.row.Discover !== 'Not even'"
51
+ size="mini"
52
+ @click="handleDiscover(scope.row)"
53
+ >
54
+ Discover
55
+ </el-button>
56
+ <el-button
57
+ v-if="scope.row['Blackfynn dataset'] !== '/'"
58
+ size="mini"
59
+ @click="handleBlackfynn(scope.row)"
60
+ >
61
+ Blackfynn
62
+ </el-button>
63
+ </template>
64
+ </el-table-column>
65
+ </el-table>
66
+ </div>
67
+ </template>
68
+
69
+ <script>
70
+ /* eslint-disable no-alert, no-console */
71
+ import Vue from "vue";
72
+ import models from './ModelsInformation'
73
+ import { Button, Input, Table, TableColumn } from "element-ui";
74
+ import lang from "element-ui/lib/locale/lang/en";
75
+ import locale from "element-ui/lib/locale";
76
+
77
+ locale.use(lang);
78
+ Vue.use(Button);
79
+ Vue.use(Input);
80
+ Vue.use(Table);
81
+ Vue.use(TableColumn);
82
+
83
+
84
+ export default {
85
+ name: "ModelsTable",
86
+ mixins: [models],
87
+ data() {
88
+ return {
89
+ search: '',
90
+ }
91
+ },
92
+ created: function() {
93
+ this.getModelsInformation();
94
+ },
95
+ methods: {
96
+ handleView: function(row) {
97
+ this.$emit("viewModelClicked", row.Location);
98
+ },
99
+ handleDiscover: function(row) {
100
+ window.open(row.Discover, "_blank");
101
+ },
102
+ handleBlackfynn: function(row) {
103
+ window.open(row['Blackfynn dataset'], "_blank");
104
+ },
105
+ }
106
+ };
107
+ </script>
108
+
109
+ <style scoped lang="scss">
110
+ @import "~element-ui/packages/theme-chalk/src/input";
111
+ @import "~element-ui/packages/theme-chalk/src/table";
112
+ @import "~element-ui/packages/theme-chalk/src/table-column";
113
+ </style>