glib-web 4.8.0 → 4.8.1
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/LICENSE +0 -0
- package/actions/auth/restart.js +0 -0
- package/actions/commands/copy.js +0 -0
- package/actions/dialogs/notification.js +0 -0
- package/actions/dialogs/oauth.js +0 -0
- package/actions/dialogs/reload.js +0 -0
- package/actions/http/delete.js +0 -0
- package/actions/logics/set.js +5 -1
- package/actions/sheets/select.js +0 -0
- package/actions/snackbars/select.js +0 -0
- package/actions/windows/openWeb.js +0 -0
- package/actions/windows/print.js +0 -0
- package/components/_message.vue +0 -0
- package/components/component.vue +2 -0
- package/components/fields/multiUpload.vue +21 -6
- package/components/fields/phone/countries.js +0 -0
- package/components/fields/phone/sprite.css +0 -0
- package/components/fields/radio/_featured.vue +9 -10
- package/components/fields/radio.vue +7 -12
- package/components/h1.vue +0 -0
- package/components/h2.vue +0 -0
- package/components/h3.vue +0 -0
- package/components/h5.vue +0 -0
- package/components/h6.vue +0 -0
- package/components/hr.vue +0 -0
- package/components/html.vue +0 -0
- package/components/icon.vue +0 -0
- package/components/mixins/extension.js +0 -0
- package/components/mixins/longClick.js +0 -0
- package/components/mixins/scrolling.js +0 -0
- package/components/mixins/table/export.js +0 -0
- package/components/mixins/table/import.js +45 -9
- package/components/mixins/text.js +0 -0
- package/components/multimedia/video.vue +0 -0
- package/components/panels/bulkEdit.vue +298 -0
- package/keys.js +0 -0
- package/package.json +1 -1
- package/plugins/vuetify.js +5 -4
- package/static/plugins/alignment/alignment.js +0 -0
- package/static/plugins/alignment/alignment.min.js +0 -0
- package/static/plugins/beyondgrammar/beyondgrammar.js +0 -0
- package/static/plugins/beyondgrammar/beyondgrammar.min.js +0 -0
- package/static/plugins/blockcode/blockcode.js +0 -0
- package/static/plugins/blockcode/blockcode.min.js +0 -0
- package/static/plugins/clips/clips.js +0 -0
- package/static/plugins/clips/clips.min.js +0 -0
- package/static/plugins/counter/counter.js +0 -0
- package/static/plugins/counter/counter.min.js +0 -0
- package/static/plugins/definedlinks/definedlinks.js +0 -0
- package/static/plugins/definedlinks/definedlinks.min.js +0 -0
- package/static/plugins/handle/handle.js +0 -0
- package/static/plugins/handle/handle.min.js +0 -0
- package/static/plugins/icons/icons.js +0 -0
- package/static/plugins/icons/icons.min.js +0 -0
- package/static/plugins/imageposition/imageposition.js +0 -0
- package/static/plugins/imageposition/imageposition.min.js +0 -0
- package/static/plugins/inlineformat/inlineformat.js +0 -0
- package/static/plugins/inlineformat/inlineformat.min.js +0 -0
- package/static/plugins/removeformat/removeformat.js +0 -0
- package/static/plugins/removeformat/removeformat.min.js +0 -0
- package/static/plugins/selector/selector.js +0 -0
- package/static/plugins/selector/selector.min.js +0 -0
- package/static/plugins/specialchars/specialchars.js +0 -0
- package/static/plugins/specialchars/specialchars.min.js +0 -0
- package/static/plugins/textdirection/textdirection.js +0 -0
- package/static/plugins/textdirection/textdirection.min.js +0 -0
- package/static/plugins/textexpander/textexpander.js +0 -0
- package/static/plugins/textexpander/textexpander.min.js +0 -0
- package/static/plugins/underline/underline.js +0 -0
- package/static/plugins/underline/underline.min.js +0 -0
- package/static/redactorx.css +0 -0
- package/static/redactorx.min.css +0 -0
- package/static/redactorx.min.js +0 -0
- package/static/redactorx.usm.min.js +0 -0
- package/styles/test.sass +0 -0
- package/styles/test.scss +0 -0
- package/templates/unsupported.vue +0 -0
- package/utils/dom.js +0 -0
- package/utils/helper.js +0 -0
- package/utils/type.js +3 -0
package/LICENSE
CHANGED
|
File without changes
|
package/actions/auth/restart.js
CHANGED
|
File without changes
|
package/actions/commands/copy.js
CHANGED
|
File without changes
|
|
File without changes
|
package/actions/dialogs/oauth.js
CHANGED
|
File without changes
|
|
File without changes
|
package/actions/http/delete.js
CHANGED
|
File without changes
|
package/actions/logics/set.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import jsonLogic from 'json-logic-js';
|
|
2
2
|
import { fieldModels } from "../../components/composable/conditional";
|
|
3
3
|
import merge from 'lodash.merge';
|
|
4
|
+
import { nextTick } from "vue";
|
|
4
5
|
|
|
5
6
|
const subscript = function (a, b) {
|
|
6
7
|
if (a) {
|
|
@@ -78,6 +79,9 @@ export default class {
|
|
|
78
79
|
});
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
// Make sure the update performed by the above `action_merge()` has been reflected.
|
|
83
|
+
nextTick(() => {
|
|
84
|
+
GLib.action.execute(spec.onSet, component);
|
|
85
|
+
})
|
|
82
86
|
}
|
|
83
87
|
}
|
package/actions/sheets/select.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/actions/windows/print.js
CHANGED
|
File without changes
|
package/components/_message.vue
CHANGED
|
File without changes
|
package/components/component.vue
CHANGED
|
@@ -103,6 +103,7 @@ import FormPanel from "./panels/form.vue";
|
|
|
103
103
|
import ListPanel from "./panels/list.vue";
|
|
104
104
|
import CarouselPanel from "./panels/carousel.vue";
|
|
105
105
|
import TablePanel from "./panels/table.vue";
|
|
106
|
+
import BulkEditPanel from "./panels/bulkEdit.vue";
|
|
106
107
|
import CustomPanel from "./panels/custom.vue";
|
|
107
108
|
import ColumnPanel from "./panels/column.vue";
|
|
108
109
|
import ResponsivePanel from "./panels/responsive.vue";
|
|
@@ -198,6 +199,7 @@ export default {
|
|
|
198
199
|
"panels-list": ListPanel,
|
|
199
200
|
"panels-carousel": CarouselPanel,
|
|
200
201
|
"panels-table": TablePanel,
|
|
202
|
+
"panels-bulkEdit": BulkEditPanel,
|
|
201
203
|
"panels-custom": CustomPanel,
|
|
202
204
|
"panels-responsive": ResponsivePanel,
|
|
203
205
|
"panels-column": ColumnPanel,
|
|
@@ -38,12 +38,14 @@
|
|
|
38
38
|
</div>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
41
|
-
<
|
|
42
|
-
<div class="
|
|
43
|
-
<div class="
|
|
41
|
+
<Transition name="slide-fade">
|
|
42
|
+
<div class="percentage-wrapper " v-show="file[1].progress.value > 0 && !file[1].message">
|
|
43
|
+
<div class="background">
|
|
44
|
+
<div class="value" :style="{ width: `${file[1].progress.value}%` }"></div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="percentage">{{ parseInt(file[1].progress.value) }}%</div>
|
|
44
47
|
</div>
|
|
45
|
-
|
|
46
|
-
</div>
|
|
48
|
+
</Transition>
|
|
47
49
|
</div>
|
|
48
50
|
</template>
|
|
49
51
|
</div>
|
|
@@ -52,6 +54,19 @@
|
|
|
52
54
|
</template>
|
|
53
55
|
|
|
54
56
|
<style>
|
|
57
|
+
.slide-fade-enter-active {
|
|
58
|
+
transition: all 0.3s ease-out;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.slide-fade-leave-active {
|
|
62
|
+
transition: all 1s cubic-bezier(1, 0.5, 0.8, 1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.slide-fade-enter-from,
|
|
66
|
+
.slide-fade-leave-to {
|
|
67
|
+
opacity: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
55
70
|
.border-\[2px\] {
|
|
56
71
|
border-width: 2px;
|
|
57
72
|
}
|
|
@@ -375,7 +390,7 @@ export default defineComponent({
|
|
|
375
390
|
props,
|
|
376
391
|
doc,
|
|
377
392
|
pic,
|
|
378
|
-
pdf
|
|
393
|
+
pdf
|
|
379
394
|
};
|
|
380
395
|
}
|
|
381
396
|
})
|
|
File without changes
|
|
File without changes
|
|
@@ -29,13 +29,12 @@ export default {
|
|
|
29
29
|
align-items: center;
|
|
30
30
|
justify-content: center;
|
|
31
31
|
width: 240px;
|
|
32
|
-
height:
|
|
32
|
+
height: 100%;
|
|
33
33
|
transition: border-color 0.3s, box-shadow 0.3s, color 0.3s;
|
|
34
34
|
text-align: center;
|
|
35
35
|
cursor: pointer;
|
|
36
|
-
padding: 16px;
|
|
37
36
|
position: relative;
|
|
38
|
-
border:
|
|
37
|
+
border: 2px solid #E6E6E6;
|
|
39
38
|
border-radius: 24px;
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -56,18 +55,15 @@ export default {
|
|
|
56
55
|
align-items: center;
|
|
57
56
|
justify-content: center;
|
|
58
57
|
width: 100%;
|
|
59
|
-
|
|
60
|
-
margin-right: 30px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.custom-radio .custom-radio-icon {
|
|
64
|
-
margin-bottom: 8px;
|
|
58
|
+
padding: 40px;
|
|
65
59
|
}
|
|
66
60
|
|
|
67
61
|
.custom-radio .custom-radio-label {
|
|
68
62
|
font-size: 22px;
|
|
69
63
|
color: inherit;
|
|
70
|
-
margin-top:
|
|
64
|
+
margin-top: 24px;
|
|
65
|
+
word-break: break-word;
|
|
66
|
+
min-width: 180px;
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
.custom-radio ::v-deep .v-selection-control__input {
|
|
@@ -90,6 +86,9 @@ export default {
|
|
|
90
86
|
display: none;
|
|
91
87
|
}
|
|
92
88
|
|
|
89
|
+
.custom-radio ::v-deep .v-selection-control__wrapper {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
93
92
|
|
|
94
93
|
.custom-radio .v-ripple__container {
|
|
95
94
|
display: none;
|
|
@@ -38,13 +38,12 @@ export default {
|
|
|
38
38
|
align-items: center;
|
|
39
39
|
justify-content: center;
|
|
40
40
|
width: 240px;
|
|
41
|
-
height: 254px;
|
|
41
|
+
min-height: 254px;
|
|
42
42
|
transition: border-color 0.3s, box-shadow 0.3s, color 0.3s;
|
|
43
43
|
text-align: center;
|
|
44
44
|
cursor: pointer;
|
|
45
|
-
padding: 16px;
|
|
46
45
|
position: relative;
|
|
47
|
-
border:
|
|
46
|
+
border: 2px solid #E6E6E6;
|
|
48
47
|
border-radius: 24px;
|
|
49
48
|
}
|
|
50
49
|
|
|
@@ -65,20 +64,13 @@ export default {
|
|
|
65
64
|
align-items: center;
|
|
66
65
|
justify-content: center;
|
|
67
66
|
width: 100%;
|
|
68
|
-
|
|
69
|
-
margin-right: 30px;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.custom-radio .custom-radio-icon {
|
|
73
|
-
width: 80px;
|
|
74
|
-
height: 80px;
|
|
75
|
-
margin-bottom: 8px;
|
|
67
|
+
padding: 40px;
|
|
76
68
|
}
|
|
77
69
|
|
|
78
70
|
.custom-radio .custom-radio-label {
|
|
79
71
|
font-size: 22px;
|
|
80
72
|
color: inherit;
|
|
81
|
-
margin-top:
|
|
73
|
+
margin-top: 24px;
|
|
82
74
|
}
|
|
83
75
|
|
|
84
76
|
.custom-radio ::v-deep .v-selection-control__input {
|
|
@@ -101,6 +93,9 @@ export default {
|
|
|
101
93
|
display: none;
|
|
102
94
|
}
|
|
103
95
|
|
|
96
|
+
.custom-radio ::v-deep .v-selection-control__wrapper {
|
|
97
|
+
display: none;
|
|
98
|
+
}
|
|
104
99
|
|
|
105
100
|
.custom-radio .v-ripple__container {
|
|
106
101
|
display: none;
|
package/components/h1.vue
CHANGED
|
File without changes
|
package/components/h2.vue
CHANGED
|
File without changes
|
package/components/h3.vue
CHANGED
|
File without changes
|
package/components/h5.vue
CHANGED
|
File without changes
|
package/components/h6.vue
CHANGED
|
File without changes
|
package/components/hr.vue
CHANGED
|
File without changes
|
package/components/html.vue
CHANGED
|
File without changes
|
package/components/icon.vue
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fieldModels } from "../../composable/conditional";
|
|
2
|
+
|
|
1
3
|
export default {
|
|
2
4
|
data: function() {
|
|
3
5
|
return {
|
|
@@ -15,34 +17,61 @@ export default {
|
|
|
15
17
|
vm.importParamName = obj.paramName;
|
|
16
18
|
});
|
|
17
19
|
},
|
|
20
|
+
rowSelected(sectionIndex, rowIndex) {
|
|
21
|
+
return fieldModels[this.rowCheckId(sectionIndex, rowIndex)];
|
|
22
|
+
},
|
|
23
|
+
selectedRowCount(section) {
|
|
24
|
+
const sectionIndex = section.index;
|
|
25
|
+
let count = 0;
|
|
26
|
+
section.dataRows.forEach((_row, rowIndex) => {
|
|
27
|
+
if (this.rowSelected(sectionIndex, rowIndex)) {
|
|
28
|
+
count++;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return count;
|
|
32
|
+
},
|
|
18
33
|
submitRows(event, section) {
|
|
19
|
-
const vm = this;
|
|
20
34
|
const keys = section.header.dataCells;
|
|
21
35
|
const rows = [];
|
|
22
|
-
section.
|
|
36
|
+
const sectionIndex = section.index;
|
|
37
|
+
let count = 0;
|
|
38
|
+
section.dataRows.forEach((row, rowIndex) => {
|
|
39
|
+
if (!this.rowSelected(sectionIndex, rowIndex)) { // Don't submit
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
count++;
|
|
23
44
|
const cells = {};
|
|
24
|
-
row.forEach((cell,
|
|
25
|
-
const key = `${
|
|
45
|
+
row.forEach((cell, cellIndex) => {
|
|
46
|
+
const key = `${this.importParamName}[${keys[cellIndex]}]`;
|
|
26
47
|
cells[key] = cell;
|
|
27
48
|
});
|
|
49
|
+
cells['_index'] = rowIndex;
|
|
28
50
|
rows.push(cells);
|
|
29
51
|
});
|
|
30
52
|
|
|
31
|
-
if (
|
|
32
|
-
|
|
53
|
+
if (count > 0) {
|
|
54
|
+
this._submitEachRow(rows);
|
|
55
|
+
} else {
|
|
56
|
+
Utils.launch.dialog.alert("Please select at least one row.", this);
|
|
33
57
|
}
|
|
34
58
|
},
|
|
35
|
-
_submitEachRow(rows
|
|
59
|
+
_submitEachRow(rows) {
|
|
60
|
+
const url = Utils.type.string(this.importSubmitUrl)
|
|
61
|
+
if (!url) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
36
65
|
const vm = this;
|
|
37
66
|
const row = rows.shift();
|
|
38
67
|
if (row) {
|
|
39
68
|
const data = {
|
|
40
|
-
url:
|
|
69
|
+
url: url,
|
|
41
70
|
formData: row
|
|
42
71
|
};
|
|
43
72
|
Utils.http.execute(data, "POST", vm, response => {
|
|
44
73
|
GLib.action.handleResponse(response, vm);
|
|
45
|
-
vm._submitEachRow(rows
|
|
74
|
+
vm._submitEachRow(rows);
|
|
46
75
|
});
|
|
47
76
|
}
|
|
48
77
|
},
|
|
@@ -55,6 +84,13 @@ export default {
|
|
|
55
84
|
return cell.trim();
|
|
56
85
|
});
|
|
57
86
|
section.dataRows = rows;
|
|
87
|
+
|
|
88
|
+
if (rows.length > 0) {
|
|
89
|
+
this.fileLoaded = true;
|
|
90
|
+
GLib.action.execute(this.spec.onLoadRows, this);
|
|
91
|
+
} else {
|
|
92
|
+
Utils.launch.dialog.alert("File doesn't contain valid data.", this);
|
|
93
|
+
}
|
|
58
94
|
};
|
|
59
95
|
|
|
60
96
|
// Reset value so it will trigger again the next time the same file is selected.
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div :style="$styles()" :class="$classes()">
|
|
3
|
+
<panels-responsive v-if="header" :spec="header" />
|
|
4
|
+
|
|
5
|
+
<div class="scrollable">
|
|
6
|
+
<div ref="topAnchor"></div>
|
|
7
|
+
|
|
8
|
+
<table v-if="loadIf">
|
|
9
|
+
<template v-for="(section, sectionIndex) in sections" :key="`head_${sectionIndex}`">
|
|
10
|
+
<thead>
|
|
11
|
+
<tr v-if="importable || exportable">
|
|
12
|
+
<td colspan="20">
|
|
13
|
+
<div>
|
|
14
|
+
<template v-if="importable && fileLoaded">
|
|
15
|
+
<span>{{ section.dataRows.length }} rows loaded</span> --
|
|
16
|
+
<span>{{ selectedRowCount(section) }} rows selected</span>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<div class="float-right">
|
|
20
|
+
<v-btn v-if="exportable" :download="exportFile" :href="exportCsv(section)">{{ exportLabel }}</v-btn>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div v-if="output" style="white-space: pre-line;">
|
|
25
|
+
{{ output }}
|
|
26
|
+
</div>
|
|
27
|
+
</td>
|
|
28
|
+
</tr>
|
|
29
|
+
|
|
30
|
+
<tr v-if="section.header" :style="$styles(section.header)">
|
|
31
|
+
<template v-if="section.header.dataCells">
|
|
32
|
+
<th class="status" v-if="fileLoaded">
|
|
33
|
+
<glib-component :spec="headerCheckSpec(section)" />
|
|
34
|
+
</th>
|
|
35
|
+
<th class="fixed-width" v-for="(cell, index) in section.header.dataCells" :key="index"
|
|
36
|
+
:colSpan="colSpan(section.header, index)">
|
|
37
|
+
{{ cell }}
|
|
38
|
+
</th>
|
|
39
|
+
</template>
|
|
40
|
+
<th class="fixed-width" v-for="(cell, index) in section.header.cellViews" v-else :key="index"
|
|
41
|
+
:colSpan="colSpan(section.header, index)">
|
|
42
|
+
<glib-component :spec="cell" />
|
|
43
|
+
</th>
|
|
44
|
+
</tr>
|
|
45
|
+
</thead>
|
|
46
|
+
|
|
47
|
+
<tbody>
|
|
48
|
+
<!-- <template v-for="(row, rowIndex) in section.rows" :key="`row_${rowIndex}`">
|
|
49
|
+
<tr :class="row.onClick ? 'clickable' : ''">
|
|
50
|
+
<td v-for="(cell, cellIndex) in row.cellViews" :key="`cell_${cellIndex}`"
|
|
51
|
+
:colSpan="colSpan(row, cellIndex)" :style="colStyles(row, cellIndex)">
|
|
52
|
+
<glib-component :spec="cell" />
|
|
53
|
+
</td>
|
|
54
|
+
</tr>
|
|
55
|
+
</template> -->
|
|
56
|
+
|
|
57
|
+
<tr v-for="(row, rowIndex) in section.dataRows" :key="`data_row_${rowIndex}`">
|
|
58
|
+
<!-- TODO: Make this first column sticky.
|
|
59
|
+
See https://css-tricks.com/a-table-with-both-a-sticky-header-and-a-sticky-first-column/
|
|
60
|
+
-->
|
|
61
|
+
<td class="status" v-if="fileLoaded">
|
|
62
|
+
<glib-component :spec="rowCheckSpec(sectionIndex, rowIndex)" />
|
|
63
|
+
<glib-component :spec="pendingIconSpec(rowIndex)" />
|
|
64
|
+
</td>
|
|
65
|
+
<td v-for="(cell, cellIndex) in row" :key="`data_cell_${cellIndex}`">
|
|
66
|
+
<v-text-field density="compact" variant="solo-filled" v-model="row[cellIndex]" />
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
69
|
+
|
|
70
|
+
<tr v-if="importable && section.dataRows.length <= 0">
|
|
71
|
+
<td colspan="20">
|
|
72
|
+
<!-- TODO: Reuse code from multiUpload so it supports drag-and-drop too -->
|
|
73
|
+
<input ref="fileInput" style="display: none;" type="file" accept=".csv" @change="loadFile($event, section)" />
|
|
74
|
+
<div style="cursor: pointer; border: 1px solid rgba(0, 0, 0, 0.12); text-align: center; padding: 20px; margin: 20px;" @click="triggerImport(sectionIndex)">
|
|
75
|
+
Drag your CSV file here<br />
|
|
76
|
+
or click to browse
|
|
77
|
+
</div>
|
|
78
|
+
</td>
|
|
79
|
+
</tr>
|
|
80
|
+
</tbody>
|
|
81
|
+
</template>
|
|
82
|
+
</table>
|
|
83
|
+
|
|
84
|
+
<div ref="bottomAnchor" class="py-3 px-6" :style="bottomAnchorStyles">
|
|
85
|
+
Loading...
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<panels-responsive v-if="footer" :spec="footer" />
|
|
90
|
+
</div>
|
|
91
|
+
</template>
|
|
92
|
+
|
|
93
|
+
<script>
|
|
94
|
+
import autoloadMixin from "../mixins/table/autoload.js";
|
|
95
|
+
import exportMixin from "../mixins/table/export.js";
|
|
96
|
+
import importMixin from "../mixins/table/import.js";
|
|
97
|
+
|
|
98
|
+
export default {
|
|
99
|
+
mixins: [autoloadMixin, exportMixin, importMixin],
|
|
100
|
+
props: {
|
|
101
|
+
spec: { type: Object, required: true }
|
|
102
|
+
},
|
|
103
|
+
data() {
|
|
104
|
+
return {
|
|
105
|
+
sections: [],
|
|
106
|
+
fileLoaded: false
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
computed: {
|
|
110
|
+
header() {
|
|
111
|
+
return this.spec.header;
|
|
112
|
+
},
|
|
113
|
+
footer() {
|
|
114
|
+
return this.spec.footer;
|
|
115
|
+
},
|
|
116
|
+
output() {
|
|
117
|
+
// let str = ""
|
|
118
|
+
// let count = 0
|
|
119
|
+
// for (const section of this.sections) {
|
|
120
|
+
// for (const row of section.dataRows) {
|
|
121
|
+
// const name = row[2]
|
|
122
|
+
// const email = row[3]
|
|
123
|
+
// const createdAt = row[5]
|
|
124
|
+
// const activationState = row[14] ? 'active' : 'pending'
|
|
125
|
+
// count += 1
|
|
126
|
+
// str += `{ name: "${name}".to_s, email: '${email}'.to_s, created_at: '${createdAt}', activation_state: '${activationState}'},\n`
|
|
127
|
+
// }
|
|
128
|
+
// }
|
|
129
|
+
// return `Processing ${count} rows:\n[\n${str}\n]`
|
|
130
|
+
return "";
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
methods: {
|
|
134
|
+
$mounted() {
|
|
135
|
+
this.$onEvent("forms/directSubmit", (e) => {
|
|
136
|
+
for (const section of this.sections) {
|
|
137
|
+
this.submitRows(e.data.url, section);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
},
|
|
141
|
+
$ready() {
|
|
142
|
+
this.sections = this.spec.sections;
|
|
143
|
+
this.sections.forEach((section, sectionIndex) => {
|
|
144
|
+
section.header = section.header || {};
|
|
145
|
+
section.index = sectionIndex
|
|
146
|
+
// Use Object.assign() to bind the nested property
|
|
147
|
+
Object.assign(section, { dataRows: [] });
|
|
148
|
+
})
|
|
149
|
+
this.autoloadAll(this.spec.nextPage);
|
|
150
|
+
this.initCsvExport();
|
|
151
|
+
this.initCsvImport();
|
|
152
|
+
this.enableInfiniteScrollIfApplicable();
|
|
153
|
+
},
|
|
154
|
+
$tearDown() {
|
|
155
|
+
this.cancelAutoloadRequest();
|
|
156
|
+
},
|
|
157
|
+
pendingIconSpec(rowIndex) {
|
|
158
|
+
const statusViewIdPrefix = this.spec.statusViewIdPrefix || 'data_status_';
|
|
159
|
+
return {
|
|
160
|
+
view: 'icon',
|
|
161
|
+
styleClasses: ['warning'],
|
|
162
|
+
id: `${statusViewIdPrefix}${rowIndex}`,
|
|
163
|
+
// TODO: It seems that logics_set/components_set doesn't work when changing the icon name.
|
|
164
|
+
material: {
|
|
165
|
+
name: 'preview'
|
|
166
|
+
},
|
|
167
|
+
// TODO: Implement this in the frontend. Right now, this is implemented in glib-web backend.
|
|
168
|
+
tooltip: {
|
|
169
|
+
text: "Review before submitting"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
headerCheckSpec(section) {
|
|
174
|
+
const sectionIndex = section.index;
|
|
175
|
+
const maxIndex = section.dataRows.length;
|
|
176
|
+
const result = {
|
|
177
|
+
view: 'fields/check',
|
|
178
|
+
name: 'check_all',
|
|
179
|
+
checkValue: true,
|
|
180
|
+
onChange: {
|
|
181
|
+
action: 'logics/set',
|
|
182
|
+
targetIds: Array(maxIndex).fill().map((_, i) => `_check_row_${sectionIndex}_${i}`),
|
|
183
|
+
conditionalData: {
|
|
184
|
+
checkValue: true,
|
|
185
|
+
value: { "var": "check_all" }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
},
|
|
191
|
+
rowCheckSpec(sectionIndex, rowIndex) {
|
|
192
|
+
const id = this.rowCheckId(sectionIndex, rowIndex);
|
|
193
|
+
// TODO: Right now, there is a bug where when the "select all" checkbox is checked, the individual
|
|
194
|
+
// checkboxes do not get checked. BUT, it works if we change the `name: id` to a different name (see below).
|
|
195
|
+
// It looks like there is a bug where the `id` and `name` cannot be the same.
|
|
196
|
+
return {
|
|
197
|
+
view: 'fields/check',
|
|
198
|
+
checkValue: true,
|
|
199
|
+
// name: `${id}-name`, // This works with "select all" (see above)
|
|
200
|
+
name: id,
|
|
201
|
+
id: id
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
rowCheckId(sectionIndex, rowIndex) {
|
|
205
|
+
// Use underscore to prevent conflict with server-defined IDs, e.g. for pendingIconSpec()
|
|
206
|
+
return `_check_row_${sectionIndex}_${rowIndex}`
|
|
207
|
+
},
|
|
208
|
+
colSpan(row, index) {
|
|
209
|
+
const spans = row.colSpans || [];
|
|
210
|
+
return spans[index] || 1;
|
|
211
|
+
},
|
|
212
|
+
colStyles(row, index) {
|
|
213
|
+
const colStyles = row.colStyles || [];
|
|
214
|
+
return this.$styles(colStyles[index] || {});
|
|
215
|
+
},
|
|
216
|
+
rows(section) {
|
|
217
|
+
return section.rows || [];
|
|
218
|
+
},
|
|
219
|
+
triggerImport(index) {
|
|
220
|
+
const input = this.$refs.fileInput[index];
|
|
221
|
+
input.click();
|
|
222
|
+
},
|
|
223
|
+
totalRows(section) {
|
|
224
|
+
return (section.rows || []).length + (section.dataRows || []).length;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
</script>
|
|
229
|
+
|
|
230
|
+
<style lang="scss" scoped>
|
|
231
|
+
table {
|
|
232
|
+
border-spacing: 0;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// thead {
|
|
236
|
+
// th {
|
|
237
|
+
// padding: 10px 4px;
|
|
238
|
+
// border-top: 1px solid rgba(0, 0, 0, 0.12);
|
|
239
|
+
// // border-left: 1px solid rgba(0, 0, 0, 0.12);
|
|
240
|
+
// }
|
|
241
|
+
// }
|
|
242
|
+
|
|
243
|
+
thead {
|
|
244
|
+
th {
|
|
245
|
+
&.fixed-width {
|
|
246
|
+
min-width: 200px; // TODO: Make this configurable
|
|
247
|
+
}
|
|
248
|
+
&.status {
|
|
249
|
+
min-width: 80px;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
}
|
|
254
|
+
tbody {
|
|
255
|
+
// tr.clickable {
|
|
256
|
+
// td>a {
|
|
257
|
+
// cursor: pointer;
|
|
258
|
+
// }
|
|
259
|
+
|
|
260
|
+
// &:hover {
|
|
261
|
+
// background: #eee;
|
|
262
|
+
// }
|
|
263
|
+
// }
|
|
264
|
+
|
|
265
|
+
td {
|
|
266
|
+
border-top: 1px solid rgba(0, 0, 0, 0.12);
|
|
267
|
+
|
|
268
|
+
span {
|
|
269
|
+
display: block;
|
|
270
|
+
color: inherit;
|
|
271
|
+
cursor: default;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
&.status {
|
|
275
|
+
display: flex;
|
|
276
|
+
align-items: center;
|
|
277
|
+
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.scrollable {
|
|
283
|
+
width: 100%;
|
|
284
|
+
overflow: auto;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.data-cell {
|
|
288
|
+
white-space: pre-line;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
table.table--grid {
|
|
292
|
+
tbody {
|
|
293
|
+
td {
|
|
294
|
+
border-right: 1px solid rgba(0, 0, 0, 0.12);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
</style>
|
package/keys.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/plugins/vuetify.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { createVuetify } from "vuetify";
|
|
2
2
|
// import 'material-design-icons-iconfont/dist/material-design-icons.css';
|
|
3
3
|
import { aliases, md } from 'vuetify/iconsets/md';
|
|
4
|
-
import 'vuetify/styles';
|
|
4
|
+
import 'vuetify/lib/styles/main.sass';
|
|
5
5
|
import * as components from 'vuetify/components';
|
|
6
|
+
import { jsonView } from "../store";
|
|
6
7
|
// import * as directives from 'vuetify/directives'
|
|
8
|
+
import { md3 } from 'vuetify/blueprints';
|
|
7
9
|
|
|
8
10
|
const opts = {
|
|
11
|
+
blueprint: md3,
|
|
9
12
|
components,
|
|
10
13
|
// directives,
|
|
11
14
|
icons: {
|
|
@@ -15,9 +18,7 @@ const opts = {
|
|
|
15
18
|
md,
|
|
16
19
|
},
|
|
17
20
|
},
|
|
18
|
-
theme: {
|
|
19
|
-
themes: {}
|
|
20
|
-
},
|
|
21
|
+
theme: jsonView.page.theme || {},
|
|
21
22
|
display: {
|
|
22
23
|
smAndDown: true
|
|
23
24
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/static/redactorx.css
CHANGED
|
File without changes
|
package/static/redactorx.min.css
CHANGED
|
File without changes
|
package/static/redactorx.min.js
CHANGED
|
File without changes
|
|
File without changes
|
package/styles/test.sass
CHANGED
|
File without changes
|
package/styles/test.scss
CHANGED
|
File without changes
|
|
File without changes
|
package/utils/dom.js
CHANGED
|
File without changes
|
package/utils/helper.js
CHANGED
|
File without changes
|