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.
Files changed (80) hide show
  1. package/LICENSE +0 -0
  2. package/actions/auth/restart.js +0 -0
  3. package/actions/commands/copy.js +0 -0
  4. package/actions/dialogs/notification.js +0 -0
  5. package/actions/dialogs/oauth.js +0 -0
  6. package/actions/dialogs/reload.js +0 -0
  7. package/actions/http/delete.js +0 -0
  8. package/actions/logics/set.js +5 -1
  9. package/actions/sheets/select.js +0 -0
  10. package/actions/snackbars/select.js +0 -0
  11. package/actions/windows/openWeb.js +0 -0
  12. package/actions/windows/print.js +0 -0
  13. package/components/_message.vue +0 -0
  14. package/components/component.vue +2 -0
  15. package/components/fields/multiUpload.vue +21 -6
  16. package/components/fields/phone/countries.js +0 -0
  17. package/components/fields/phone/sprite.css +0 -0
  18. package/components/fields/radio/_featured.vue +9 -10
  19. package/components/fields/radio.vue +7 -12
  20. package/components/h1.vue +0 -0
  21. package/components/h2.vue +0 -0
  22. package/components/h3.vue +0 -0
  23. package/components/h5.vue +0 -0
  24. package/components/h6.vue +0 -0
  25. package/components/hr.vue +0 -0
  26. package/components/html.vue +0 -0
  27. package/components/icon.vue +0 -0
  28. package/components/mixins/extension.js +0 -0
  29. package/components/mixins/longClick.js +0 -0
  30. package/components/mixins/scrolling.js +0 -0
  31. package/components/mixins/table/export.js +0 -0
  32. package/components/mixins/table/import.js +45 -9
  33. package/components/mixins/text.js +0 -0
  34. package/components/multimedia/video.vue +0 -0
  35. package/components/panels/bulkEdit.vue +298 -0
  36. package/keys.js +0 -0
  37. package/package.json +1 -1
  38. package/plugins/vuetify.js +5 -4
  39. package/static/plugins/alignment/alignment.js +0 -0
  40. package/static/plugins/alignment/alignment.min.js +0 -0
  41. package/static/plugins/beyondgrammar/beyondgrammar.js +0 -0
  42. package/static/plugins/beyondgrammar/beyondgrammar.min.js +0 -0
  43. package/static/plugins/blockcode/blockcode.js +0 -0
  44. package/static/plugins/blockcode/blockcode.min.js +0 -0
  45. package/static/plugins/clips/clips.js +0 -0
  46. package/static/plugins/clips/clips.min.js +0 -0
  47. package/static/plugins/counter/counter.js +0 -0
  48. package/static/plugins/counter/counter.min.js +0 -0
  49. package/static/plugins/definedlinks/definedlinks.js +0 -0
  50. package/static/plugins/definedlinks/definedlinks.min.js +0 -0
  51. package/static/plugins/handle/handle.js +0 -0
  52. package/static/plugins/handle/handle.min.js +0 -0
  53. package/static/plugins/icons/icons.js +0 -0
  54. package/static/plugins/icons/icons.min.js +0 -0
  55. package/static/plugins/imageposition/imageposition.js +0 -0
  56. package/static/plugins/imageposition/imageposition.min.js +0 -0
  57. package/static/plugins/inlineformat/inlineformat.js +0 -0
  58. package/static/plugins/inlineformat/inlineformat.min.js +0 -0
  59. package/static/plugins/removeformat/removeformat.js +0 -0
  60. package/static/plugins/removeformat/removeformat.min.js +0 -0
  61. package/static/plugins/selector/selector.js +0 -0
  62. package/static/plugins/selector/selector.min.js +0 -0
  63. package/static/plugins/specialchars/specialchars.js +0 -0
  64. package/static/plugins/specialchars/specialchars.min.js +0 -0
  65. package/static/plugins/textdirection/textdirection.js +0 -0
  66. package/static/plugins/textdirection/textdirection.min.js +0 -0
  67. package/static/plugins/textexpander/textexpander.js +0 -0
  68. package/static/plugins/textexpander/textexpander.min.js +0 -0
  69. package/static/plugins/underline/underline.js +0 -0
  70. package/static/plugins/underline/underline.min.js +0 -0
  71. package/static/redactorx.css +0 -0
  72. package/static/redactorx.min.css +0 -0
  73. package/static/redactorx.min.js +0 -0
  74. package/static/redactorx.usm.min.js +0 -0
  75. package/styles/test.sass +0 -0
  76. package/styles/test.scss +0 -0
  77. package/templates/unsupported.vue +0 -0
  78. package/utils/dom.js +0 -0
  79. package/utils/helper.js +0 -0
  80. package/utils/type.js +3 -0
package/LICENSE CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -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
- GLib.action.execute(spec.onSet, targetComponent);
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
  }
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -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
- <div class="percentage-wrapper" v-show="file[1].progress.value > 0 && file[1].progress.value < 100">
42
- <div class="background">
43
- <div class="value" :style="{ width: `${file[1].progress.value}%` }"></div>
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
- <div class="percentage">{{ parseInt(file[1].progress.value) }}%</div>
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: 254px;
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: 1px solid #E6E6E6;
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
- height: 100%;
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: 16px;
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: 1px solid #E6E6E6;
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
- height: 100%;
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: 16px;
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
File without changes
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.dataRows.forEach(row => {
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, index) => {
25
- const key = `${vm.importParamName}[${keys[index]}]`;
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 (Utils.type.isString(this.importSubmitUrl)) {
32
- vm._submitEachRow(rows, event.target);
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, target) {
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: this.importSubmitUrl,
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, target);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glib-web",
3
- "version": "4.8.0",
3
+ "version": "4.8.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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
File without changes
File without changes
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
package/utils/type.js CHANGED
@@ -66,4 +66,7 @@ export default class {
66
66
  const val = parseFloat(obj);
67
67
  return isNaN(val) ? null : val;
68
68
  }
69
+ static string(obj) {
70
+ return this.isString(obj) ? obj : null
71
+ }
69
72
  }