@things-factory/gallery 10.1.248 → 10.1.249

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist-client/bootstrap.d.ts +2 -0
  2. package/dist-client/bootstrap.js +26 -0
  3. package/dist-client/bootstrap.js.map +1 -0
  4. package/dist-client/components/gallery-forms.d.ts +31 -0
  5. package/dist-client/components/gallery-forms.js +223 -0
  6. package/dist-client/components/gallery-forms.js.map +1 -0
  7. package/dist-client/components/gallery-saver-setting-let.d.ts +11 -0
  8. package/dist-client/components/gallery-saver-setting-let.js +81 -0
  9. package/dist-client/components/gallery-saver-setting-let.js.map +1 -0
  10. package/dist-client/components/gallery-show.d.ts +46 -0
  11. package/dist-client/components/gallery-show.js +316 -0
  12. package/dist-client/components/gallery-show.js.map +1 -0
  13. package/dist-client/components/gallery-uploader.d.ts +57 -0
  14. package/dist-client/components/gallery-uploader.js +624 -0
  15. package/dist-client/components/gallery-uploader.js.map +1 -0
  16. package/dist-client/components/gallery-viewer.d.ts +30 -0
  17. package/dist-client/components/gallery-viewer.js +429 -0
  18. package/dist-client/components/gallery-viewer.js.map +1 -0
  19. package/dist-client/index.d.ts +1 -0
  20. package/dist-client/index.js +2 -0
  21. package/dist-client/index.js.map +1 -0
  22. package/dist-client/pages/gallery-page.d.ts +54 -0
  23. package/dist-client/pages/gallery-page.js +590 -0
  24. package/dist-client/pages/gallery-page.js.map +1 -0
  25. package/dist-client/route.d.ts +1 -0
  26. package/dist-client/route.js +9 -0
  27. package/dist-client/route.js.map +1 -0
  28. package/dist-client/tsconfig.tsbuildinfo +1 -0
  29. package/dist-client/utils/gallery-api.d.ts +99 -0
  30. package/dist-client/utils/gallery-api.js +46 -0
  31. package/dist-client/utils/gallery-api.js.map +1 -0
  32. package/dist-client/utils/gallery-badge.d.ts +4 -0
  33. package/dist-client/utils/gallery-badge.js +45 -0
  34. package/dist-client/utils/gallery-badge.js.map +1 -0
  35. package/dist-client/utils/gallery-saver.d.ts +6 -0
  36. package/dist-client/utils/gallery-saver.js +69 -0
  37. package/dist-client/utils/gallery-saver.js.map +1 -0
  38. package/dist-client/utils/gallery-words.d.ts +7 -0
  39. package/dist-client/utils/gallery-words.js +20 -0
  40. package/dist-client/utils/gallery-words.js.map +1 -0
  41. package/dist-client/utils/photo-prep.d.ts +10 -0
  42. package/dist-client/utils/photo-prep.js +102 -0
  43. package/dist-client/utils/photo-prep.js.map +1 -0
  44. package/dist-server/attachment-reader.d.ts +1 -0
  45. package/dist-server/attachment-reader.js +13 -0
  46. package/dist-server/attachment-reader.js.map +1 -0
  47. package/dist-server/index.d.ts +1 -0
  48. package/dist-server/index.js +11 -0
  49. package/dist-server/index.js.map +1 -0
  50. package/dist-server/role-tasks.d.ts +2 -0
  51. package/dist-server/role-tasks.js +15 -0
  52. package/dist-server/role-tasks.js.map +1 -0
  53. package/dist-server/service/gallery/gallery-resolver.d.ts +29 -0
  54. package/dist-server/service/gallery/gallery-resolver.js +613 -0
  55. package/dist-server/service/gallery/gallery-resolver.js.map +1 -0
  56. package/dist-server/service/gallery/gallery-rules.d.ts +90 -0
  57. package/dist-server/service/gallery/gallery-rules.js +182 -0
  58. package/dist-server/service/gallery/gallery-rules.js.map +1 -0
  59. package/dist-server/service/gallery/gallery-service.d.ts +37 -0
  60. package/dist-server/service/gallery/gallery-service.js +234 -0
  61. package/dist-server/service/gallery/gallery-service.js.map +1 -0
  62. package/dist-server/service/gallery/gallery-types.d.ts +65 -0
  63. package/dist-server/service/gallery/gallery-types.js +239 -0
  64. package/dist-server/service/gallery/gallery-types.js.map +1 -0
  65. package/dist-server/service/gallery/gallery.d.ts +84 -0
  66. package/dist-server/service/gallery/gallery.js +335 -0
  67. package/dist-server/service/gallery/gallery.js.map +1 -0
  68. package/dist-server/service/gallery/index.d.ts +4 -0
  69. package/dist-server/service/gallery/index.js +8 -0
  70. package/dist-server/service/gallery/index.js.map +1 -0
  71. package/dist-server/service/index.d.ts +7 -0
  72. package/dist-server/service/index.js +23 -0
  73. package/dist-server/service/index.js.map +1 -0
  74. package/dist-server/tsconfig.tsbuildinfo +1 -0
  75. package/package.json +2 -2
