@things-factory/board-ui 10.1.40 → 10.1.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/board-list/board-thumb.d.ts +33 -0
- package/dist-client/board-list/board-thumb.js +119 -0
- package/dist-client/board-list/board-thumb.js.map +1 -0
- package/dist-client/graphql/favorite-board.js +3 -0
- package/dist-client/graphql/favorite-board.js.map +1 -1
- package/dist-client/graphql/my-board.js +3 -0
- package/dist-client/graphql/my-board.js.map +1 -1
- package/dist-client/graphql/play-group.js +2 -0
- package/dist-client/graphql/play-group.js.map +1 -1
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +1 -0
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/board-list-page.d.ts +39 -42
- package/dist-client/pages/board-list-page.js +388 -284
- package/dist-client/pages/board-list-page.js.map +1 -1
- package/dist-client/pages/board-modeller-page.d.ts +2 -0
- package/dist-client/pages/board-modeller-page.js +18 -1
- package/dist-client/pages/board-modeller-page.js.map +1 -1
- package/dist-client/pages/board-template/board-template-list-page.d.ts +21 -10
- package/dist-client/pages/board-template/board-template-list-page.js +147 -136
- package/dist-client/pages/board-template/board-template-list-page.js.map +1 -1
- package/dist-client/pages/play-list-page.d.ts +22 -12
- package/dist-client/pages/play-list-page.js +264 -113
- package/dist-client/pages/play-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/setting-let/board-modeller-setting-let.d.ts +21 -0
- package/dist-client/setting-let/board-modeller-setting-let.js +144 -0
- package/dist-client/setting-let/board-modeller-setting-let.js.map +1 -0
- package/dist-client/styles/board-card-styles.d.ts +11 -0
- package/dist-client/styles/board-card-styles.js +90 -0
- package/dist-client/styles/board-card-styles.js.map +1 -0
- package/dist-client/themes/board-theme.css +32 -19
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/board-meta.d.ts +10 -0
- package/dist-client/utils/board-meta.js +34 -0
- package/dist-client/utils/board-meta.js.map +1 -0
- package/dist-client/viewparts/board-basic-info.d.ts +38 -7
- package/dist-client/viewparts/board-basic-info.js +378 -349
- package/dist-client/viewparts/board-basic-info.js.map +1 -1
- package/dist-client/viewparts/board-info-link.d.ts +5 -1
- package/dist-client/viewparts/board-info-link.js +79 -21
- package/dist-client/viewparts/board-info-link.js.map +1 -1
- package/dist-client/viewparts/board-info-template.d.ts +15 -0
- package/dist-client/viewparts/board-info-template.js +97 -0
- package/dist-client/viewparts/board-info-template.js.map +1 -0
- package/dist-client/viewparts/board-info.d.ts +5 -0
- package/dist-client/viewparts/board-info.js +24 -73
- package/dist-client/viewparts/board-info.js.map +1 -1
- package/dist-client/viewparts/board-template-builder.d.ts +1 -0
- package/dist-client/viewparts/board-template-builder.js +37 -65
- package/dist-client/viewparts/board-template-builder.js.map +1 -1
- package/dist-client/viewparts/board-template-info.d.ts +3 -0
- package/dist-client/viewparts/board-template-info.js +75 -134
- package/dist-client/viewparts/board-template-info.js.map +1 -1
- package/dist-client/viewparts/group-info-basic.d.ts +8 -3
- package/dist-client/viewparts/group-info-basic.js +54 -190
- package/dist-client/viewparts/group-info-basic.js.map +1 -1
- package/dist-client/viewparts/group-info-import.d.ts +3 -1
- package/dist-client/viewparts/group-info-import.js +29 -62
- package/dist-client/viewparts/group-info-import.js.map +1 -1
- package/dist-client/viewparts/group-info.d.ts +4 -0
- package/dist-client/viewparts/group-info.js +21 -55
- package/dist-client/viewparts/group-info.js.map +1 -1
- package/dist-client/viewparts/info-dialog-styles.d.ts +19 -0
- package/dist-client/viewparts/info-dialog-styles.js +194 -0
- package/dist-client/viewparts/info-dialog-styles.js.map +1 -0
- package/dist-client/viewparts/link-builder.d.ts +3 -0
- package/dist-client/viewparts/link-builder.js +87 -81
- package/dist-client/viewparts/link-builder.js.map +1 -1
- package/dist-client/viewparts/play-group-info-basic.d.ts +4 -3
- package/dist-client/viewparts/play-group-info-basic.js +49 -188
- package/dist-client/viewparts/play-group-info-basic.js.map +1 -1
- package/dist-client/viewparts/play-group-info.d.ts +4 -0
- package/dist-client/viewparts/play-group-info.js +22 -53
- package/dist-client/viewparts/play-group-info.js.map +1 -1
- package/package.json +4 -4
- package/translations/en.json +32 -0
- package/translations/ja.json +10 -0
- package/translations/ko.json +32 -0
- package/translations/ms.json +8 -0
- package/translations/zh.json +10 -0
|
@@ -1,22 +1,31 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import '@operato/data-grist';
|
|
2
3
|
import '@material/web/icon/icon.js';
|
|
3
|
-
import '@material/web/
|
|
4
|
+
import '@material/web/button/text-button.js';
|
|
5
|
+
import '@operato/input/ox-input-select-buttons.js';
|
|
6
|
+
import '../board-list/board-thumb.js';
|
|
4
7
|
import '../viewparts/play-group-info.js';
|
|
5
|
-
import '../board-list/board-tile-list.js';
|
|
6
|
-
import '../board-list/play-group-bar.js';
|
|
7
8
|
import gql from 'graphql-tag';
|
|
8
9
|
import { css, html } from 'lit';
|
|
9
10
|
import { customElement, property, query } from 'lit/decorators.js';
|
|
11
|
+
import { DataGrist } from '@operato/data-grist';
|
|
10
12
|
import { UPDATE_FAVORITES } from '@things-factory/fav-base/client';
|
|
11
|
-
import {
|
|
13
|
+
import { openPopup } from '@operato/layout';
|
|
12
14
|
import { navigate, PageView, store } from '@operato/shell';
|
|
13
15
|
import { client } from '@operato/graphql';
|
|
14
16
|
import { i18next, localize } from '@operato/i18n';
|
|
15
|
-
import { ScrollbarStyles } from '@operato/styles';
|
|
17
|
+
import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
|
|
16
18
|
import { pulltorefresh } from '@operato/pull-to-refresh';
|
|
17
|
-
import { swipe, isMobileDevice } from '@things-factory/utils/src/index.js';
|
|
18
19
|
import { notify } from '../utils/notify-helper.js';
|
|
20
|
+
import { boardMeta } from '../utils/board-meta.js';
|
|
21
|
+
import { BoardCardStyles } from '../styles/board-card-styles.js';
|
|
19
22
|
import { createPlayGroup, deletePlayGroup, fetchPlayGroup, fetchPlayGroupList, updateBoard, updatePlayGroup } from '../graphql';
|
|
23
|
+
/*
|
|
24
|
+
* Same board-card look as board-list-page (ox-grist CARD mode, drag-reorder — see
|
|
25
|
+
* `data-grist`'s `rows.reorderable`, ADR: shared component over a board-only fork).
|
|
26
|
+
* A play group's board set is small and its own array *is* the order, so there is no pagination or
|
|
27
|
+
* server-side sort here - `fetchHandler` always hands back the whole thing.
|
|
28
|
+
*/
|
|
20
29
|
let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
21
30
|
constructor() {
|
|
22
31
|
super(...arguments);
|
|
@@ -25,66 +34,145 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
25
34
|
this.favorites = [];
|
|
26
35
|
}
|
|
27
36
|
static { this.styles = [
|
|
37
|
+
/* The frame owns the page shell; the grist is the content it sizes (ADR-0060 decision 8). */
|
|
38
|
+
WorkSurfacePageStyles,
|
|
28
39
|
ScrollbarStyles,
|
|
40
|
+
CommonGristStyles,
|
|
41
|
+
CommonHeaderStyles,
|
|
42
|
+
/* The card itself - shared with the other catalogs, see styles/board-card-styles.ts. */
|
|
43
|
+
BoardCardStyles,
|
|
29
44
|
css `
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
board-tile-list {
|
|
45
|
+
/*
|
|
46
|
+
The play groups are chips, not a tab strip - the same select-buttons the list's own
|
|
47
|
+
facets use, so this page and board-list read as one product. One is always pressed:
|
|
48
|
+
a play list is *of* a group, there is no "all groups" view here.
|
|
49
|
+
*/
|
|
50
|
+
ox-input-select-buttons {
|
|
39
51
|
flex: 1;
|
|
40
|
-
overflow-y: auto;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
#play {
|
|
44
|
-
position: absolute;
|
|
45
|
-
bottom: 15px;
|
|
46
|
-
right: 16px;
|
|
47
|
-
text-decoration: auto;
|
|
48
52
|
}
|
|
49
53
|
`
|
|
50
54
|
]; }
|
|
51
55
|
get context() {
|
|
52
|
-
|
|
56
|
+
/* The pressed chip already names the group; the title names the screen, as board-list's does. */
|
|
53
57
|
return {
|
|
54
|
-
title: {
|
|
55
|
-
icon: 'video_library',
|
|
56
|
-
text: group ? group.name : 'Play List'
|
|
57
|
-
},
|
|
58
|
+
title: i18next.t('title.play list', { defaultValue: 'Play List' }),
|
|
58
59
|
board_topmenu: true
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
render() {
|
|
63
|
+
const current = (this.groups || []).find(group => group.id === this.groupId);
|
|
62
64
|
return html `
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
<ox-grist
|
|
66
|
+
class="page-fill"
|
|
67
|
+
mode="CARD"
|
|
68
|
+
.config=${this.gristConfig}
|
|
69
|
+
.fetchHandler=${this.fetchHandler.bind(this)}
|
|
70
|
+
@reorder=${e => this.onReorder(e.detail)}
|
|
71
|
+
>
|
|
72
|
+
<div slot="headroom">
|
|
73
|
+
<ox-input-select-buttons
|
|
74
|
+
.value=${this.groupId || ''}
|
|
75
|
+
.options=${(this.groups || []).map(group => ({ display: group.name, value: group.id }))}
|
|
76
|
+
@change=${(e) => {
|
|
77
|
+
const id = e.detail;
|
|
78
|
+
/* The URL stays the source of truth - same round trip a deep link takes. */
|
|
79
|
+
if (id && id !== this.groupId)
|
|
80
|
+
navigate(`${this.page || 'play-list'}/${id}`);
|
|
81
|
+
}}
|
|
82
|
+
></ox-input-select-buttons>
|
|
83
|
+
${current
|
|
84
|
+
? html `
|
|
85
|
+
<md-text-button @click=${() => this.onInfoPlayGroup(current)}>
|
|
86
|
+
<md-icon slot="icon">edit</md-icon>
|
|
87
|
+
${i18next.t('text.edit play-group', { defaultValue: 'Edit' })}
|
|
88
|
+
</md-text-button>
|
|
89
|
+
`
|
|
90
|
+
: ''}
|
|
91
|
+
<md-text-button @click=${() => this.onInfoPlayGroup(undefined)}>
|
|
92
|
+
<md-icon slot="icon">playlist_add</md-icon>
|
|
93
|
+
${i18next.t('text.new play-group', { defaultValue: 'New Play Group' })}
|
|
94
|
+
</md-text-button>
|
|
95
|
+
</div>
|
|
96
|
+
</ox-grist>
|
|
80
97
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
${this.groupId
|
|
99
|
+
? html `
|
|
100
|
+
<button fab title=${i18next.t('label.play', { defaultValue: 'Play' })} @click=${() => navigate(`board-player/${this.groupId}`)}>
|
|
101
|
+
<md-icon>play_arrow</md-icon>${i18next.t('label.play', { defaultValue: 'Play' })}
|
|
102
|
+
</button>
|
|
103
|
+
`
|
|
104
|
+
: ''}
|
|
86
105
|
`;
|
|
87
106
|
}
|
|
107
|
+
async pageInitialized() {
|
|
108
|
+
this.gristConfig = {
|
|
109
|
+
list: {
|
|
110
|
+
thumbnail: 'thumbnail',
|
|
111
|
+
fields: ['name', 'meta'],
|
|
112
|
+
details: []
|
|
113
|
+
},
|
|
114
|
+
columns: [
|
|
115
|
+
{
|
|
116
|
+
type: 'image',
|
|
117
|
+
name: 'thumbnail',
|
|
118
|
+
record: {
|
|
119
|
+
editable: false,
|
|
120
|
+
align: 'center',
|
|
121
|
+
renderEmpty: true,
|
|
122
|
+
/* board-thumb.ts owns the picture and draft badge; info/favorite are gutter columns
|
|
123
|
+
* below - see board-list-page.ts's identical setup and board-thumb.ts's own comment. */
|
|
124
|
+
renderer: (value, column, record) => html `<board-thumb .board=${record}></board-thumb>`
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{ type: 'string', name: 'name', record: { editable: false } },
|
|
128
|
+
{ type: 'string', name: 'meta', record: { editable: false } },
|
|
129
|
+
{
|
|
130
|
+
type: 'gutter',
|
|
131
|
+
gutterName: 'button',
|
|
132
|
+
name: 'edit',
|
|
133
|
+
/* Edit first, the star last - same order as board-list-page.ts. */
|
|
134
|
+
icon: 'edit',
|
|
135
|
+
quiet: true,
|
|
136
|
+
title: i18next.t('label.edit', { defaultValue: 'Edit' }),
|
|
137
|
+
handlers: {
|
|
138
|
+
click: (_columns, _data, _column, record) => this.onInfoBoard(record)
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: 'gutter',
|
|
143
|
+
gutterName: 'button',
|
|
144
|
+
name: 'favorite',
|
|
145
|
+
icon: (record) => (record?.favorited ? 'star' : 'star_border'),
|
|
146
|
+
quiet: (record) => !record?.favorited,
|
|
147
|
+
title: (record) => i18next.t(record?.favorited ? 'label.unfavorite' : 'label.favorite', {
|
|
148
|
+
defaultValue: record?.favorited ? 'Remove from favorites' : 'Add to favorites'
|
|
149
|
+
}),
|
|
150
|
+
handlers: {
|
|
151
|
+
click: (_columns, _data, _column, record) => this.toggleFavorite(record)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
rows: {
|
|
156
|
+
selectable: false,
|
|
157
|
+
appendable: false,
|
|
158
|
+
reorderable: true,
|
|
159
|
+
handlers: {
|
|
160
|
+
click: (_columns, _data, _column, record) => navigate(`board-viewer/${record.id}`)
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
sorters: []
|
|
164
|
+
};
|
|
165
|
+
this.refresh();
|
|
166
|
+
}
|
|
167
|
+
async fetchHandler(_option) {
|
|
168
|
+
const favorites = this.favorites || [];
|
|
169
|
+
const records = (this.boards || []).map(board => ({
|
|
170
|
+
...board,
|
|
171
|
+
favorited: favorites.includes(board.id),
|
|
172
|
+
meta: boardMeta(board)
|
|
173
|
+
}));
|
|
174
|
+
return { total: records.length, records };
|
|
175
|
+
}
|
|
88
176
|
async refresh() {
|
|
89
177
|
this.groups = (await fetchPlayGroupList()).playGroups.items;
|
|
90
178
|
this.groups && (await this.refreshBoards());
|
|
@@ -95,11 +183,15 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
95
183
|
return;
|
|
96
184
|
}
|
|
97
185
|
if (!this.groupId) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
186
|
+
const groupId = this.groups && this.groups[0] && this.groups[0].id;
|
|
187
|
+
/*
|
|
188
|
+
* Build the address from the page name, not by appending to window.location: re-entering
|
|
189
|
+
* this page from the rail while a play-list/<id> URL is still current appended a second
|
|
190
|
+
* id (play-list/<id>/<id>), the route stopped matching and groupId came back empty - no chip
|
|
191
|
+
* pressed, no Edit button (seen live 2026-09-23).
|
|
192
|
+
*/
|
|
101
193
|
if (groupId) {
|
|
102
|
-
navigate(
|
|
194
|
+
navigate(`${this.page || 'play-list'}/${groupId}`, true);
|
|
103
195
|
}
|
|
104
196
|
return;
|
|
105
197
|
}
|
|
@@ -111,21 +203,31 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
111
203
|
this.boards = [];
|
|
112
204
|
}
|
|
113
205
|
this.updateContext();
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.refresh();
|
|
206
|
+
this.grist?.fetch();
|
|
207
|
+
if (this.grist) {
|
|
208
|
+
this.grist.style.transition = '';
|
|
209
|
+
this.grist.style.transform = `translate3d(0, 0, 0)`;
|
|
210
|
+
}
|
|
120
211
|
}
|
|
121
212
|
async pageUpdated(changes, lifecycle) {
|
|
122
213
|
if (this.active) {
|
|
123
214
|
this.page = lifecycle.page;
|
|
124
|
-
|
|
215
|
+
/*
|
|
216
|
+
* On a full page load the router can deliver the bare /play-list lifecycle *after* this
|
|
217
|
+
* page has already redirected itself to /play-list/<first group> - the id would be wiped
|
|
218
|
+
* while the URL still shows it (no chip pressed, no Edit button; seen live 2026-09-23).
|
|
219
|
+
* The address bar is the source of truth, so read the id back from it in that case.
|
|
220
|
+
*/
|
|
221
|
+
this.groupId = lifecycle.resourceId || this.groupIdFromLocation();
|
|
125
222
|
await this.updateComplete;
|
|
126
223
|
this.refreshBoards();
|
|
127
224
|
}
|
|
128
225
|
}
|
|
226
|
+
groupIdFromLocation() {
|
|
227
|
+
const segments = location.pathname.split('/').filter(Boolean);
|
|
228
|
+
const at = segments.lastIndexOf(this.page || 'play-list');
|
|
229
|
+
return at >= 0 ? segments[at + 1] || '' : '';
|
|
230
|
+
}
|
|
129
231
|
connectedCallback() {
|
|
130
232
|
super.connectedCallback();
|
|
131
233
|
this._applyState();
|
|
@@ -137,57 +239,31 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
137
239
|
}
|
|
138
240
|
_applyState() {
|
|
139
241
|
const __state__ = store.getState();
|
|
140
|
-
|
|
242
|
+
const favorites = __state__.favorite.favorites;
|
|
243
|
+
/*
|
|
244
|
+
* `store.subscribe` fires on every dispatch anywhere in the app, not just favorite changes - an
|
|
245
|
+
* unconditional fetch() here risks a loop if fetch() completing itself dispatches through this
|
|
246
|
+
* same store (board-list-page.ts hit exactly this).
|
|
247
|
+
*/
|
|
248
|
+
const changed = JSON.stringify(favorites) !== JSON.stringify(this.favorites);
|
|
249
|
+
this.favorites = favorites;
|
|
250
|
+
if (changed) {
|
|
251
|
+
this.grist?.fetch();
|
|
252
|
+
}
|
|
141
253
|
}
|
|
142
254
|
firstUpdated() {
|
|
143
|
-
|
|
255
|
+
/* Groups are chips now, one tap each - the swipe-between-routes gesture the tab strip needed
|
|
256
|
+
* no longer has a job here. */
|
|
144
257
|
pulltorefresh({
|
|
145
258
|
container: this.shadowRoot,
|
|
146
|
-
scrollable:
|
|
259
|
+
scrollable: this.grist,
|
|
147
260
|
refresh: () => {
|
|
148
261
|
return this.refresh();
|
|
149
262
|
}
|
|
150
263
|
});
|
|
151
|
-
if (isMobileDevice()) {
|
|
152
|
-
swipe({
|
|
153
|
-
container: list,
|
|
154
|
-
animates: {
|
|
155
|
-
dragging: async (d, opts) => {
|
|
156
|
-
const groups = this.groups;
|
|
157
|
-
const currentIndex = groups.findIndex(group => group.id == this.groupId);
|
|
158
|
-
if ((d > 0 && currentIndex <= 0) || (d < 0 && currentIndex >= groups.length - 1)) {
|
|
159
|
-
/* TODO blocked gesture */
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
list.style.transform = `translate3d(${d}px, 0, 0)`;
|
|
163
|
-
},
|
|
164
|
-
aborting: async (opts) => {
|
|
165
|
-
list.style.transition = 'transform 0.3s';
|
|
166
|
-
list.style.transform = `translate3d(0, 0, 0)`;
|
|
167
|
-
setTimeout(() => {
|
|
168
|
-
list.style.transition = '';
|
|
169
|
-
}, 300);
|
|
170
|
-
},
|
|
171
|
-
swiping: async (d, opts) => {
|
|
172
|
-
const groups = this.groups;
|
|
173
|
-
const currentIndex = groups.findIndex(group => group.id == this.groupId);
|
|
174
|
-
if ((d > 0 && currentIndex <= 0) || (d < 0 && currentIndex >= groups.length - 1)) {
|
|
175
|
-
list.style.transition = '';
|
|
176
|
-
list.style.transform = `translate3d(0, 0, 0)`;
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
list.style.transition = 'transform 0.3s';
|
|
180
|
-
list.style.transform = `translate3d(${d < 0 ? '-100%' : '100%'}, 0, 0)`;
|
|
181
|
-
navigate(`${this.page}/${groups[currentIndex + (d < 0 ? 1 : -1)].id}`);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
264
|
}
|
|
188
265
|
async onInfoBoard(board) {
|
|
189
|
-
|
|
190
|
-
template: html `
|
|
266
|
+
openPopup(html `
|
|
191
267
|
<board-info
|
|
192
268
|
.board=${board}
|
|
193
269
|
.groupId=${this.groupId}
|
|
@@ -196,19 +272,21 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
196
272
|
@join-playgroup=${e => this.onJoinPlayGroup(e.detail)}
|
|
197
273
|
@leave-playgroup=${e => this.onLeavePlayGroup(e.detail)}
|
|
198
274
|
></board-info>
|
|
199
|
-
|
|
200
|
-
});
|
|
275
|
+
`, { backdrop: true, size: 'medium', closable: true, title: board.name });
|
|
201
276
|
}
|
|
202
277
|
async onInfoPlayGroup(group) {
|
|
203
|
-
|
|
204
|
-
template: html `
|
|
278
|
+
openPopup(html `
|
|
205
279
|
<play-group-info
|
|
206
280
|
.playGroup=${group}
|
|
207
281
|
@update-play-group=${e => this.onUpdatePlayGroup(e.detail)}
|
|
208
282
|
@delete-play-group=${e => this.onDeletePlayGroup(e.detail)}
|
|
209
283
|
@create-play-group=${e => this.onCreatePlayGroup(e.detail)}
|
|
210
284
|
></play-group-info>
|
|
211
|
-
|
|
285
|
+
`, {
|
|
286
|
+
backdrop: true,
|
|
287
|
+
size: 'small',
|
|
288
|
+
closable: true,
|
|
289
|
+
title: group?.name || i18next.t('text.new play-group', { defaultValue: 'New Play Group' })
|
|
212
290
|
});
|
|
213
291
|
}
|
|
214
292
|
async onCreatePlayGroup(playGroup) {
|
|
@@ -299,7 +377,8 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
299
377
|
}
|
|
300
378
|
this.refresh();
|
|
301
379
|
}
|
|
302
|
-
async onReorder({
|
|
380
|
+
async onReorder({ ids, movedId }) {
|
|
381
|
+
const groupId = this.groupId;
|
|
303
382
|
try {
|
|
304
383
|
const response = await client.mutate({
|
|
305
384
|
mutation: gql `
|
|
@@ -312,7 +391,7 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
312
391
|
`,
|
|
313
392
|
variables: {
|
|
314
393
|
id: groupId,
|
|
315
|
-
boardIds
|
|
394
|
+
boardIds: ids
|
|
316
395
|
}
|
|
317
396
|
});
|
|
318
397
|
const playGroup = response.data.reorderPlayGroup;
|
|
@@ -320,10 +399,78 @@ let PlayListPage = class PlayListPage extends localize(i18next)(PageView) {
|
|
|
320
399
|
}
|
|
321
400
|
catch (ex) {
|
|
322
401
|
notify('error', ex, ex);
|
|
323
|
-
|
|
402
|
+
/* 실패 시에만 서버 데이터로 복원 */
|
|
324
403
|
this.refresh();
|
|
325
404
|
}
|
|
326
405
|
}
|
|
406
|
+
async toggleFavorite(board) {
|
|
407
|
+
const wasFavorite = (this.favorites || []).includes(board.id);
|
|
408
|
+
/*
|
|
409
|
+
* The star answers the click at once; the server round trip only confirms it. Before, nothing
|
|
410
|
+
* moved until the mutation, the favorites re-query, the store dispatch and a full refetch had
|
|
411
|
+
* all come back - a click with no reaction reads as a click that did not land.
|
|
412
|
+
*
|
|
413
|
+
* `favorites` is set locally too, so the store update that follows carries the same list and
|
|
414
|
+
* `_applyState` does not trigger the refetch that would repaint every card.
|
|
415
|
+
*/
|
|
416
|
+
this.favorites = wasFavorite
|
|
417
|
+
? (this.favorites || []).filter(id => id !== board.id)
|
|
418
|
+
: [...(this.favorites || []), board.id];
|
|
419
|
+
this.patchRecord(board.id, { favorited: !wasFavorite });
|
|
420
|
+
try {
|
|
421
|
+
if (wasFavorite) {
|
|
422
|
+
await this.removeFavorite(board.id);
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
await this.addFavorite(board.id);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
catch (ex) {
|
|
429
|
+
/* Put it back the way it was and say why. */
|
|
430
|
+
this.favorites = wasFavorite
|
|
431
|
+
? [...(this.favorites || []), board.id]
|
|
432
|
+
: (this.favorites || []).filter(id => id !== board.id);
|
|
433
|
+
this.patchRecord(board.id, { favorited: wasFavorite });
|
|
434
|
+
notify('error', ex?.message || String(ex));
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/** Replaces one record in the grist in place, so only that card re-renders. */
|
|
438
|
+
patchRecord(id, patch) {
|
|
439
|
+
const grist = this.grist;
|
|
440
|
+
const data = grist?.data;
|
|
441
|
+
if (!data?.records) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
grist.data = {
|
|
445
|
+
...data,
|
|
446
|
+
records: data.records.map(record => (record.id === id ? { ...record, ...patch } : record))
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
async removeFavorite(boardId) {
|
|
450
|
+
await client.mutate({
|
|
451
|
+
mutation: gql `
|
|
452
|
+
mutation {
|
|
453
|
+
deleteFavorite(routing: "${boardId}")
|
|
454
|
+
}
|
|
455
|
+
`
|
|
456
|
+
});
|
|
457
|
+
this.refreshFavorites();
|
|
458
|
+
}
|
|
459
|
+
async addFavorite(boardId) {
|
|
460
|
+
await client.mutate({
|
|
461
|
+
mutation: gql `
|
|
462
|
+
mutation {
|
|
463
|
+
createFavorite(favorite: {
|
|
464
|
+
routing: "${boardId}"
|
|
465
|
+
}) {
|
|
466
|
+
id
|
|
467
|
+
routing
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
`
|
|
471
|
+
});
|
|
472
|
+
this.refreshFavorites();
|
|
473
|
+
}
|
|
327
474
|
async refreshFavorites() {
|
|
328
475
|
const response = await client.query({
|
|
329
476
|
query: gql `
|
|
@@ -358,9 +505,13 @@ __decorate([
|
|
|
358
505
|
__metadata("design:type", Array)
|
|
359
506
|
], PlayListPage.prototype, "favorites", void 0);
|
|
360
507
|
__decorate([
|
|
361
|
-
|
|
362
|
-
__metadata("design:type",
|
|
363
|
-
], PlayListPage.prototype, "
|
|
508
|
+
property({ type: Object }),
|
|
509
|
+
__metadata("design:type", Object)
|
|
510
|
+
], PlayListPage.prototype, "gristConfig", void 0);
|
|
511
|
+
__decorate([
|
|
512
|
+
query('ox-grist'),
|
|
513
|
+
__metadata("design:type", DataGrist)
|
|
514
|
+
], PlayListPage.prototype, "grist", void 0);
|
|
364
515
|
PlayListPage = __decorate([
|
|
365
516
|
customElement('play-list-page')
|
|
366
517
|
], PlayListPage);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"play-list-page.js","sourceRoot":"","sources":["../../client/pages/play-list-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/fab/fab.js'\n\nimport '../viewparts/play-group-info.js'\nimport '../board-list/board-tile-list.js'\nimport '../board-list/play-group-bar.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { UPDATE_FAVORITES } from '@things-factory/fav-base/client'\nimport { openOverlay } from '@operato/layout'\nimport { navigate, PageView, store } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { pulltorefresh } from '@operato/pull-to-refresh'\nimport { swipe, isMobileDevice } from '@things-factory/utils/src/index.js'\nimport { notify } from '../utils/notify-helper.js'\n\nimport {\n createPlayGroup,\n deletePlayGroup,\n fetchPlayGroup,\n fetchPlayGroupList,\n leavePlayGroup,\n updateBoard,\n updatePlayGroup\n} from '../graphql'\n\n@customElement('play-list-page')\nexport class PlayListPage extends localize(i18next)(PageView) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n position: relative;\n\n overflow: hidden;\n }\n\n board-tile-list {\n flex: 1;\n overflow-y: auto;\n }\n\n #play {\n position: absolute;\n bottom: 15px;\n right: 16px;\n text-decoration: auto;\n }\n `\n ]\n\n @property({ type: String }) groupId?: string\n @property({ type: Array }) groups: any[] = []\n @property({ type: Array }) boards: any[] = []\n @property({ type: Array }) favorites: any[] = []\n\n @query('board-tile-list') boardTileList!: HTMLElement\n\n private page?: string\n\n get context() {\n const group = this.groups && this.groups.find(group => group.id === this.groupId)\n\n return {\n title: {\n icon: 'video_library',\n text: group ? group.name : 'Play List'\n },\n board_topmenu: true\n }\n }\n\n render() {\n return html`\n <play-group-bar\n .groups=${this.groups}\n .groupId=${this.groupId}\n target-page=\"play-list\"\n @info-play-group=${e => this.onInfoPlayGroup(e.detail)}\n ></play-group-bar>\n\n <board-tile-list\n .favorites=${this.favorites}\n .boards=${this.boards}\n .group=${this.groupId}\n @info-board=${e => this.onInfoBoard(e.detail)}\n @delete-board=${e => this.onDeleteBoard(e.detail)}\n @refresh-favorites=${e => this.refreshFavorites()}\n @reordered=${e => this.onReorder(e.detail)}\n reorderable\n ></board-tile-list>\n\n <a id=\"play\" .href=${'board-player/' + this.groupId}>\n <md-fab title=\"play\">\n <md-icon slot=\"icon\">play_arrow</md-icon>\n </md-fab>\n </a>\n `\n }\n\n async refresh() {\n this.groups = (await fetchPlayGroupList()).playGroups.items\n\n this.groups && (await this.refreshBoards())\n }\n\n async refreshBoards() {\n if (!this.groups) {\n await this.refresh()\n return\n }\n\n if (!this.groupId) {\n let groupId = this.groups && this.groups[0] && this.groups[0].id\n const newURL = new URL(window.location.href)\n\n newURL.pathname += `/${groupId}`\n\n if (groupId) {\n navigate(newURL.href, true)\n }\n return\n }\n\n if (this.groupId) {\n const playGroup = (await fetchPlayGroup(this.groupId)).playGroup\n this.boards = playGroup ? playGroup.boards : []\n } else {\n this.boards = []\n }\n\n this.updateContext()\n\n const list = this.boardTileList\n\n list.style.transition = ''\n list.style.transform = `translate3d(0, 0, 0)`\n }\n\n async pageInitialized() {\n this.refresh()\n }\n\n async pageUpdated(changes, lifecycle) {\n if (this.active) {\n this.page = lifecycle.page\n this.groupId = lifecycle.resourceId\n\n await this.updateComplete\n\n this.refreshBoards()\n }\n }\n\n private _unsubscribe?: () => void\n\n\n connectedCallback() {\n\n super.connectedCallback()\n\n this._applyState()\n\n this._unsubscribe = store.subscribe(() => this._applyState())\n\n }\n\n\n disconnectedCallback() {\n\n super.disconnectedCallback()\n\n this._unsubscribe?.()\n\n }\n\n\n private _applyState() {\n const __state__ = store.getState() as any\n this.favorites = __state__.favorite.favorites\n }\n\n firstUpdated() {\n const list = this.boardTileList\n\n pulltorefresh({\n container: this.shadowRoot,\n scrollable: list,\n refresh: () => {\n return this.refresh()\n }\n })\n\n if (isMobileDevice()) {\n swipe({\n container: list,\n animates: {\n dragging: async (d, opts) => {\n const groups = this.groups\n const currentIndex = groups.findIndex(group => group.id == this.groupId)\n\n if ((d > 0 && currentIndex <= 0) || (d < 0 && currentIndex >= groups.length - 1)) {\n /* TODO blocked gesture */\n return false\n }\n\n list.style.transform = `translate3d(${d}px, 0, 0)`\n },\n aborting: async opts => {\n list.style.transition = 'transform 0.3s'\n list.style.transform = `translate3d(0, 0, 0)`\n\n setTimeout(() => {\n list.style.transition = ''\n }, 300)\n },\n swiping: async (d, opts) => {\n const groups = this.groups\n const currentIndex = groups.findIndex(group => group.id == this.groupId)\n\n if ((d > 0 && currentIndex <= 0) || (d < 0 && currentIndex >= groups.length - 1)) {\n list.style.transition = ''\n list.style.transform = `translate3d(0, 0, 0)`\n } else {\n list.style.transition = 'transform 0.3s'\n list.style.transform = `translate3d(${d < 0 ? '-100%' : '100%'}, 0, 0)`\n\n navigate(`${this.page}/${groups[currentIndex + (d < 0 ? 1 : -1)].id}`)\n }\n }\n }\n })\n }\n }\n\n async onInfoBoard(board) {\n openOverlay('viewpart-info', {\n template: html`\n <board-info\n .board=${board}\n .groupId=${this.groupId}\n @update-board=${e => this.onUpdateBoard(e.detail)}\n @delete-board=${e => this.onDeleteBoard(e.detail)}\n @join-playgroup=${e => this.onJoinPlayGroup(e.detail)}\n @leave-playgroup=${e => this.onLeavePlayGroup(e.detail)}\n ></board-info>\n `\n })\n }\n\n async onInfoPlayGroup(group) {\n openOverlay('viewpart-info', {\n template: html`\n <play-group-info\n .playGroup=${group}\n @update-play-group=${e => this.onUpdatePlayGroup(e.detail)}\n @delete-play-group=${e => this.onDeletePlayGroup(e.detail)}\n @create-play-group=${e => this.onCreatePlayGroup(e.detail)}\n ></play-group-info>\n `\n })\n }\n\n async onCreatePlayGroup(playGroup) {\n try {\n await createPlayGroup(playGroup)\n notify('info', i18next.t('text.play-group created', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onUpdatePlayGroup(playGroup) {\n try {\n await updatePlayGroup(playGroup)\n notify('info', i18next.t('text.play-group updated', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onDeletePlayGroup(playGroup) {\n try {\n await deletePlayGroup(playGroup.id)\n notify('info', i18next.t('text.play-group deleted', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onUpdateBoard(board) {\n try {\n await updateBoard(board)\n notify('info', i18next.t('text.board updated', { board: board.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refreshBoards()\n }\n\n async onDeleteBoard(board) {\n const playGroup = this.groups && this.groups.find(group => group.id === this.groupId)\n await this.onLeavePlayGroup({ board, playGroup })\n }\n\n async onJoinPlayGroup({ board, playGroup }) {\n try {\n await client.mutate({\n mutation: gql`\n mutation JoinPlayGroup($id: String!, $boardIds: [String!]!) {\n joinPlayGroup(id: $id, boardIds: $boardIds) {\n id\n }\n }\n `,\n variables: {\n id: playGroup.id,\n boardIds: [board.id]\n }\n })\n\n notify('info', i18next.t('text.joined into play-group', { board: board.name, playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onLeavePlayGroup({ board, playGroup }) {\n try {\n await client.mutate({\n mutation: gql`\n mutation ($id: String!, $boardIds: [String!]!) {\n leavePlayGroup(id: $id, boardIds: $boardIds) {\n id\n }\n }\n `,\n variables: {\n id: playGroup.id,\n boardIds: [board.id]\n }\n })\n\n notify('info', i18next.t('text.leaved from play-group', { board: board.name, playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onReorder({ boardIds, groupId }) {\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $boardIds: [String!]!) {\n reorderPlayGroup(id: $id, boardIds: $boardIds) {\n id\n name\n }\n }\n `,\n variables: {\n id: groupId,\n boardIds\n }\n })\n\n const playGroup = response.data.reorderPlayGroup\n\n notify('info', i18next.t('text.reorder play-group', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n // 실패 시에만 서버 데이터로 복원\n this.refresh()\n }\n }\n\n async refreshFavorites() {\n const response = await client.query({\n query: gql`\n query {\n myFavorites {\n id\n routing\n }\n }\n `\n })\n\n store.dispatch({\n type: UPDATE_FAVORITES,\n favorites: response.data.myFavorites.map(favorite => favorite.routing)\n })\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"play-list-page.js","sourceRoot":"","sources":["../../client/pages/play-list-page.ts"],"names":[],"mappings":";AAAA,OAAO,qBAAqB,CAAA;AAC5B,OAAO,4BAA4B,CAAA;AACnC,OAAO,qCAAqC,CAAA;AAC5C,OAAO,2CAA2C,CAAA;AAElD,OAAO,8BAA8B,CAAA;AACrC,OAAO,iCAAiC,CAAA;AAExC,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,SAAS,EAAe,MAAM,qBAAqB,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC/G,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EACL,eAAe,EACf,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB;;;;;GAKG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;IAAtD;;QAsBsB,WAAM,GAAU,EAAE,CAAA;QAClB,WAAM,GAAU,EAAE,CAAA;QAClB,cAAS,GAAU,EAAE,CAAA;IAqflD,CAAC;aA5gBQ,WAAM,GAAG;QACd,6FAA6F;QAC7F,qBAAqB;QACrB,eAAe;QACf,iBAAiB;QACjB,kBAAkB;QAClB,wFAAwF;QACxF,eAAe;QACf,GAAG,CAAA;;;;;;;;;KASF;KACF,AAlBY,CAkBZ;IAYD,IAAI,OAAO;QACT,iGAAiG;QACjG,OAAO;YACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,iBAAiB,EAAE,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;YAClE,aAAa,EAAE,IAAI;SACpB,CAAA;IACH,CAAC;IAED,MAAM;QACJ,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,CAAA;QAE5E,OAAO,IAAI,CAAA;;;;kBAIG,IAAI,CAAC,WAAW;wBACV,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;mBACjC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;;;;qBAI3B,IAAI,CAAC,OAAO,IAAI,EAAE;uBAChB,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;sBAC7E,CAAC,CAAc,EAAE,EAAE;YAC3B,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAAA;YACnB,4EAA4E;YAC5E,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,OAAO;gBAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,IAAI,EAAE,EAAE,CAAC,CAAA;QAC9E,CAAC;;YAED,OAAO;YACP,CAAC,CAAC,IAAI,CAAA;yCACuB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;;oBAExD,OAAO,CAAC,CAAC,CAAC,sBAAsB,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;;eAEhE;YACH,CAAC,CAAC,EAAE;mCACmB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC;;cAE1D,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;;;;;QAK1E,IAAI,CAAC,OAAO;YACZ,CAAC,CAAC,IAAI,CAAA;gCACkB,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,QAAQ,CAAC,gBAAgB,IAAI,CAAC,OAAO,EAAE,CAAC;6CAC7F,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;;WAEnF;YACH,CAAC,CAAC,EAAE;KACP,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC,WAAW,GAAG;YACjB,IAAI,EAAE;gBACJ,SAAS,EAAE,WAAW;gBACtB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;gBACxB,OAAO,EAAE,EAAE;aACZ;YACD,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,OAAO;oBACb,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE;wBACN,QAAQ,EAAE,KAAK;wBACf,KAAK,EAAE,QAAQ;wBACf,WAAW,EAAE,IAAI;wBACjB;gHACwF;wBACxF,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAA,uBAAuB,MAAM,iBAAiB;qBACxF;iBACF;gBACD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;gBAC7D,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;gBAC7D;oBACE,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,QAAQ;oBACpB,IAAI,EAAE,MAAM;oBACZ,mEAAmE;oBACnE,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE,IAAI;oBACX,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;oBACxD,QAAQ,EAAE;wBACR,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;qBACtE;iBACF;gBACD;oBACE,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE,QAAQ;oBACpB,IAAI,EAAE,UAAU;oBAChB,IAAI,EAAE,CAAC,MAAY,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC;oBACpE,KAAK,EAAE,CAAC,MAAY,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,SAAS;oBAC3C,KAAK,EAAE,CAAC,MAAY,EAAE,EAAE,CACtB,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,gBAAgB,EAAE;wBACnE,YAAY,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,kBAAkB;qBAC/E,CAAC;oBACJ,QAAQ,EAAE;wBACR,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;qBACzE;iBACF;aACF;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE,KAAK;gBACjB,UAAU,EAAE,KAAK;gBACjB,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE;oBACR,KAAK,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,MAAM,CAAC,EAAE,EAAE,CAAC;iBACnF;aACF;YACD,OAAO,EAAE,EAAE;SACZ,CAAA;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAoB;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAA;QACtC,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChD,GAAG,KAAK;YACR,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACvC,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC;SACvB,CAAC,CAAC,CAAA;QAEH,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAA;IAC3C,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,kBAAkB,EAAE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAA;QAE3D,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,CAAA;IAC7C,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;YACpB,OAAM;QACR,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAElE;;;;;eAKG;YACH,IAAI,OAAO,EAAE,CAAC;gBACZ,QAAQ,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,IAAI,OAAO,EAAE,EAAE,IAAI,CAAC,CAAA;YAC1D,CAAC;YACD,OAAM;QACR,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;YAChE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAA;QACjD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,EAAE,CAAA;QAClB,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;QAEnB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAA;YAChC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,sBAAsB,CAAA;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS;QAClC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAA;YAC1B;;;;;eAKG;YACH,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,UAAU,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAA;YAEjE,MAAM,IAAI,CAAC,cAAc,CAAA;YAEzB,IAAI,CAAC,aAAa,EAAE,CAAA;QACtB,CAAC;IACH,CAAC;IAEO,mBAAmB;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC7D,MAAM,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC,CAAA;QAEzD,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IAC9C,CAAC;IAID,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,IAAI,CAAC,WAAW,EAAE,CAAA;QAElB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,YAAY,EAAE,EAAE,CAAA;IACvB,CAAC;IAEO,WAAW;QACjB,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAS,CAAA;QACzC,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAA;QAE9C;;;;WAIG;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAC5E,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAE1B,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAA;QACrB,CAAC;IACH,CAAC;IAED,YAAY;QACV;uCAC+B;QAC/B,aAAa,CAAC;YACZ,SAAS,EAAE,IAAI,CAAC,UAAU;YAC1B,UAAU,EAAE,IAAI,CAAC,KAAK;YACtB,OAAO,EAAE,GAAG,EAAE;gBACZ,OAAO,IAAI,CAAC,OAAO,EAAE,CAAA;YACvB,CAAC;SACF,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAK;QACrB,SAAS,CACP,IAAI,CAAA;;mBAES,KAAK;qBACH,IAAI,CAAC,OAAO;0BACP,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;0BACjC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC;4BAC/B,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC;6BAClC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC;;OAE1D,EACD,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CACtE,CAAA;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAAK;QACzB,SAAS,CACP,IAAI,CAAA;;uBAEa,KAAK;+BACG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC;+BACrC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC;+BACrC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC;;OAE7D,EACD;YACE,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;SAC3F,CACF,CAAA;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,SAAS;QAC/B,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,SAAS,CAAC,CAAA;YAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrF,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,SAAS;QAC/B,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,SAAS,CAAC,CAAA;YAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrF,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,SAAS;QAC/B,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YACnC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrF,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAK;QACvB,IAAI,CAAC;YACH,MAAM,WAAW,CAAC,KAAK,CAAC,CAAA;YACxB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACxE,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,KAAK;QACvB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,OAAO,CAAC,CAAA;QACrF,MAAM,IAAI,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC;gBAClB,QAAQ,EAAE,GAAG,CAAA;;;;;;SAMZ;gBACD,SAAS,EAAE;oBACT,EAAE,EAAE,SAAS,CAAC,EAAE;oBAChB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;iBACrB;aACF,CAAC,CAAA;YAEF,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC5G,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,MAAM,CAAC;gBAClB,QAAQ,EAAE,GAAG,CAAA;;;;;;SAMZ;gBACD,SAAS,EAAE;oBACT,EAAE,EAAE,SAAS,CAAC,EAAE;oBAChB,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;iBACrB;aACF,CAAC,CAAA;YAEF,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QAC5G,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACzB,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAsC;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAE5B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;gBACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;;SAOZ;gBACD,SAAS,EAAE;oBACT,EAAE,EAAE,OAAO;oBACX,QAAQ,EAAE,GAAG;iBACd;aACF,CAAC,CAAA;YAEF,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAA;YAEhD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;QACrF,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;YACvB,uBAAuB;YACvB,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAAK;QACxB,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAE7D;;;;;;;WAOG;QACH,IAAI,CAAC,SAAS,GAAG,WAAW;YAC1B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC;YACtD,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QACzC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,WAAW,EAAE,CAAC,CAAA;QAEvD,IAAI,CAAC;YACH,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YACrC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YAClC,CAAC;QACH,CAAC;QAAC,OAAO,EAAE,EAAE,CAAC;YACZ,6CAA6C;YAC7C,IAAI,CAAC,SAAS,GAAG,WAAW;gBAC1B,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;gBACvC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAA;YACxD,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;YACtD,MAAM,CAAC,OAAO,EAAG,EAAU,EAAE,OAAO,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QACrD,CAAC;IACH,CAAC;IAED,+EAA+E;IACvE,WAAW,CAAC,EAAU,EAAE,KAA8B;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,CAAA;QAExB,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;YACnB,OAAM;QACR,CAAC;QAED,KAAK,CAAC,IAAI,GAAG;YACX,GAAG,IAAI;YACP,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;SAC3F,CAAA;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAO;QAC1B,MAAM,MAAM,CAAC,MAAM,CAAC;YAClB,QAAQ,EAAE,GAAG,CAAA;;qCAEkB,OAAO;;OAErC;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAO;QACvB,MAAM,MAAM,CAAC,MAAM,CAAC;YAClB,QAAQ,EAAE,GAAG,CAAA;;;wBAGK,OAAO;;;;;;OAMxB;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;YAClC,KAAK,EAAE,GAAG,CAAA;;;;;;;OAOT;SACF,CAAC,CAAA;QAEF,KAAK,CAAC,QAAQ,CAAC;YACb,IAAI,EAAE,gBAAgB;YACtB,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;SACvE,CAAC,CAAA;IACJ,CAAC;;AAvf2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;6CAAiB;AACjB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;4CAAmB;AAClB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;4CAAmB;AAClB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;+CAAsB;AACpB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;iDAAiB;AAEjB;IAA1B,KAAK,CAAC,UAAU,CAAC;8BAAiB,SAAS;2CAAA;AA3BjC,YAAY;IADxB,aAAa,CAAC,gBAAgB,CAAC;GACnB,YAAY,CA6gBxB","sourcesContent":["import '@operato/data-grist'\nimport '@material/web/icon/icon.js'\nimport '@material/web/button/text-button.js'\nimport '@operato/input/ox-input-select-buttons.js'\n\nimport '../board-list/board-thumb.js'\nimport '../viewparts/play-group-info.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { UPDATE_FAVORITES } from '@things-factory/fav-base/client'\nimport { openPopup } from '@operato/layout'\nimport { navigate, PageView, store } from '@operato/shell'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { pulltorefresh } from '@operato/pull-to-refresh'\nimport { notify } from '../utils/notify-helper.js'\nimport { boardMeta } from '../utils/board-meta.js'\nimport { BoardCardStyles } from '../styles/board-card-styles.js'\n\nimport {\n createPlayGroup,\n deletePlayGroup,\n fetchPlayGroup,\n fetchPlayGroupList,\n updateBoard,\n updatePlayGroup\n} from '../graphql'\n\n/*\n * Same board-card look as board-list-page (ox-grist CARD mode, drag-reorder — see\n * `data-grist`'s `rows.reorderable`, ADR: shared component over a board-only fork).\n * A play group's board set is small and its own array *is* the order, so there is no pagination or\n * server-side sort here - `fetchHandler` always hands back the whole thing.\n */\n@customElement('play-list-page')\nexport class PlayListPage extends localize(i18next)(PageView) {\n static styles = [\n /* The frame owns the page shell; the grist is the content it sizes (ADR-0060 decision 8). */\n WorkSurfacePageStyles,\n ScrollbarStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n /* The card itself - shared with the other catalogs, see styles/board-card-styles.ts. */\n BoardCardStyles,\n css`\n /*\n The play groups are chips, not a tab strip - the same select-buttons the list's own\n facets use, so this page and board-list read as one product. One is always pressed:\n a play list is *of* a group, there is no \"all groups\" view here.\n */\n ox-input-select-buttons {\n flex: 1;\n }\n `\n ]\n\n @property({ type: String }) groupId?: string\n @property({ type: Array }) groups: any[] = []\n @property({ type: Array }) boards: any[] = []\n @property({ type: Array }) favorites: any[] = []\n @property({ type: Object }) gristConfig: any\n\n @query('ox-grist') private grist!: DataGrist\n\n private page?: string\n\n get context() {\n /* The pressed chip already names the group; the title names the screen, as board-list's does. */\n return {\n title: i18next.t('title.play list', { defaultValue: 'Play List' }),\n board_topmenu: true\n }\n }\n\n render() {\n const current = (this.groups || []).find(group => group.id === this.groupId)\n\n return html`\n <ox-grist\n class=\"page-fill\"\n mode=\"CARD\"\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n @reorder=${e => this.onReorder(e.detail)}\n >\n <div slot=\"headroom\">\n <ox-input-select-buttons\n .value=${this.groupId || ''}\n .options=${(this.groups || []).map(group => ({ display: group.name, value: group.id }))}\n @change=${(e: CustomEvent) => {\n const id = e.detail\n /* The URL stays the source of truth - same round trip a deep link takes. */\n if (id && id !== this.groupId) navigate(`${this.page || 'play-list'}/${id}`)\n }}\n ></ox-input-select-buttons>\n ${current\n ? html`\n <md-text-button @click=${() => this.onInfoPlayGroup(current)}>\n <md-icon slot=\"icon\">edit</md-icon>\n ${i18next.t('text.edit play-group', { defaultValue: 'Edit' })}\n </md-text-button>\n `\n : ''}\n <md-text-button @click=${() => this.onInfoPlayGroup(undefined)}>\n <md-icon slot=\"icon\">playlist_add</md-icon>\n ${i18next.t('text.new play-group', { defaultValue: 'New Play Group' })}\n </md-text-button>\n </div>\n </ox-grist>\n\n ${this.groupId\n ? html`\n <button fab title=${i18next.t('label.play', { defaultValue: 'Play' })} @click=${() => navigate(`board-player/${this.groupId}`)}>\n <md-icon>play_arrow</md-icon>${i18next.t('label.play', { defaultValue: 'Play' })}\n </button>\n `\n : ''}\n `\n }\n\n async pageInitialized() {\n this.gristConfig = {\n list: {\n thumbnail: 'thumbnail',\n fields: ['name', 'meta'],\n details: []\n },\n columns: [\n {\n type: 'image',\n name: 'thumbnail',\n record: {\n editable: false,\n align: 'center',\n renderEmpty: true,\n /* board-thumb.ts owns the picture and draft badge; info/favorite are gutter columns\n * below - see board-list-page.ts's identical setup and board-thumb.ts's own comment. */\n renderer: (value, column, record) => html`<board-thumb .board=${record}></board-thumb>`\n }\n },\n { type: 'string', name: 'name', record: { editable: false } },\n { type: 'string', name: 'meta', record: { editable: false } },\n {\n type: 'gutter',\n gutterName: 'button',\n name: 'edit',\n /* Edit first, the star last - same order as board-list-page.ts. */\n icon: 'edit',\n quiet: true,\n title: i18next.t('label.edit', { defaultValue: 'Edit' }),\n handlers: {\n click: (_columns, _data, _column, record) => this.onInfoBoard(record)\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n name: 'favorite',\n icon: (record?: any) => (record?.favorited ? 'star' : 'star_border'),\n quiet: (record?: any) => !record?.favorited,\n title: (record?: any) =>\n i18next.t(record?.favorited ? 'label.unfavorite' : 'label.favorite', {\n defaultValue: record?.favorited ? 'Remove from favorites' : 'Add to favorites'\n }),\n handlers: {\n click: (_columns, _data, _column, record) => this.toggleFavorite(record)\n }\n }\n ],\n rows: {\n selectable: false,\n appendable: false,\n reorderable: true,\n handlers: {\n click: (_columns, _data, _column, record) => navigate(`board-viewer/${record.id}`)\n }\n },\n sorters: []\n }\n\n this.refresh()\n }\n\n async fetchHandler(_option: FetchOption) {\n const favorites = this.favorites || []\n const records = (this.boards || []).map(board => ({\n ...board,\n favorited: favorites.includes(board.id),\n meta: boardMeta(board)\n }))\n\n return { total: records.length, records }\n }\n\n async refresh() {\n this.groups = (await fetchPlayGroupList()).playGroups.items\n\n this.groups && (await this.refreshBoards())\n }\n\n async refreshBoards() {\n if (!this.groups) {\n await this.refresh()\n return\n }\n\n if (!this.groupId) {\n const groupId = this.groups && this.groups[0] && this.groups[0].id\n\n /*\n * Build the address from the page name, not by appending to window.location: re-entering\n * this page from the rail while a play-list/<id> URL is still current appended a second\n * id (play-list/<id>/<id>), the route stopped matching and groupId came back empty - no chip\n * pressed, no Edit button (seen live 2026-09-23).\n */\n if (groupId) {\n navigate(`${this.page || 'play-list'}/${groupId}`, true)\n }\n return\n }\n\n if (this.groupId) {\n const playGroup = (await fetchPlayGroup(this.groupId)).playGroup\n this.boards = playGroup ? playGroup.boards : []\n } else {\n this.boards = []\n }\n\n this.updateContext()\n this.grist?.fetch()\n\n if (this.grist) {\n this.grist.style.transition = ''\n this.grist.style.transform = `translate3d(0, 0, 0)`\n }\n }\n\n async pageUpdated(changes, lifecycle) {\n if (this.active) {\n this.page = lifecycle.page\n /*\n * On a full page load the router can deliver the bare /play-list lifecycle *after* this\n * page has already redirected itself to /play-list/<first group> - the id would be wiped\n * while the URL still shows it (no chip pressed, no Edit button; seen live 2026-09-23).\n * The address bar is the source of truth, so read the id back from it in that case.\n */\n this.groupId = lifecycle.resourceId || this.groupIdFromLocation()\n\n await this.updateComplete\n\n this.refreshBoards()\n }\n }\n\n private groupIdFromLocation(): string {\n const segments = location.pathname.split('/').filter(Boolean)\n const at = segments.lastIndexOf(this.page || 'play-list')\n\n return at >= 0 ? segments[at + 1] || '' : ''\n }\n\n private _unsubscribe?: () => void\n\n connectedCallback() {\n super.connectedCallback()\n\n this._applyState()\n\n this._unsubscribe = store.subscribe(() => this._applyState())\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n this._unsubscribe?.()\n }\n\n private _applyState() {\n const __state__ = store.getState() as any\n const favorites = __state__.favorite.favorites\n\n /*\n * `store.subscribe` fires on every dispatch anywhere in the app, not just favorite changes - an\n * unconditional fetch() here risks a loop if fetch() completing itself dispatches through this\n * same store (board-list-page.ts hit exactly this).\n */\n const changed = JSON.stringify(favorites) !== JSON.stringify(this.favorites)\n this.favorites = favorites\n\n if (changed) {\n this.grist?.fetch()\n }\n }\n\n firstUpdated() {\n /* Groups are chips now, one tap each - the swipe-between-routes gesture the tab strip needed\n * no longer has a job here. */\n pulltorefresh({\n container: this.shadowRoot,\n scrollable: this.grist,\n refresh: () => {\n return this.refresh()\n }\n })\n }\n\n async onInfoBoard(board) {\n openPopup(\n html`\n <board-info\n .board=${board}\n .groupId=${this.groupId}\n @update-board=${e => this.onUpdateBoard(e.detail)}\n @delete-board=${e => this.onDeleteBoard(e.detail)}\n @join-playgroup=${e => this.onJoinPlayGroup(e.detail)}\n @leave-playgroup=${e => this.onLeavePlayGroup(e.detail)}\n ></board-info>\n `,\n { backdrop: true, size: 'medium', closable: true, title: board.name }\n )\n }\n\n async onInfoPlayGroup(group) {\n openPopup(\n html`\n <play-group-info\n .playGroup=${group}\n @update-play-group=${e => this.onUpdatePlayGroup(e.detail)}\n @delete-play-group=${e => this.onDeletePlayGroup(e.detail)}\n @create-play-group=${e => this.onCreatePlayGroup(e.detail)}\n ></play-group-info>\n `,\n {\n backdrop: true,\n size: 'small',\n closable: true,\n title: group?.name || i18next.t('text.new play-group', { defaultValue: 'New Play Group' })\n }\n )\n }\n\n async onCreatePlayGroup(playGroup) {\n try {\n await createPlayGroup(playGroup)\n notify('info', i18next.t('text.play-group created', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onUpdatePlayGroup(playGroup) {\n try {\n await updatePlayGroup(playGroup)\n notify('info', i18next.t('text.play-group updated', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onDeletePlayGroup(playGroup) {\n try {\n await deletePlayGroup(playGroup.id)\n notify('info', i18next.t('text.play-group deleted', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onUpdateBoard(board) {\n try {\n await updateBoard(board)\n notify('info', i18next.t('text.board updated', { board: board.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refreshBoards()\n }\n\n async onDeleteBoard(board) {\n const playGroup = this.groups && this.groups.find(group => group.id === this.groupId)\n await this.onLeavePlayGroup({ board, playGroup })\n }\n\n async onJoinPlayGroup({ board, playGroup }) {\n try {\n await client.mutate({\n mutation: gql`\n mutation JoinPlayGroup($id: String!, $boardIds: [String!]!) {\n joinPlayGroup(id: $id, boardIds: $boardIds) {\n id\n }\n }\n `,\n variables: {\n id: playGroup.id,\n boardIds: [board.id]\n }\n })\n\n notify('info', i18next.t('text.joined into play-group', { board: board.name, playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onLeavePlayGroup({ board, playGroup }) {\n try {\n await client.mutate({\n mutation: gql`\n mutation ($id: String!, $boardIds: [String!]!) {\n leavePlayGroup(id: $id, boardIds: $boardIds) {\n id\n }\n }\n `,\n variables: {\n id: playGroup.id,\n boardIds: [board.id]\n }\n })\n\n notify('info', i18next.t('text.leaved from play-group', { board: board.name, playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n }\n\n this.refresh()\n }\n\n async onReorder({ ids, movedId }: { ids: string[]; movedId: string }) {\n const groupId = this.groupId\n\n try {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $boardIds: [String!]!) {\n reorderPlayGroup(id: $id, boardIds: $boardIds) {\n id\n name\n }\n }\n `,\n variables: {\n id: groupId,\n boardIds: ids\n }\n })\n\n const playGroup = response.data.reorderPlayGroup\n\n notify('info', i18next.t('text.reorder play-group', { playGroup: playGroup.name }))\n } catch (ex) {\n notify('error', ex, ex)\n /* 실패 시에만 서버 데이터로 복원 */\n this.refresh()\n }\n }\n\n async toggleFavorite(board) {\n const wasFavorite = (this.favorites || []).includes(board.id)\n\n /*\n * The star answers the click at once; the server round trip only confirms it. Before, nothing\n * moved until the mutation, the favorites re-query, the store dispatch and a full refetch had\n * all come back - a click with no reaction reads as a click that did not land.\n *\n * `favorites` is set locally too, so the store update that follows carries the same list and\n * `_applyState` does not trigger the refetch that would repaint every card.\n */\n this.favorites = wasFavorite\n ? (this.favorites || []).filter(id => id !== board.id)\n : [...(this.favorites || []), board.id]\n this.patchRecord(board.id, { favorited: !wasFavorite })\n\n try {\n if (wasFavorite) {\n await this.removeFavorite(board.id)\n } else {\n await this.addFavorite(board.id)\n }\n } catch (ex) {\n /* Put it back the way it was and say why. */\n this.favorites = wasFavorite\n ? [...(this.favorites || []), board.id]\n : (this.favorites || []).filter(id => id !== board.id)\n this.patchRecord(board.id, { favorited: wasFavorite })\n notify('error', (ex as any)?.message || String(ex))\n }\n }\n\n /** Replaces one record in the grist in place, so only that card re-renders. */\n private patchRecord(id: string, patch: Record<string, unknown>) {\n const grist = this.grist\n const data = grist?.data\n\n if (!data?.records) {\n return\n }\n\n grist.data = {\n ...data,\n records: data.records.map(record => (record.id === id ? { ...record, ...patch } : record))\n }\n }\n\n async removeFavorite(boardId) {\n await client.mutate({\n mutation: gql`\n mutation {\n deleteFavorite(routing: \"${boardId}\")\n }\n `\n })\n\n this.refreshFavorites()\n }\n\n async addFavorite(boardId) {\n await client.mutate({\n mutation: gql`\n mutation {\n createFavorite(favorite: {\n routing: \"${boardId}\"\n }) {\n id\n routing\n }\n }\n `\n })\n\n this.refreshFavorites()\n }\n\n async refreshFavorites() {\n const response = await client.query({\n query: gql`\n query {\n myFavorites {\n id\n routing\n }\n }\n `\n })\n\n store.dispatch({\n type: UPDATE_FAVORITES,\n favorites: response.data.myFavorites.map(favorite => favorite.routing)\n })\n }\n}\n"]}
|
package/dist-client/route.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function route(page: string): "board-viewer" | "board-
|
|
1
|
+
export default function route(page: string): "board-viewer" | "board-modeller" | "board-create" | "play-list" | "board-viewer-by-name" | "board-player" | "board-player-by-name" | "board-list" | "attachment-list" | "font-list" | "printable-board-viewer" | "theme-list" | "board-template-list" | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import '@material/web/radio/radio.js';
|
|
2
|
+
import '@operato/i18n/ox-i18n.js';
|
|
3
|
+
import '@things-factory/setting-base';
|
|
4
|
+
import { LitElement } from 'lit';
|
|
5
|
+
export type ModellerToolbarMode = 'contextual' | 'docked' | 'toolbar';
|
|
6
|
+
export declare const BOARD_MODELLER_SETTING_KEY = "board-modeller";
|
|
7
|
+
/** Where the modeller keeps its editing tools: next to the selection (default) or in the top bar. */
|
|
8
|
+
export declare function getModellerToolbarMode(): Promise<ModellerToolbarMode>;
|
|
9
|
+
declare const BoardModellerSettingLet_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
10
|
+
/**
|
|
11
|
+
* The setting behind the modeller's two toolbar layouts. Both are the same verbs; this only decides
|
|
12
|
+
* whether they float next to what is selected or sit in one fixed row across the top.
|
|
13
|
+
*/
|
|
14
|
+
export declare class BoardModellerSettingLet extends BoardModellerSettingLet_base {
|
|
15
|
+
static styles: import("lit").CSSResult[];
|
|
16
|
+
private mode;
|
|
17
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
18
|
+
firstUpdated(): Promise<void>;
|
|
19
|
+
private onChange;
|
|
20
|
+
}
|
|
21
|
+
export {};
|