glib-web 0.5.98 → 0.6.2
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/README.md +0 -0
- package/action.js +167 -167
- package/actions/analytics/logEvent.js +0 -0
- package/actions/auth/creditCard.js +0 -0
- package/actions/auth/restart.js +0 -0
- package/actions/auth/saveCsrfToken.js +0 -0
- package/actions/cables/push.js +0 -0
- package/actions/dialogs/alert.js +0 -0
- package/actions/dialogs/notification.js +0 -0
- package/actions/dialogs/oauth.js +0 -0
- package/actions/dialogs/open.js +0 -0
- package/actions/dialogs/options.js +0 -0
- package/actions/dialogs/show.js +0 -0
- package/actions/forms/submit.js +0 -0
- package/actions/http/delete.js +0 -0
- package/actions/http/patch.js +0 -0
- package/actions/http/post.js +0 -0
- package/actions/http/put.js +0 -0
- package/actions/panels/scrollTo.js +18 -18
- package/actions/panels/scrollToBottom.js +0 -0
- package/actions/runMultiple.js +0 -0
- package/actions/sheets/select.js +0 -0
- package/actions/snackbars/alert.js +0 -0
- package/actions/snackbars/select.js +0 -0
- package/actions/timeouts/set.js +20 -20
- package/actions/windows/close.js +0 -0
- package/actions/windows/closeAll.js +0 -0
- package/actions/windows/closeWithReload.js +0 -0
- package/actions/windows/open.js +0 -0
- package/actions/windows/openWeb.js +0 -0
- package/actions/windows/refreshState.js +5 -5
- package/actions/windows/reload.js +0 -0
- package/actions/ws/push.js +0 -0
- package/app.vue +180 -180
- package/components/_badge.vue +23 -23
- package/components/_button.vue +107 -107
- package/components/_dropdownMenu.vue +76 -76
- package/components/_icon.vue +50 -50
- package/components/_message.vue +0 -0
- package/components/avatar.vue +18 -18
- package/components/banners/alert.vue +0 -0
- package/components/banners/select.vue +82 -82
- package/components/button.vue +33 -40
- package/components/calendar.vue +0 -0
- package/components/charts/column.vue +47 -34
- package/components/charts/line.vue +67 -65
- package/components/chip.vue +51 -26
- package/components/component.vue +225 -225
- package/components/datetime.vue +0 -0
- package/components/fab.vue +0 -0
- package/components/fields/_patternText.vue +65 -65
- package/components/fields/_select.vue +86 -86
- package/components/fields/autocomplete.vue +73 -73
- package/components/fields/check.vue +91 -81
- package/components/fields/checkGroup.vue +58 -58
- package/components/fields/country/countries.js +0 -0
- package/components/fields/country/field.vue +0 -0
- package/components/fields/country/regions.js +0 -0
- package/components/fields/creditCard.vue +22 -13
- package/components/fields/date.vue +24 -24
- package/components/fields/datetime.vue +0 -0
- package/components/fields/dynamicGroup.vue +0 -0
- package/components/fields/dynamicSelect.vue +0 -0
- package/components/fields/file.vue +0 -0
- package/components/fields/googlePlace.vue +0 -0
- package/components/fields/hidden.vue +0 -0
- package/components/fields/location.vue +198 -198
- package/components/fields/newRichText.vue +0 -0
- package/components/fields/phone/countries.js +315 -315
- package/components/fields/phone/field.vue +351 -351
- package/components/fields/phone/sprite.css +1071 -1071
- package/components/fields/radio.vue +16 -16
- package/components/fields/radioGroup.vue +42 -42
- package/components/fields/rating.vue +0 -0
- package/components/fields/richText.vue +0 -0
- package/components/fields/select.vue +17 -17
- package/components/fields/stripe/stripeFields.vue +93 -93
- package/components/fields/stripe/stripeIndividualFields.vue +207 -207
- package/components/fields/stripeExternalAccount.vue +135 -135
- package/components/fields/text.vue +0 -0
- package/components/fields/textarea.vue +0 -0
- package/components/fields/timeZone.vue +22 -22
- package/components/fields/timer.vue +83 -83
- package/components/h1.vue +28 -28
- package/components/h2.vue +28 -20
- package/components/h3.vue +29 -22
- package/components/h4.vue +28 -20
- package/components/h5.vue +28 -20
- package/components/h6.vue +28 -20
- package/components/hr.vue +0 -0
- package/components/html.vue +0 -0
- package/components/icon.vue +25 -25
- package/components/image.vue +0 -0
- package/components/label.vue +62 -62
- package/components/map.vue +0 -0
- package/components/markdown.vue +0 -0
- package/components/mixins/{chart.js → chart/annotation.js} +73 -73
- package/components/mixins/chart/tooltip.js +31 -0
- package/components/mixins/events.js +178 -178
- package/components/mixins/generic.js +0 -0
- package/components/mixins/list/autoload.js +0 -0
- package/components/mixins/longClick.js +0 -0
- package/components/mixins/scrolling.js +0 -0
- package/components/mixins/styles.js +222 -222
- package/components/mixins/table/autoload.js +0 -0
- package/components/mixins/table/export.js +0 -0
- package/components/mixins/table/import.js +0 -0
- package/components/mixins/text.js +20 -20
- package/components/mixins/tooltip.js +11 -0
- package/components/mixins/ws/actionCable.js +48 -48
- package/components/mixins/ws/phoenixSocket.js +0 -0
- package/components/p.vue +0 -0
- package/components/panels/carousel.vue +55 -55
- package/components/panels/column.vue +0 -0
- package/components/panels/custom.vue +0 -0
- package/components/panels/flow.vue +81 -81
- package/components/panels/form.vue +130 -130
- package/components/panels/horizontal.vue +0 -0
- package/components/panels/list.vue +247 -247
- package/components/panels/responsive.vue +94 -94
- package/components/panels/scroll.vue +0 -0
- package/components/panels/split.vue +0 -0
- package/components/panels/table.vue +0 -0
- package/components/panels/ul.vue +34 -34
- package/components/panels/vertical.vue +0 -0
- package/components/panels/web.vue +11 -11
- package/components/progressbar.vue +36 -36
- package/components/spacer.vue +0 -0
- package/components/switch.vue +42 -42
- package/components/tabBar.vue +68 -68
- package/extensions/array.js +0 -0
- package/extensions/string.js +21 -21
- package/index.js +199 -199
- package/keys.js +0 -0
- package/nav/appbar.vue +136 -136
- package/nav/content.vue +0 -0
- package/nav/dialog.vue +127 -127
- package/nav/drawer.vue +105 -105
- package/nav/drawerButton.vue +31 -31
- package/nav/drawerLabel.vue +0 -0
- package/nav/sheet.vue +0 -0
- package/nav/snackbar.vue +0 -0
- package/package.json +44 -44
- package/settings.json.example +0 -0
- 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.js +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/_menu.vue +38 -38
- package/templates/comment.vue +202 -202
- package/templates/featured.vue +32 -32
- package/templates/thumbnail.vue +145 -145
- package/templates/unsupported.vue +12 -12
- package/utils/app.js +0 -0
- package/utils/dom.js +0 -0
- package/utils/form.js +0 -0
- package/utils/hash.js +0 -0
- package/utils/helper.js +0 -0
- package/utils/history.js +70 -70
- package/utils/http.js +209 -209
- package/utils/launch.js +135 -135
- package/utils/private/ws.js +0 -0
- package/utils/public.js +0 -0
- package/utils/settings.js +0 -0
- package/utils/storage.js +0 -0
- package/utils/type.js +0 -0
- package/utils/uploader.js +0 -0
- package/utils/url.js +136 -136
|
@@ -1,247 +1,247 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<v-list
|
|
3
|
-
:two-line="twoLine"
|
|
4
|
-
:three-line="threeLine"
|
|
5
|
-
class="py-0"
|
|
6
|
-
:style="genericStyles()"
|
|
7
|
-
>
|
|
8
|
-
<div ref="topAnchor"></div>
|
|
9
|
-
|
|
10
|
-
<template v-for="(section, sectionIndex) in sections">
|
|
11
|
-
<div :key="`section${sectionIndex}`">
|
|
12
|
-
<panels-responsive v-if="section.header" :spec="section.header" />
|
|
13
|
-
|
|
14
|
-
<draggable
|
|
15
|
-
v-model="section.rows"
|
|
16
|
-
ghost-class="ghost"
|
|
17
|
-
group="a"
|
|
18
|
-
handle=".handle"
|
|
19
|
-
:data-index="sectionIndex"
|
|
20
|
-
@end="onDragEnd"
|
|
21
|
-
>
|
|
22
|
-
<div
|
|
23
|
-
v-for="(row, rowIndex) in section.rows"
|
|
24
|
-
:key="`${sectionIndex}_${rowIndex}`"
|
|
25
|
-
:class="row.styleClasses"
|
|
26
|
-
>
|
|
27
|
-
<v-divider v-if="!spec.responsiveCols && rowIndex == 0" />
|
|
28
|
-
|
|
29
|
-
<component
|
|
30
|
-
:is="template(row)"
|
|
31
|
-
:spec="row"
|
|
32
|
-
:responsive-cols="spec.responsiveCols"
|
|
33
|
-
:index="rowIndex"
|
|
34
|
-
/>
|
|
35
|
-
<v-divider
|
|
36
|
-
v-if="
|
|
37
|
-
!spec.responsiveCols &&
|
|
38
|
-
(rowIndex != section.rows.length - 1 ||
|
|
39
|
-
sectionIndex != sections.length - 1)
|
|
40
|
-
"
|
|
41
|
-
/>
|
|
42
|
-
</div>
|
|
43
|
-
</draggable>
|
|
44
|
-
|
|
45
|
-
<panels-responsive v-if="section.footer" :spec="section.footer" />
|
|
46
|
-
</div>
|
|
47
|
-
</template>
|
|
48
|
-
|
|
49
|
-
<div ref="bottomAnchor" class="py-3 px-4" :style="bottomAnchorStyles">
|
|
50
|
-
Loading...
|
|
51
|
-
</div>
|
|
52
|
-
</v-list>
|
|
53
|
-
</template>
|
|
54
|
-
|
|
55
|
-
<script>
|
|
56
|
-
import draggable from "vuedraggable";
|
|
57
|
-
import autoloadMixin from "../mixins/list/autoload.js";
|
|
58
|
-
import ThumbnailTemplate from "../../templates/thumbnail";
|
|
59
|
-
import FeaturedTemplate from "../../templates/featured";
|
|
60
|
-
import CommentTemplate from "../../templates/comment";
|
|
61
|
-
import actionCableMixin from "../mixins/ws/actionCable.js";
|
|
62
|
-
|
|
63
|
-
export default {
|
|
64
|
-
components: {
|
|
65
|
-
draggable,
|
|
66
|
-
"template-thumbnail": ThumbnailTemplate,
|
|
67
|
-
"template-featured": FeaturedTemplate,
|
|
68
|
-
"template-commentOutgoing": CommentTemplate,
|
|
69
|
-
"template-commentIncoming": CommentTemplate
|
|
70
|
-
},
|
|
71
|
-
mixins: [autoloadMixin, actionCableMixin],
|
|
72
|
-
props: {
|
|
73
|
-
spec: { type: Object, required: true }
|
|
74
|
-
},
|
|
75
|
-
data: function() {
|
|
76
|
-
return {
|
|
77
|
-
sections: []
|
|
78
|
-
};
|
|
79
|
-
},
|
|
80
|
-
computed: {
|
|
81
|
-
twoLine() {
|
|
82
|
-
for (const section of this.sections) {
|
|
83
|
-
const rows = section.rows || [];
|
|
84
|
-
for (const row of rows) {
|
|
85
|
-
if (row.subtitle) {
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return false;
|
|
91
|
-
},
|
|
92
|
-
threeLine() {
|
|
93
|
-
for (const section of this.sections) {
|
|
94
|
-
const rows = section.rows || [];
|
|
95
|
-
for (const row of rows) {
|
|
96
|
-
if (row.subsubtitle) {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
methods: {
|
|
105
|
-
$ready() {
|
|
106
|
-
this.sections = this.spec.sections || [];
|
|
107
|
-
this.autoloadAll(this.spec.nextPage);
|
|
108
|
-
this.enableInfiniteScrollIfApplicable();
|
|
109
|
-
this.$wsSubscribeEvents(this.spec.phoenixSocket);
|
|
110
|
-
this.$wsInitActionCable(this.spec.actionCable);
|
|
111
|
-
|
|
112
|
-
for (const section of this.sections) {
|
|
113
|
-
section.rows = section.rows || [];
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
action_loadNext(spec) {
|
|
117
|
-
console.log("TODO: load new comments and append to this list", spec);
|
|
118
|
-
// TODO
|
|
119
|
-
// - Load next rows/items from the Rails server
|
|
120
|
-
// - You can pass some parameters (e.g. currentItemId) for pagination
|
|
121
|
-
// - For example, if currentItemId is 56, the server will know that it needs to
|
|
122
|
-
// return items that are newer than 56
|
|
123
|
-
// - You may use other ways for pagination as well
|
|
124
|
-
// - Append the rows to this list
|
|
125
|
-
},
|
|
126
|
-
action_append(spec) {
|
|
127
|
-
for (const [index, appendedSection] of spec.sections.entries()) {
|
|
128
|
-
const section = this.sections[index] || {};
|
|
129
|
-
|
|
130
|
-
if (!section.rows) {
|
|
131
|
-
this.$set(section, "rows", []);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
Utils.type.ifArray(appendedSection.rows, rows => {
|
|
135
|
-
for (const row of rows) {
|
|
136
|
-
section.rows.push(row);
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
action_update(spec) {
|
|
142
|
-
const updatedRows = {};
|
|
143
|
-
|
|
144
|
-
Utils.type.ifArray(spec.rows, rows => {
|
|
145
|
-
for (const row of rows) {
|
|
146
|
-
updatedRows[row.id] = row;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
for (const section of this.sections) {
|
|
151
|
-
section.rows = section.rows.map(row => {
|
|
152
|
-
const updatedRow = updatedRows[row.id];
|
|
153
|
-
if (updatedRow) {
|
|
154
|
-
return updatedRow;
|
|
155
|
-
} else {
|
|
156
|
-
return row;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
},
|
|
161
|
-
action_delete(spec) {
|
|
162
|
-
const deletedRows = {};
|
|
163
|
-
Utils.type.ifArray(spec.rows, rows => {
|
|
164
|
-
for (const row of rows) {
|
|
165
|
-
deletedRows[row.id] = row;
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
for (const section of this.sections) {
|
|
170
|
-
section.rows = section.rows.filter(row => {
|
|
171
|
-
// return !rows.includes(row.id);
|
|
172
|
-
return !deletedRows[row.id];
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
$tearDown() {
|
|
177
|
-
this.cancelAutoloadRequest();
|
|
178
|
-
},
|
|
179
|
-
template(row) {
|
|
180
|
-
const name = `template-${row.template.replace("/", "-")}`;
|
|
181
|
-
const strict = true;
|
|
182
|
-
if (strict) {
|
|
183
|
-
return name;
|
|
184
|
-
} else {
|
|
185
|
-
if (this.$options.components[name]) {
|
|
186
|
-
return name;
|
|
187
|
-
}
|
|
188
|
-
console.warn(`Invalid template: ${row.template}`);
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
},
|
|
192
|
-
serializedSpec(row) {
|
|
193
|
-
return JSON.stringify(row);
|
|
194
|
-
},
|
|
195
|
-
onDragEnd(event) {
|
|
196
|
-
const targetSectionedRowIndex = event.newIndex;
|
|
197
|
-
if (event.from == event.to && event.oldIndex == targetSectionedRowIndex) {
|
|
198
|
-
console.log("Reordering canceled");
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const targetSectionIndex = this.getSectionIndex(event.to);
|
|
203
|
-
const targetSection = this.getSection(targetSectionIndex);
|
|
204
|
-
// The dragged row is now on the new index
|
|
205
|
-
const draggedRow = targetSection.rows[targetSectionedRowIndex];
|
|
206
|
-
|
|
207
|
-
const targetAbsoluteIndex =
|
|
208
|
-
this.previousSectionsRowCount(event.to) + targetSectionedRowIndex;
|
|
209
|
-
|
|
210
|
-
const mergedSpec = Object.assign(draggedRow.onReorder, {
|
|
211
|
-
[draggedRow.paramNameForFormData || "formData"]: {
|
|
212
|
-
[draggedRow.paramNameForNewIndex]: targetAbsoluteIndex, // Deprecated
|
|
213
|
-
[draggedRow.paramNameForNewAbsoluteIndex ||
|
|
214
|
-
"newAbsoluteIndex"]: targetAbsoluteIndex,
|
|
215
|
-
[draggedRow.paramNameForNewSectionIndex ||
|
|
216
|
-
"newSectionIndex"]: targetSectionIndex,
|
|
217
|
-
[draggedRow.paramNameForNewSectionedRowIndex ||
|
|
218
|
-
"newSectionedRowIndex"]: targetSectionedRowIndex
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
GLib.action.execute(mergedSpec, null, this);
|
|
223
|
-
},
|
|
224
|
-
getSectionIndex(element) {
|
|
225
|
-
return element.dataset.index;
|
|
226
|
-
},
|
|
227
|
-
getSection(sectionIndex) {
|
|
228
|
-
return this.sections[sectionIndex];
|
|
229
|
-
},
|
|
230
|
-
previousSectionsRowCount(element) {
|
|
231
|
-
const sectionIndex = this.getSectionIndex(element);
|
|
232
|
-
let count = 0;
|
|
233
|
-
for (let i = 0; i < sectionIndex; i++) {
|
|
234
|
-
count += this.getSection(i).rows.length;
|
|
235
|
-
}
|
|
236
|
-
return count;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
</script>
|
|
241
|
-
|
|
242
|
-
<style lang="scss" scoped>
|
|
243
|
-
.ghost {
|
|
244
|
-
opacity: 0.5;
|
|
245
|
-
background: #dddddd;
|
|
246
|
-
}
|
|
247
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<v-list
|
|
3
|
+
:two-line="twoLine"
|
|
4
|
+
:three-line="threeLine"
|
|
5
|
+
class="py-0"
|
|
6
|
+
:style="genericStyles()"
|
|
7
|
+
>
|
|
8
|
+
<div ref="topAnchor"></div>
|
|
9
|
+
|
|
10
|
+
<template v-for="(section, sectionIndex) in sections">
|
|
11
|
+
<div :key="`section${sectionIndex}`">
|
|
12
|
+
<panels-responsive v-if="section.header" :spec="section.header" />
|
|
13
|
+
|
|
14
|
+
<draggable
|
|
15
|
+
v-model="section.rows"
|
|
16
|
+
ghost-class="ghost"
|
|
17
|
+
group="a"
|
|
18
|
+
handle=".handle"
|
|
19
|
+
:data-index="sectionIndex"
|
|
20
|
+
@end="onDragEnd"
|
|
21
|
+
>
|
|
22
|
+
<div
|
|
23
|
+
v-for="(row, rowIndex) in section.rows"
|
|
24
|
+
:key="`${sectionIndex}_${rowIndex}`"
|
|
25
|
+
:class="row.styleClasses"
|
|
26
|
+
>
|
|
27
|
+
<v-divider v-if="!spec.responsiveCols && rowIndex == 0" />
|
|
28
|
+
|
|
29
|
+
<component
|
|
30
|
+
:is="template(row)"
|
|
31
|
+
:spec="row"
|
|
32
|
+
:responsive-cols="spec.responsiveCols"
|
|
33
|
+
:index="rowIndex"
|
|
34
|
+
/>
|
|
35
|
+
<v-divider
|
|
36
|
+
v-if="
|
|
37
|
+
!spec.responsiveCols &&
|
|
38
|
+
(rowIndex != section.rows.length - 1 ||
|
|
39
|
+
sectionIndex != sections.length - 1)
|
|
40
|
+
"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
</draggable>
|
|
44
|
+
|
|
45
|
+
<panels-responsive v-if="section.footer" :spec="section.footer" />
|
|
46
|
+
</div>
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<div ref="bottomAnchor" class="py-3 px-4" :style="bottomAnchorStyles">
|
|
50
|
+
Loading...
|
|
51
|
+
</div>
|
|
52
|
+
</v-list>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script>
|
|
56
|
+
import draggable from "vuedraggable";
|
|
57
|
+
import autoloadMixin from "../mixins/list/autoload.js";
|
|
58
|
+
import ThumbnailTemplate from "../../templates/thumbnail";
|
|
59
|
+
import FeaturedTemplate from "../../templates/featured";
|
|
60
|
+
import CommentTemplate from "../../templates/comment";
|
|
61
|
+
import actionCableMixin from "../mixins/ws/actionCable.js";
|
|
62
|
+
|
|
63
|
+
export default {
|
|
64
|
+
components: {
|
|
65
|
+
draggable,
|
|
66
|
+
"template-thumbnail": ThumbnailTemplate,
|
|
67
|
+
"template-featured": FeaturedTemplate,
|
|
68
|
+
"template-commentOutgoing": CommentTemplate,
|
|
69
|
+
"template-commentIncoming": CommentTemplate
|
|
70
|
+
},
|
|
71
|
+
mixins: [autoloadMixin, actionCableMixin],
|
|
72
|
+
props: {
|
|
73
|
+
spec: { type: Object, required: true }
|
|
74
|
+
},
|
|
75
|
+
data: function() {
|
|
76
|
+
return {
|
|
77
|
+
sections: []
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
computed: {
|
|
81
|
+
twoLine() {
|
|
82
|
+
for (const section of this.sections) {
|
|
83
|
+
const rows = section.rows || [];
|
|
84
|
+
for (const row of rows) {
|
|
85
|
+
if (row.subtitle) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
},
|
|
92
|
+
threeLine() {
|
|
93
|
+
for (const section of this.sections) {
|
|
94
|
+
const rows = section.rows || [];
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
if (row.subsubtitle) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
methods: {
|
|
105
|
+
$ready() {
|
|
106
|
+
this.sections = this.spec.sections || [];
|
|
107
|
+
this.autoloadAll(this.spec.nextPage);
|
|
108
|
+
this.enableInfiniteScrollIfApplicable();
|
|
109
|
+
this.$wsSubscribeEvents(this.spec.phoenixSocket);
|
|
110
|
+
this.$wsInitActionCable(this.spec.actionCable);
|
|
111
|
+
|
|
112
|
+
for (const section of this.sections) {
|
|
113
|
+
section.rows = section.rows || [];
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
action_loadNext(spec) {
|
|
117
|
+
console.log("TODO: load new comments and append to this list", spec);
|
|
118
|
+
// TODO
|
|
119
|
+
// - Load next rows/items from the Rails server
|
|
120
|
+
// - You can pass some parameters (e.g. currentItemId) for pagination
|
|
121
|
+
// - For example, if currentItemId is 56, the server will know that it needs to
|
|
122
|
+
// return items that are newer than 56
|
|
123
|
+
// - You may use other ways for pagination as well
|
|
124
|
+
// - Append the rows to this list
|
|
125
|
+
},
|
|
126
|
+
action_append(spec) {
|
|
127
|
+
for (const [index, appendedSection] of spec.sections.entries()) {
|
|
128
|
+
const section = this.sections[index] || {};
|
|
129
|
+
|
|
130
|
+
if (!section.rows) {
|
|
131
|
+
this.$set(section, "rows", []);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Utils.type.ifArray(appendedSection.rows, rows => {
|
|
135
|
+
for (const row of rows) {
|
|
136
|
+
section.rows.push(row);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
action_update(spec) {
|
|
142
|
+
const updatedRows = {};
|
|
143
|
+
|
|
144
|
+
Utils.type.ifArray(spec.rows, rows => {
|
|
145
|
+
for (const row of rows) {
|
|
146
|
+
updatedRows[row.id] = row;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
for (const section of this.sections) {
|
|
151
|
+
section.rows = section.rows.map(row => {
|
|
152
|
+
const updatedRow = updatedRows[row.id];
|
|
153
|
+
if (updatedRow) {
|
|
154
|
+
return updatedRow;
|
|
155
|
+
} else {
|
|
156
|
+
return row;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
action_delete(spec) {
|
|
162
|
+
const deletedRows = {};
|
|
163
|
+
Utils.type.ifArray(spec.rows, rows => {
|
|
164
|
+
for (const row of rows) {
|
|
165
|
+
deletedRows[row.id] = row;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
for (const section of this.sections) {
|
|
170
|
+
section.rows = section.rows.filter(row => {
|
|
171
|
+
// return !rows.includes(row.id);
|
|
172
|
+
return !deletedRows[row.id];
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
$tearDown() {
|
|
177
|
+
this.cancelAutoloadRequest();
|
|
178
|
+
},
|
|
179
|
+
template(row) {
|
|
180
|
+
const name = `template-${row.template.replace("/", "-")}`;
|
|
181
|
+
const strict = true;
|
|
182
|
+
if (strict) {
|
|
183
|
+
return name;
|
|
184
|
+
} else {
|
|
185
|
+
if (this.$options.components[name]) {
|
|
186
|
+
return name;
|
|
187
|
+
}
|
|
188
|
+
console.warn(`Invalid template: ${row.template}`);
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
serializedSpec(row) {
|
|
193
|
+
return JSON.stringify(row);
|
|
194
|
+
},
|
|
195
|
+
onDragEnd(event) {
|
|
196
|
+
const targetSectionedRowIndex = event.newIndex;
|
|
197
|
+
if (event.from == event.to && event.oldIndex == targetSectionedRowIndex) {
|
|
198
|
+
console.log("Reordering canceled");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const targetSectionIndex = this.getSectionIndex(event.to);
|
|
203
|
+
const targetSection = this.getSection(targetSectionIndex);
|
|
204
|
+
// The dragged row is now on the new index
|
|
205
|
+
const draggedRow = targetSection.rows[targetSectionedRowIndex];
|
|
206
|
+
|
|
207
|
+
const targetAbsoluteIndex =
|
|
208
|
+
this.previousSectionsRowCount(event.to) + targetSectionedRowIndex;
|
|
209
|
+
|
|
210
|
+
const mergedSpec = Object.assign(draggedRow.onReorder, {
|
|
211
|
+
[draggedRow.paramNameForFormData || "formData"]: {
|
|
212
|
+
[draggedRow.paramNameForNewIndex]: targetAbsoluteIndex, // Deprecated
|
|
213
|
+
[draggedRow.paramNameForNewAbsoluteIndex ||
|
|
214
|
+
"newAbsoluteIndex"]: targetAbsoluteIndex,
|
|
215
|
+
[draggedRow.paramNameForNewSectionIndex ||
|
|
216
|
+
"newSectionIndex"]: targetSectionIndex,
|
|
217
|
+
[draggedRow.paramNameForNewSectionedRowIndex ||
|
|
218
|
+
"newSectionedRowIndex"]: targetSectionedRowIndex
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
GLib.action.execute(mergedSpec, null, this);
|
|
223
|
+
},
|
|
224
|
+
getSectionIndex(element) {
|
|
225
|
+
return element.dataset.index;
|
|
226
|
+
},
|
|
227
|
+
getSection(sectionIndex) {
|
|
228
|
+
return this.sections[sectionIndex];
|
|
229
|
+
},
|
|
230
|
+
previousSectionsRowCount(element) {
|
|
231
|
+
const sectionIndex = this.getSectionIndex(element);
|
|
232
|
+
let count = 0;
|
|
233
|
+
for (let i = 0; i < sectionIndex; i++) {
|
|
234
|
+
count += this.getSection(i).rows.length;
|
|
235
|
+
}
|
|
236
|
+
return count;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
</script>
|
|
241
|
+
|
|
242
|
+
<style lang="scss" scoped>
|
|
243
|
+
.ghost {
|
|
244
|
+
opacity: 0.5;
|
|
245
|
+
background: #dddddd;
|
|
246
|
+
}
|
|
247
|
+
</style>
|
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:class="cssClasses"
|
|
4
|
-
:style="$styles()"
|
|
5
|
-
:href="$href()"
|
|
6
|
-
@click="$onClick()"
|
|
7
|
-
>
|
|
8
|
-
<v-row no-gutters class="full-height">
|
|
9
|
-
<template v-for="(item, index) in spec.childViews">
|
|
10
|
-
<ui-component
|
|
11
|
-
v-if="isColumn(item)"
|
|
12
|
-
:key="viewKey(item, index)"
|
|
13
|
-
:spec="item"
|
|
14
|
-
/>
|
|
15
|
-
<div
|
|
16
|
-
v-else
|
|
17
|
-
:key="viewKey(item, index)"
|
|
18
|
-
class="full-width"
|
|
19
|
-
:style="innerStyles"
|
|
20
|
-
>
|
|
21
|
-
<ui-component :spec="item" />
|
|
22
|
-
</div>
|
|
23
|
-
</template>
|
|
24
|
-
</v-row>
|
|
25
|
-
</div>
|
|
26
|
-
</template>
|
|
27
|
-
|
|
28
|
-
<script>
|
|
29
|
-
import Vue from "vue";
|
|
30
|
-
|
|
31
|
-
export default {
|
|
32
|
-
props: {
|
|
33
|
-
spec: {
|
|
34
|
-
type: Object,
|
|
35
|
-
required: true,
|
|
36
|
-
default: function() {
|
|
37
|
-
return {};
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
data() {
|
|
42
|
-
return {
|
|
43
|
-
innerStyles: {}
|
|
44
|
-
};
|
|
45
|
-
},
|
|
46
|
-
computed: {
|
|
47
|
-
cssClasses() {
|
|
48
|
-
// This panel will be nameless when used in predefined layout (e.g. page.body, list.header, etc.)
|
|
49
|
-
this.spec.view = this.spec.view || "panels/responsive";
|
|
50
|
-
return this.$classes();
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
methods: {
|
|
54
|
-
$ready() {
|
|
55
|
-
let align = null;
|
|
56
|
-
switch (this.spec.align) {
|
|
57
|
-
case "center":
|
|
58
|
-
align = "center";
|
|
59
|
-
break;
|
|
60
|
-
case "right":
|
|
61
|
-
align = "flex-end";
|
|
62
|
-
break;
|
|
63
|
-
default:
|
|
64
|
-
align = "flex-start";
|
|
65
|
-
}
|
|
66
|
-
Vue.set(this.innerStyles, "align-items", align);
|
|
67
|
-
},
|
|
68
|
-
isColumn(item) {
|
|
69
|
-
return item.view == "panels/column-v1";
|
|
70
|
-
},
|
|
71
|
-
viewKey(item, index) {
|
|
72
|
-
// Use view name for key to avoid component reuse issue
|
|
73
|
-
return `view${index}_${item.view}`;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
</script>
|
|
78
|
-
|
|
79
|
-
<style scoped>
|
|
80
|
-
.row {
|
|
81
|
-
margin-left: 0;
|
|
82
|
-
margin-right: 0;
|
|
83
|
-
}
|
|
84
|
-
.full-width {
|
|
85
|
-
width: 100%;
|
|
86
|
-
flex: 0 0 100%;
|
|
87
|
-
display: flex;
|
|
88
|
-
flex-direction: column;
|
|
89
|
-
}
|
|
90
|
-
/* Needed to ensure that split's sub panels have the same height */
|
|
91
|
-
.full-height {
|
|
92
|
-
height: 100%;
|
|
93
|
-
}
|
|
94
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="cssClasses"
|
|
4
|
+
:style="$styles()"
|
|
5
|
+
:href="$href()"
|
|
6
|
+
@click="$onClick()"
|
|
7
|
+
>
|
|
8
|
+
<v-row no-gutters class="full-height">
|
|
9
|
+
<template v-for="(item, index) in spec.childViews">
|
|
10
|
+
<ui-component
|
|
11
|
+
v-if="isColumn(item)"
|
|
12
|
+
:key="viewKey(item, index)"
|
|
13
|
+
:spec="item"
|
|
14
|
+
/>
|
|
15
|
+
<div
|
|
16
|
+
v-else
|
|
17
|
+
:key="viewKey(item, index)"
|
|
18
|
+
class="full-width"
|
|
19
|
+
:style="innerStyles"
|
|
20
|
+
>
|
|
21
|
+
<ui-component :spec="item" />
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
</v-row>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script>
|
|
29
|
+
import Vue from "vue";
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
props: {
|
|
33
|
+
spec: {
|
|
34
|
+
type: Object,
|
|
35
|
+
required: true,
|
|
36
|
+
default: function() {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
data() {
|
|
42
|
+
return {
|
|
43
|
+
innerStyles: {}
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
computed: {
|
|
47
|
+
cssClasses() {
|
|
48
|
+
// This panel will be nameless when used in predefined layout (e.g. page.body, list.header, etc.)
|
|
49
|
+
this.spec.view = this.spec.view || "panels/responsive";
|
|
50
|
+
return this.$classes();
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
methods: {
|
|
54
|
+
$ready() {
|
|
55
|
+
let align = null;
|
|
56
|
+
switch (this.spec.align) {
|
|
57
|
+
case "center":
|
|
58
|
+
align = "center";
|
|
59
|
+
break;
|
|
60
|
+
case "right":
|
|
61
|
+
align = "flex-end";
|
|
62
|
+
break;
|
|
63
|
+
default:
|
|
64
|
+
align = "flex-start";
|
|
65
|
+
}
|
|
66
|
+
Vue.set(this.innerStyles, "align-items", align);
|
|
67
|
+
},
|
|
68
|
+
isColumn(item) {
|
|
69
|
+
return item.view == "panels/column-v1";
|
|
70
|
+
},
|
|
71
|
+
viewKey(item, index) {
|
|
72
|
+
// Use view name for key to avoid component reuse issue
|
|
73
|
+
return `view${index}_${item.view}`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<style scoped>
|
|
80
|
+
.row {
|
|
81
|
+
margin-left: 0;
|
|
82
|
+
margin-right: 0;
|
|
83
|
+
}
|
|
84
|
+
.full-width {
|
|
85
|
+
width: 100%;
|
|
86
|
+
flex: 0 0 100%;
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-direction: column;
|
|
89
|
+
}
|
|
90
|
+
/* Needed to ensure that split's sub panels have the same height */
|
|
91
|
+
.full-height {
|
|
92
|
+
height: 100%;
|
|
93
|
+
}
|
|
94
|
+
</style>
|
|
File without changes
|