@@ -0,0 +1,54 @@
1
+ import '@material/web/icon/icon.js';
2
+ import '@operato/input/ox-input-file.js';
3
+ import '../components/gallery-forms.js';
4
+ import '../components/gallery-uploader.js';
5
+ import '../components/gallery-viewer.js';
6
+ import { PageView } from '@operato/shell';
7
+ declare const GalleryPage_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
8
+ /**
9
+ * 갤러리 — the company's photos, its events, everyone's, and one's own (ADR-0165 decisions 2, 6). One page: the tabs are
10
+ * its ways in, and an event, a person or a tag narrows it (`?event=` · `?author=` · `?tag=`; `?post=` opens one post).
11
+ * Posting takes only photos - 「사진 올리기」, and on a phone 「찍기」 opens the camera at once.
12
+ */
13
+ export declare class GalleryPage extends GalleryPage_base {
14
+ static styles: import("lit").CSSResult[];
15
+ private tab;
16
+ private eventId?;
17
+ private authorId?;
18
+ private tag?;
19
+ private posts;
20
+ private total;
21
+ private events;
22
+ private tags;
23
+ private event?;
24
+ private loading;
25
+ private moderator;
26
+ private picker;
27
+ private camera;
28
+ private onChanged;
29
+ get context(): {
30
+ title: string;
31
+ actions: any[];
32
+ };
33
+ render(): import("lit-html").TemplateResult<1>;
34
+ private get narrowed();
35
+ private renderNarrowing;
36
+ private renderPosts;
37
+ private renderEvents;
38
+ connectedCallback(): void;
39
+ disconnectedCallback(): void;
40
+ pageInitialized(): Promise<void>;
41
+ pageUpdated(changes: any, lifecycle: any): Promise<void>;
42
+ private filter;
43
+ private load;
44
+ /** Where a new post goes - the screen it is posted from. */
45
+ private preset;
46
+ private picked;
47
+ private upload;
48
+ private open;
49
+ private openById;
50
+ private replace;
51
+ private makeEvent;
52
+ private renameTag;
53
+ }
54
+ export {};
@@ -0,0 +1,590 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import '@material/web/icon/icon.js';
3
+ import '@operato/input/ox-input-file.js';
4
+ import '../components/gallery-forms.js';
5
+ import '../components/gallery-uploader.js';
6
+ import '../components/gallery-viewer.js';
7
+ import { css, html, nothing } from 'lit';
8
+ import { customElement, query, state } from 'lit/decorators.js';
9
+ import { i18next, localize } from '@operato/i18n';
10
+ import { notify, openPopup } from '@operato/layout';
11
+ import { navigate, PageView } from '@operato/shell';
12
+ import { ScrollbarStyles } from '@operato/styles';
13
+ import { isMobileDevice } from '@operato/utils';
14
+ import { hasPrivilege } from '@things-factory/auth-base/dist-client';
15
+ import { GalleryShow } from '../components/gallery-show.js';
16
+ import { galleryApi } from '../utils/gallery-api.js';
17
+ import { refreshGalleryBadge } from '../utils/gallery-badge.js';
18
+ import { day, days, reasonOf, t } from '../utils/gallery-words.js';
19
+ const TABS = ['company', 'events', 'all', 'mine'];
20
+ const PAGE = 30;
21
+ /**
22
+ * 갤러리 — the company's photos, its events, everyone's, and one's own (ADR-0165 decisions 2, 6). One page: the tabs are
23
+ * its ways in, and an event, a person or a tag narrows it (`?event=` · `?author=` · `?tag=`; `?post=` opens one post).
24
+ * Posting takes only photos - 「사진 올리기」, and on a phone 「찍기」 opens the camera at once.
25
+ */
26
+ let GalleryPage = class GalleryPage extends localize(i18next)(PageView) {
27
+ constructor() {
28
+ super(...arguments);
29
+ this.tab = 'company';
30
+ this.posts = [];
31
+ this.total = 0;
32
+ this.events = [];
33
+ this.tags = [];
34
+ this.loading = false;
35
+ this.moderator = false;
36
+ this.onChanged = () => this.load();
37
+ }
38
+ static { this.styles = [
39
+ ScrollbarStyles,
40
+ css `
41
+ :host {
42
+ display: block;
43
+ overflow: auto;
44
+ padding: var(--spacing-large, 12px) var(--spacing-large, 16px);
45
+ box-sizing: border-box;
46
+ background: var(--md-sys-color-surface);
47
+ color: var(--md-sys-color-on-surface);
48
+ }
49
+ .tabs {
50
+ display: flex;
51
+ gap: var(--spacing-small, 4px);
52
+ overflow-x: auto;
53
+ margin-bottom: var(--spacing-medium, 8px);
54
+ }
55
+ .tabs button {
56
+ flex: none;
57
+ padding: 4px var(--spacing-large, 12px);
58
+ border: 1px solid var(--ui-line-soft, var(--md-sys-color-outline-variant));
59
+ border-radius: 999px;
60
+ background: none;
61
+ color: var(--md-sys-color-on-surface);
62
+ font: inherit;
63
+ font-size: var(--ui-t-body, 14px);
64
+ cursor: pointer;
65
+ }
66
+ .tabs button[aria-selected='true'] {
67
+ border-color: var(--md-sys-color-primary);
68
+ background: var(--md-sys-color-primary-container);
69
+ color: var(--md-sys-color-on-primary-container);
70
+ }
71
+ .narrow {
72
+ display: flex;
73
+ flex-wrap: wrap;
74
+ align-items: baseline;
75
+ gap: var(--spacing-small, 4px) var(--spacing-medium, 8px);
76
+ margin-bottom: var(--spacing-medium, 8px);
77
+ }
78
+ .narrow h2 {
79
+ margin: 0;
80
+ font-size: var(--ui-t-title, 18px);
81
+ }
82
+ .narrow .muted {
83
+ font-size: var(--ui-t-small, 12px);
84
+ }
85
+ .chips {
86
+ display: flex;
87
+ flex-wrap: wrap;
88
+ gap: var(--spacing-small, 4px);
89
+ margin-bottom: var(--spacing-medium, 8px);
90
+ }
91
+ .chip,
92
+ .link {
93
+ display: inline-flex;
94
+ align-items: center;
95
+ gap: 2px;
96
+ padding: 2px var(--spacing-medium, 8px);
97
+ border: 1px solid var(--ui-line-soft, var(--md-sys-color-outline-variant));
98
+ border-radius: 999px;
99
+ background: none;
100
+ color: var(--md-sys-color-on-surface);
101
+ font: inherit;
102
+ font-size: var(--ui-t-small, 12px);
103
+ line-height: 1.6;
104
+ cursor: pointer;
105
+ }
106
+ .chip[aria-pressed='true'] {
107
+ border-color: var(--md-sys-color-primary);
108
+ color: var(--md-sys-color-primary);
109
+ }
110
+ .chip md-icon,
111
+ .link md-icon {
112
+ --md-icon-size: 14px;
113
+ }
114
+ .link {
115
+ border: 0;
116
+ padding: 0;
117
+ color: var(--md-sys-color-primary);
118
+ }
119
+ .muted {
120
+ color: var(--ui-muted, var(--md-sys-color-on-surface-variant));
121
+ }
122
+ .grid {
123
+ display: grid;
124
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
125
+ gap: var(--spacing-medium, 8px);
126
+ }
127
+ .card {
128
+ display: flex;
129
+ flex-direction: column;
130
+ gap: 2px;
131
+ padding: 0;
132
+ border: 0;
133
+ background: none;
134
+ color: inherit;
135
+ font: inherit;
136
+ text-align: start;
137
+ cursor: pointer;
138
+ min-width: 0;
139
+ }
140
+ .picture {
141
+ position: relative;
142
+ width: 100%;
143
+ aspect-ratio: 1;
144
+ border-radius: var(--border-radius, 6px);
145
+ overflow: hidden;
146
+ background: var(--md-sys-color-surface-container-high);
147
+ }
148
+ .picture img {
149
+ width: 100%;
150
+ height: 100%;
151
+ object-fit: cover;
152
+ display: block;
153
+ transition: transform 160ms ease-out;
154
+ }
155
+ .card:hover .picture img {
156
+ transform: scale(1.03);
157
+ }
158
+ .badge {
159
+ position: absolute;
160
+ display: inline-flex;
161
+ align-items: center;
162
+ gap: 2px;
163
+ padding: 0 6px;
164
+ border-radius: 999px;
165
+ background: rgb(0 0 0 / 50%);
166
+ color: #fff;
167
+ font-size: var(--ui-t-small, 12px);
168
+ line-height: 1.6;
169
+ }
170
+ .badge md-icon {
171
+ --md-icon-size: 14px;
172
+ }
173
+ .badge.likes {
174
+ bottom: 4px;
175
+ inset-inline-start: 4px;
176
+ }
177
+ .badge.likes md-icon {
178
+ font-variation-settings: 'FILL' 0;
179
+ }
180
+ .badge.likes[liked] md-icon {
181
+ color: #ff6b6b;
182
+ font-variation-settings: 'FILL' 1;
183
+ }
184
+ .badge.count {
185
+ top: 4px;
186
+ inset-inline-end: 4px;
187
+ }
188
+ .badge.private {
189
+ bottom: 4px;
190
+ inset-inline-end: 4px;
191
+ }
192
+ .badge.hidden {
193
+ top: 4px;
194
+ inset-inline-start: 4px;
195
+ background: var(--md-sys-color-error);
196
+ }
197
+ .under {
198
+ display: flex;
199
+ gap: var(--spacing-small, 4px);
200
+ font-size: var(--ui-t-small, 12px);
201
+ color: var(--ui-muted, var(--md-sys-color-on-surface-variant));
202
+ overflow: hidden;
203
+ white-space: nowrap;
204
+ }
205
+ .under .name {
206
+ overflow: hidden;
207
+ text-overflow: ellipsis;
208
+ }
209
+ .title {
210
+ font-size: var(--ui-t-body, 14px);
211
+ font-weight: 600;
212
+ overflow: hidden;
213
+ text-overflow: ellipsis;
214
+ white-space: nowrap;
215
+ }
216
+ .empty {
217
+ display: flex;
218
+ flex-direction: column;
219
+ align-items: center;
220
+ gap: var(--spacing-medium, 8px);
221
+ padding: 48px var(--spacing-large, 16px);
222
+ color: var(--ui-muted, var(--md-sys-color-on-surface-variant));
223
+ text-align: center;
224
+ }
225
+ .empty md-icon {
226
+ --md-icon-size: 40px;
227
+ }
228
+ .empty button,
229
+ .more {
230
+ padding: 6px var(--spacing-large, 16px);
231
+ border: 1px solid var(--md-sys-color-primary);
232
+ border-radius: 999px;
233
+ background: none;
234
+ color: var(--md-sys-color-primary);
235
+ font: inherit;
236
+ cursor: pointer;
237
+ }
238
+ .more {
239
+ display: block;
240
+ margin: var(--spacing-large, 16px) auto 0;
241
+ }
242
+ ox-input-file {
243
+ display: none;
244
+ }
245
+ @media (max-width: 460px) {
246
+ :host {
247
+ padding: var(--spacing-medium, 8px);
248
+ }
249
+ .grid {
250
+ grid-template-columns: repeat(2, minmax(0, 1fr));
251
+ gap: var(--spacing-small, 4px);
252
+ }
253
+ }
254
+ `
255
+ ]; }
256
+ get context() {
257
+ const actions = [];
258
+ if (this.tag && this.moderator)
259
+ actions.push({ title: t('gallery.button.rename-tag'), icon: 'sell', action: () => this.renameTag() });
260
+ if (this.tab === 'events' && !this.eventId && this.moderator)
261
+ actions.push({ title: t('gallery.button.create-event'), icon: 'event', action: () => this.makeEvent() });
262
+ if (this.tab !== 'events' || this.eventId) {
263
+ if (isMobileDevice())
264
+ actions.push({ title: t('gallery.button.shoot'), icon: 'photo_camera', action: () => this.camera?.pick() });
265
+ if (this.total)
266
+ actions.push({ title: t('gallery.button.slideshow'), icon: 'slideshow', action: () => GalleryShow.open({ filter: this.filter(), playing: true }) });
267
+ actions.push({
268
+ title: t('gallery.button.post'),
269
+ icon: 'add_photo_alternate',
270
+ emphasis: { raised: true },
271
+ action: () => this.picker?.pick()
272
+ });
273
+ }
274
+ return { title: t('gallery.title.page'), actions };
275
+ }
276
+ render() {
277
+ return html `
278
+ <ox-input-file
279
+ id="pick"
280
+ quiet
281
+ outside-trigger
282
+ hide-filelist
283
+ multiple
284
+ accept="image/*"
285
+ @change=${(e) => this.picked(e)}
286
+ ></ox-input-file>
287
+ <ox-input-file
288
+ id="shoot"
289
+ quiet
290
+ outside-trigger
291
+ hide-filelist
292
+ accept="image/*"
293
+ capture="environment"
294
+ @change=${(e) => this.picked(e)}
295
+ ></ox-input-file>
296
+ <div class="tabs" role="tablist">
297
+ ${TABS.map(tab => html `<button role="tab" aria-selected=${String(this.tab === tab && !this.narrowed)} @click=${() => navigate(`gallery-page?tab=${tab}`)}>${t(`gallery.tab.${tab}`)}</button>`)}
298
+ </div>
299
+ ${this.renderNarrowing()} ${this.tab === 'events' && !this.eventId ? this.renderEvents() : this.renderPosts()}
300
+ `;
301
+ }
302
+ get narrowed() {
303
+ return !!(this.eventId || this.tag || this.authorId);
304
+ }
305
+ renderNarrowing() {
306
+ if (this.eventId) {
307
+ const event = this.event;
308
+ return html `<div class="narrow">
309
+ <h2>${event?.name ?? ''}</h2>
310
+ ${event ? html `<span class="muted">${days(event.startAt, event.endAt)}${event.location ? ` · ${event.location}` : ''}</span>` : nothing}
311
+ <button class="link" @click=${() => navigate('gallery-page?tab=events')}>
312
+ <md-icon>arrow_back</md-icon>${t('gallery.tab.events')}
313
+ </button>
314
+ </div>`;
315
+ }
316
+ if (this.authorId) {
317
+ const name = this.posts[0]?.creator?.name ?? '';
318
+ return html `<div class="narrow"><h2>${t('gallery.text.persons-gallery', { name })}</h2></div>`;
319
+ }
320
+ if (this.tag) {
321
+ return html `<div class="narrow">
322
+ <h2>#${this.tag}</h2>
323
+ <button class="link" @click=${() => navigate(`gallery-page?tab=${this.tab}`)}>
324
+ <md-icon>close</md-icon>${t('gallery.button.clear')}
325
+ </button>
326
+ </div>`;
327
+ }
328
+ if (this.tab === 'events' || !this.tags.length)
329
+ return nothing;
330
+ return html `<div class="chips">
331
+ ${this.tags.map(one => html `<button class="chip" @click=${() => navigate(`gallery-page?tab=${this.tab}&tag=${encodeURIComponent(one.tag)}`)}>#${one.tag}</button>`)}
332
+ </div>`;
333
+ }
334
+ renderPosts() {
335
+ if (!this.posts.length) {
336
+ return this.loading
337
+ ? nothing
338
+ : html `<div class="empty">
339
+ <md-icon>photo_library</md-icon>
340
+ <div>
341
+ ${this.eventId ? t('gallery.text.empty-event') : this.tab === 'mine' ? t('gallery.text.empty-mine') : t('gallery.text.empty')}
342
+ </div>
343
+ <button @click=${() => this.picker?.pick()}>${t('gallery.button.post')}</button>
344
+ </div>`;
345
+ }
346
+ return html `<div class="grid">
347
+ ${this.posts.map(post => html `<button class="card" @click=${() => this.open(post)}>
348
+ <div class="picture">
349
+ ${post.photos[0] ? html `<img loading="lazy" src=${post.photos[0].thumbnail || post.photos[0].fullpath} alt=${post.caption ?? ''} />` : nothing}
350
+ ${post.hiddenAt ? html `<span class="badge hidden"><md-icon>visibility_off</md-icon>${t('gallery.text.hidden')}</span>` : nothing}
351
+ ${post.photos.length > 1 ? html `<span class="badge count"><md-icon>photo_library</md-icon>${post.photos.length}</span>` : nothing}
352
+ ${post.space === 'PERSONAL' && !post.shared ? html `<span class="badge private" title=${t('gallery.text.only-me')}><md-icon>lock</md-icon></span>` : nothing}
353
+ ${post.likeCount || post.liked ? html `<span class="badge likes" ?liked=${post.liked}><md-icon>favorite</md-icon>${post.likeCount}</span>` : nothing}
354
+ </div>
355
+ <div class="under">
356
+ <span class="name">${post.creator?.name ?? ''}</span><span>·</span><span>${day(post.takenAt)}</span>
357
+ </div>
358
+ </button>`)}
359
+ </div>
360
+ ${this.posts.length < this.total ? html `<button class="more" ?disabled=${this.loading} @click=${() => this.load(true)}>${t('gallery.button.more')}</button>` : nothing}`;
361
+ }
362
+ renderEvents() {
363
+ if (!this.events.length) {
364
+ return this.loading
365
+ ? nothing
366
+ : html `<div class="empty">
367
+ <md-icon>event</md-icon>
368
+ <div>${t('gallery.text.empty-events')}</div>
369
+ ${this.moderator ? html `<button @click=${() => this.makeEvent()}>${t('gallery.button.create-event')}</button>` : nothing}
370
+ </div>`;
371
+ }
372
+ return html `<div class="grid">
373
+ ${this.events.map(event => html `<button class="card" @click=${() => navigate(`gallery-page?event=${event.id}`)}>
374
+ <div class="picture">
375
+ ${event.cover ? html `<img loading="lazy" src=${event.cover.thumbnail || event.cover.fullpath} alt="" />` : nothing}
376
+ <span class="badge count"><md-icon>photo_library</md-icon>${event.postCount}</span>
377
+ </div>
378
+ <div class="title">${event.name}</div>
379
+ <div class="under">
380
+ <span>${days(event.startAt, event.endAt)}</span
381
+ >${event.location ? html `<span>·</span><span class="name">${event.location}</span>` : nothing}
382
+ </div>
383
+ </button>`)}
384
+ </div>`;
385
+ }
386
+ connectedCallback() {
387
+ super.connectedCallback();
388
+ window.addEventListener('gallery-changed', this.onChanged);
389
+ }
390
+ disconnectedCallback() {
391
+ window.removeEventListener('gallery-changed', this.onChanged);
392
+ super.disconnectedCallback();
393
+ }
394
+ async pageInitialized() {
395
+ hasPrivilege({ category: 'gallery', privilege: 'mutation', domainOwnerGranted: true }).then(moderator => {
396
+ this.moderator = !!moderator;
397
+ this.updateContext();
398
+ });
399
+ }
400
+ async pageUpdated(changes, lifecycle) {
401
+ if (!this.active || !(changes.active || changes.params))
402
+ return;
403
+ const params = lifecycle?.params ?? {};
404
+ this.eventId = params.event || undefined;
405
+ this.tag = params.tag || undefined;
406
+ /* 「me」 is the own gallery - the server knows who asks; the client holds no user id. */
407
+ this.authorId = params.author === 'me' ? undefined : params.author || undefined;
408
+ this.tab = this.eventId ? 'events' : params.author === 'me' ? 'mine' : TABS.includes(params.tab) ? params.tab : 'company';
409
+ this.event = undefined;
410
+ this.posts = [];
411
+ this.updateContext();
412
+ await this.load();
413
+ if (params.post)
414
+ this.openById(params.post);
415
+ galleryApi
416
+ .visit()
417
+ .then(() => refreshGalleryBadge())
418
+ .catch(() => { });
419
+ }
420
+ filter() {
421
+ if (this.eventId)
422
+ return { eventId: this.eventId };
423
+ const filter = {};
424
+ if (this.tag)
425
+ filter.tag = this.tag;
426
+ if (this.authorId)
427
+ filter.authorId = this.authorId;
428
+ else if (this.tab === 'company')
429
+ filter.space = 'COMPANY';
430
+ else if (this.tab === 'mine')
431
+ filter.mine = true;
432
+ return filter;
433
+ }
434
+ async load(more = false) {
435
+ this.loading = true;
436
+ try {
437
+ if (this.tab === 'events' && !this.eventId) {
438
+ this.events = await galleryApi.events();
439
+ return;
440
+ }
441
+ const page = await galleryApi.posts(this.filter(), more ? this.posts.length : 0, PAGE);
442
+ this.posts = more ? [...this.posts, ...page.items] : page.items;
443
+ this.total = page.total;
444
+ /* The slideshow is offered once there is something to show. */
445
+ this.updateContext();
446
+ if (this.eventId && !this.event)
447
+ this.event =
448
+ page.items.find(one => one.event)?.event ?? (await galleryApi.events()).find(one => one.id === this.eventId);
449
+ if (!more && !this.narrowed)
450
+ this.tags = (await galleryApi.tags()).slice(0, 12);
451
+ }
452
+ catch (error) {
453
+ notify({ level: 'error', message: reasonOf(error) });
454
+ }
455
+ finally {
456
+ this.loading = false;
457
+ }
458
+ }
459
+ /** Where a new post goes - the screen it is posted from. */
460
+ preset() {
461
+ if (this.eventId)
462
+ return { space: 'COMPANY', eventId: this.eventId };
463
+ return { space: this.tab === 'mine' ? 'PERSONAL' : 'COMPANY' };
464
+ }
465
+ picked(e) {
466
+ const files = [...(e.detail ?? [])];
467
+ /* The picker's own reset says `change` again, with nothing - that one is let go. */
468
+ if (!files.length)
469
+ return;
470
+ e.target.reset?.();
471
+ this.upload(files);
472
+ }
473
+ upload(files = [], post) {
474
+ const { space, eventId } = this.preset();
475
+ const popup = openPopup(html `<gallery-uploader
476
+ .files=${files}
477
+ .post=${post}
478
+ space=${space}
479
+ .eventId=${eventId ?? null}
480
+ @done=${() => popup.close()}
481
+ ></gallery-uploader>`, { backdrop: true, size: 'large', title: post ? t('gallery.title.edit') : t('gallery.title.post') });
482
+ }
483
+ /* A popup closes by going back in the history: where to go next is taken once it is gone (`result`). */
484
+ async open(post) {
485
+ const popup = openPopup(html `<gallery-viewer
486
+ .post=${post}
487
+ @done=${(e) => popup.close(e.detail)}
488
+ @gallery-liked=${(e) => this.replace(e.detail)}
489
+ ></gallery-viewer>`, { backdrop: true, size: 'large', title: post.event?.name || post.creator?.name || t('gallery.title.page') });
490
+ const next = await popup.result;
491
+ if (next?.edit)
492
+ this.upload([], next.edit);
493
+ else if (next?.go)
494
+ navigate(next.go);
495
+ else if (next?.show)
496
+ GalleryShow.open({ filter: this.filter(), start: next.show });
497
+ }
498
+ async openById(id) {
499
+ try {
500
+ const post = this.posts.find(one => one.id === id) ?? (await galleryApi.post(id));
501
+ if (post)
502
+ this.open(post);
503
+ else
504
+ notify({ level: 'warn', message: t('gallery.text.unknown-post') });
505
+ }
506
+ catch (error) {
507
+ notify({ level: 'error', message: reasonOf(error) });
508
+ }
509
+ }
510
+ replace(post) {
511
+ this.posts = this.posts.map(one => (one.id === post.id ? post : one));
512
+ }
513
+ async makeEvent() {
514
+ const popup = openPopup(html `<gallery-event-form @done=${(e) => popup.close(e.detail)}></gallery-event-form>`, {
515
+ backdrop: true,
516
+ size: 'medium',
517
+ title: t('gallery.button.create-event')
518
+ });
519
+ const made = await popup.result;
520
+ if (made?.id)
521
+ navigate(`gallery-page?event=${made.id}`);
522
+ }
523
+ async renameTag() {
524
+ const popup = openPopup(html `<gallery-tag-form .tag=${this.tag} @done=${(e) => popup.close(e.detail)}></gallery-tag-form>`, {
525
+ backdrop: true,
526
+ size: 'small',
527
+ title: t('gallery.button.rename-tag')
528
+ });
529
+ const to = await popup.result;
530
+ if (to)
531
+ navigate(`gallery-page?tab=${this.tab}&tag=${encodeURIComponent(to)}`);
532
+ }
533
+ };
534
+ __decorate([
535
+ state(),
536
+ __metadata("design:type", String)
537
+ ], GalleryPage.prototype, "tab", void 0);
538
+ __decorate([
539
+ state(),
540
+ __metadata("design:type", String)
541
+ ], GalleryPage.prototype, "eventId", void 0);
542
+ __decorate([
543
+ state(),
544
+ __metadata("design:type", String)
545
+ ], GalleryPage.prototype, "authorId", void 0);
546
+ __decorate([
547
+ state(),
548
+ __metadata("design:type", String)
549
+ ], GalleryPage.prototype, "tag", void 0);
550
+ __decorate([
551
+ state(),
552
+ __metadata("design:type", Array)
553
+ ], GalleryPage.prototype, "posts", void 0);
554
+ __decorate([
555
+ state(),
556
+ __metadata("design:type", Object)
557
+ ], GalleryPage.prototype, "total", void 0);
558
+ __decorate([
559
+ state(),
560
+ __metadata("design:type", Array)
561
+ ], GalleryPage.prototype, "events", void 0);
562
+ __decorate([
563
+ state(),
564
+ __metadata("design:type", Array)
565
+ ], GalleryPage.prototype, "tags", void 0);
566
+ __decorate([
567
+ state(),
568
+ __metadata("design:type", Object)
569
+ ], GalleryPage.prototype, "event", void 0);
570
+ __decorate([
571
+ state(),
572
+ __metadata("design:type", Object)
573
+ ], GalleryPage.prototype, "loading", void 0);
574
+ __decorate([
575
+ state(),
576
+ __metadata("design:type", Object)
577
+ ], GalleryPage.prototype, "moderator", void 0);
578
+ __decorate([
579
+ query('#pick'),
580
+ __metadata("design:type", Object)
581
+ ], GalleryPage.prototype, "picker", void 0);
582
+ __decorate([
583
+ query('#shoot'),
584
+ __metadata("design:type", Object)
585
+ ], GalleryPage.prototype, "camera", void 0);
586
+ GalleryPage = __decorate([
587
+ customElement('gallery-page')
588
+ ], GalleryPage);
589
+ export { GalleryPage };
590
+ //# sourceMappingURL=gallery-page.js.map