@things-factory/announcement 10.1.265 → 10.1.269

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.
@@ -2,8 +2,10 @@
2
2
  * Keeps the person up with announcements while the application is open (ADR-0163 decision 5): the popups due at sign-in,
3
3
  * a new one popping up the moment it is published to them, and the menu badge.
4
4
  *
5
- * The notice of an announcement reaches the screen through notification's subscription; the announcements themselves
6
- * are asked of the server - a screen that was closed when one went out still finds it here.
5
+ * The notice of a new one reaches the screen through notification's subscription and pops it up. The badge and an open
6
+ * list ask again whenever an announcement addressed to the person changes - it goes out, is read in another window,
7
+ * withdrawn or its period ends (shell's myChange, kind `announcement`). The announcements themselves are asked of the
8
+ * server - a screen that was closed when one went out still finds it here.
7
9
  */
8
10
  import './components/announcement-popup.js'
9
11
 
@@ -13,7 +15,7 @@ import { html } from 'lit'
13
15
  import { subscribe } from '@operato/graphql'
14
16
  import { openPopup } from '@operato/layout'
15
17
 
16
- import { announcementApi, type AnnouncementItem } from './utils/announcement-api.js'
18
+ import { announcementApi, announcementsChanged, type AnnouncementItem } from './utils/announcement-api.js'
17
19
  import { refreshAnnouncementBadge } from './utils/announcement-badge.js'
18
20
  import { t } from './utils/announcement-words.js'
19
21
 
@@ -40,7 +42,7 @@ let popup: { close: () => void; closed: boolean } | undefined
40
42
 
41
43
  /* A reading changed on a screen or in the popup - the badge counts again. */
42
44
  window.addEventListener('announcements-changed', () => refreshAnnouncementBadge())
43
- let subscription: { unsubscribe(): void } | undefined
45
+ let subscriptions: { unsubscribe(): void }[] = []
44
46
  let watching = false
45
47
 
46
48
  /** Opens the popups due now that this session has not closed - one window at a time. */
@@ -74,23 +76,41 @@ export async function startAnnouncementWatch(): Promise<void> {
74
76
  refreshAnnouncementBadge()
75
77
  showDuePopups()
76
78
  try {
77
- subscription = await subscribe(
78
- {
79
- query: gql`
80
- subscription {
81
- notification(subjects: ["info"]) {
82
- type
79
+ subscriptions.push(
80
+ await subscribe(
81
+ {
82
+ query: gql`
83
+ subscription {
84
+ myChange(kinds: ["announcement"]) {
85
+ id
86
+ }
83
87
  }
88
+ `
89
+ },
90
+ {
91
+ next({ data }: any) {
92
+ if (data?.myChange) announcementsChanged()
84
93
  }
85
- `
86
- },
87
- {
88
- next({ data }: any) {
89
- if (data?.notification?.type !== 'announcement') return
90
- refreshAnnouncementBadge()
91
- showDuePopups()
92
94
  }
93
- }
95
+ )
96
+ )
97
+ subscriptions.push(
98
+ await subscribe(
99
+ {
100
+ query: gql`
101
+ subscription {
102
+ notification(subjects: ["info"]) {
103
+ type
104
+ }
105
+ }
106
+ `
107
+ },
108
+ {
109
+ next({ data }: any) {
110
+ if (data?.notification?.type === 'announcement') showDuePopups()
111
+ }
112
+ }
113
+ )
94
114
  )
95
115
  } catch {
96
116
  /* without the live line the badge and popups still come at the next sign-in */
@@ -98,8 +118,8 @@ export async function startAnnouncementWatch(): Promise<void> {
98
118
  }
99
119
 
100
120
  export function stopAnnouncementWatch(): void {
101
- subscription?.unsubscribe()
102
- subscription = undefined
121
+ for (const one of subscriptions) one.unsubscribe()
122
+ subscriptions = []
103
123
  popup?.close()
104
124
  popup = undefined
105
125
  watching = false
@@ -1,3 +1,4 @@
1
+ import '@operato/input/ox-input-date.js'
1
2
  import '@material/web/icon/icon.js'
2
3
  import '@operato/input/ox-input-file.js'
3
4
  import '@operato/list-state/ox-page-state.js'
@@ -396,8 +397,7 @@ export class AnnouncementEditor extends localize(i18next)(PageView) {
396
397
  ${form.requiresAcknowledgement
397
398
  ? html`<label
398
399
  >${t('announcement.field.acknowledge-by')}
399
- <input type="date" .value=${form.acknowledgeBy} ?disabled=${!editable} @input=${(e: any) => set({ acknowledgeBy: e.target.value })}
400
- /></label>`
400
+ <ox-input-date type="date" .value=${form.acknowledgeBy} ?disabled=${!editable} @change=${(e: any) => set({ acknowledgeBy: e.target.value })}></ox-input-date></label>`
401
401
  : nothing}
402
402
  <label class="check wide"><input type="checkbox" .checked=${form.popup} ?disabled=${!editable} @change=${(e: any) => set({ popup: e.target.checked })} />${t('announcement.text.popup-label')}</label>
403
403
  <label class="check wide"
@@ -427,7 +427,7 @@ export class AnnouncementEditor extends localize(i18next)(PageView) {
427
427
  </li>`
428
428
  )}
429
429
  </ul>
430
- ${editable ? html`<ox-input-file quiet hide-filelist multiple icon="attach_file" .progress=${this.progress} @change=${(e: CustomEvent) => this.pick(e)}></ox-input-file>` : nothing}
430
+ ${editable ? html`<ox-input-file quiet hide-filelist multiple icon="attach_file" .dropTarget=${this} .progress=${this.progress} @change=${(e: CustomEvent) => this.pick(e)}></ox-input-file>` : nothing}
431
431
  </section>
432
432
 
433
433
  <section class="page-section">
@@ -2,15 +2,17 @@
2
2
  * Keeps the person up with announcements while the application is open (ADR-0163 decision 5): the popups due at sign-in,
3
3
  * a new one popping up the moment it is published to them, and the menu badge.
4
4
  *
5
- * The notice of an announcement reaches the screen through notification's subscription; the announcements themselves
6
- * are asked of the server - a screen that was closed when one went out still finds it here.
5
+ * The notice of a new one reaches the screen through notification's subscription and pops it up. The badge and an open
6
+ * list ask again whenever an announcement addressed to the person changes - it goes out, is read in another window,
7
+ * withdrawn or its period ends (shell's myChange, kind `announcement`). The announcements themselves are asked of the
8
+ * server - a screen that was closed when one went out still finds it here.
7
9
  */
8
10
  import './components/announcement-popup.js';
9
11
  import gql from 'graphql-tag';
10
12
  import { html } from 'lit';
11
13
  import { subscribe } from '@operato/graphql';
12
14
  import { openPopup } from '@operato/layout';
13
- import { announcementApi } from './utils/announcement-api.js';
15
+ import { announcementApi, announcementsChanged } from './utils/announcement-api.js';
14
16
  import { refreshAnnouncementBadge } from './utils/announcement-badge.js';
15
17
  import { t } from './utils/announcement-words.js';
16
18
  /* Closed in this browser session - asked again at the next sign-in (one still to be acknowledged comes back then). */
@@ -34,7 +36,7 @@ function rememberClosed(ids) {
34
36
  let popup;
35
37
  /* A reading changed on a screen or in the popup - the badge counts again. */
36
38
  window.addEventListener('announcements-changed', () => refreshAnnouncementBadge());
37
- let subscription;
39
+ let subscriptions = [];
38
40
  let watching = false;
39
41
  /** Opens the popups due now that this session has not closed - one window at a time. */
40
42
  export async function showDuePopups() {
@@ -70,30 +72,43 @@ export async function startAnnouncementWatch() {
70
72
  refreshAnnouncementBadge();
71
73
  showDuePopups();
72
74
  try {
73
- subscription = await subscribe({
75
+ subscriptions.push(await subscribe({
74
76
  query: gql `
75
- subscription {
76
- notification(subjects: ["info"]) {
77
- type
77
+ subscription {
78
+ myChange(kinds: ["announcement"]) {
79
+ id
80
+ }
78
81
  }
79
- }
80
- `
82
+ `
81
83
  }, {
82
84
  next({ data }) {
83
- if (data?.notification?.type !== 'announcement')
84
- return;
85
- refreshAnnouncementBadge();
86
- showDuePopups();
85
+ if (data?.myChange)
86
+ announcementsChanged();
87
87
  }
88
- });
88
+ }));
89
+ subscriptions.push(await subscribe({
90
+ query: gql `
91
+ subscription {
92
+ notification(subjects: ["info"]) {
93
+ type
94
+ }
95
+ }
96
+ `
97
+ }, {
98
+ next({ data }) {
99
+ if (data?.notification?.type === 'announcement')
100
+ showDuePopups();
101
+ }
102
+ }));
89
103
  }
90
104
  catch {
91
105
  /* without the live line the badge and popups still come at the next sign-in */
92
106
  }
93
107
  }
94
108
  export function stopAnnouncementWatch() {
95
- subscription?.unsubscribe();
96
- subscription = undefined;
109
+ for (const one of subscriptions)
110
+ one.unsubscribe();
111
+ subscriptions = [];
97
112
  popup?.close();
98
113
  popup = undefined;
99
114
  watching = false;
@@ -1 +1 @@
1
- {"version":3,"file":"announcement-watch.js","sourceRoot":"","sources":["../client/announcement-watch.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Keeps the person up with announcements while the application is open (ADR-0163 decision 5): the popups due at sign-in,\n * a new one popping up the moment it is published to them, and the menu badge.\n *\n * The notice of an announcement reaches the screen through notification's subscription; the announcements themselves\n * are asked of the server - a screen that was closed when one went out still finds it here.\n */\nimport './components/announcement-popup.js'\n\nimport gql from 'graphql-tag'\nimport { html } from 'lit'\n\nimport { subscribe } from '@operato/graphql'\nimport { openPopup } from '@operato/layout'\n\nimport { announcementApi, type AnnouncementItem } from './utils/announcement-api.js'\nimport { refreshAnnouncementBadge } from './utils/announcement-badge.js'\nimport { t } from './utils/announcement-words.js'\n\n/* Closed in this browser session - asked again at the next sign-in (one still to be acknowledged comes back then). */\nconst CLOSED_KEY = 'announcement.popups-closed'\n\nfunction closedInSession(): Set<string> {\n try {\n return new Set(JSON.parse(sessionStorage.getItem(CLOSED_KEY) || '[]'))\n } catch {\n return new Set()\n }\n}\n\nfunction rememberClosed(ids: string[]) {\n try {\n sessionStorage.setItem(CLOSED_KEY, JSON.stringify([...new Set([...closedInSession(), ...ids])]))\n } catch {\n /* a browser that keeps nothing shows them again - no harm */\n }\n}\n\nlet popup: { close: () => void; closed: boolean } | undefined\n\n/* A reading changed on a screen or in the popup - the badge counts again. */\nwindow.addEventListener('announcements-changed', () => refreshAnnouncementBadge())\nlet subscription: { unsubscribe(): void } | undefined\nlet watching = false\n\n/** Opens the popups due now that this session has not closed - one window at a time. */\nexport async function showDuePopups(): Promise<void> {\n if (popup && !popup.closed) return\n let due: AnnouncementItem[]\n try {\n due = await announcementApi.popups()\n } catch {\n return\n }\n const closed = closedInSession()\n const items = due.filter(one => !closed.has(one.id))\n if (!items.length) return\n const handle: any = openPopup(html`<announcement-popup .items=${items} @done=${() => handle.close()}></announcement-popup>`, {\n backdrop: true,\n size: 'medium',\n title: t('announcement.title.popup')\n })\n popup = handle\n handle.result?.then?.(() => {\n rememberClosed(items.map(one => one.id))\n refreshAnnouncementBadge()\n })\n}\n\n/** Starts once the person is known. */\nexport async function startAnnouncementWatch(): Promise<void> {\n if (watching) return\n watching = true\n refreshAnnouncementBadge()\n showDuePopups()\n try {\n subscription = await subscribe(\n {\n query: gql`\n subscription {\n notification(subjects: [\"info\"]) {\n type\n }\n }\n `\n },\n {\n next({ data }: any) {\n if (data?.notification?.type !== 'announcement') return\n refreshAnnouncementBadge()\n showDuePopups()\n }\n }\n )\n } catch {\n /* without the live line the badge and popups still come at the next sign-in */\n }\n}\n\nexport function stopAnnouncementWatch(): void {\n subscription?.unsubscribe()\n subscription = undefined\n popup?.close()\n popup = undefined\n watching = false\n try {\n sessionStorage.removeItem(CLOSED_KEY)\n } catch {}\n}\n"]}
1
+ {"version":3,"file":"announcement-watch.js","sourceRoot":"","sources":["../client/announcement-watch.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Keeps the person up with announcements while the application is open (ADR-0163 decision 5): the popups due at sign-in,\n * a new one popping up the moment it is published to them, and the menu badge.\n *\n * The notice of a new one reaches the screen through notification's subscription and pops it up. The badge and an open\n * list ask again whenever an announcement addressed to the person changes - it goes out, is read in another window,\n * withdrawn or its period ends (shell's myChange, kind `announcement`). The announcements themselves are asked of the\n * server - a screen that was closed when one went out still finds it here.\n */\nimport './components/announcement-popup.js'\n\nimport gql from 'graphql-tag'\nimport { html } from 'lit'\n\nimport { subscribe } from '@operato/graphql'\nimport { openPopup } from '@operato/layout'\n\nimport { announcementApi, announcementsChanged, type AnnouncementItem } from './utils/announcement-api.js'\nimport { refreshAnnouncementBadge } from './utils/announcement-badge.js'\nimport { t } from './utils/announcement-words.js'\n\n/* Closed in this browser session - asked again at the next sign-in (one still to be acknowledged comes back then). */\nconst CLOSED_KEY = 'announcement.popups-closed'\n\nfunction closedInSession(): Set<string> {\n try {\n return new Set(JSON.parse(sessionStorage.getItem(CLOSED_KEY) || '[]'))\n } catch {\n return new Set()\n }\n}\n\nfunction rememberClosed(ids: string[]) {\n try {\n sessionStorage.setItem(CLOSED_KEY, JSON.stringify([...new Set([...closedInSession(), ...ids])]))\n } catch {\n /* a browser that keeps nothing shows them again - no harm */\n }\n}\n\nlet popup: { close: () => void; closed: boolean } | undefined\n\n/* A reading changed on a screen or in the popup - the badge counts again. */\nwindow.addEventListener('announcements-changed', () => refreshAnnouncementBadge())\nlet subscriptions: { unsubscribe(): void }[] = []\nlet watching = false\n\n/** Opens the popups due now that this session has not closed - one window at a time. */\nexport async function showDuePopups(): Promise<void> {\n if (popup && !popup.closed) return\n let due: AnnouncementItem[]\n try {\n due = await announcementApi.popups()\n } catch {\n return\n }\n const closed = closedInSession()\n const items = due.filter(one => !closed.has(one.id))\n if (!items.length) return\n const handle: any = openPopup(html`<announcement-popup .items=${items} @done=${() => handle.close()}></announcement-popup>`, {\n backdrop: true,\n size: 'medium',\n title: t('announcement.title.popup')\n })\n popup = handle\n handle.result?.then?.(() => {\n rememberClosed(items.map(one => one.id))\n refreshAnnouncementBadge()\n })\n}\n\n/** Starts once the person is known. */\nexport async function startAnnouncementWatch(): Promise<void> {\n if (watching) return\n watching = true\n refreshAnnouncementBadge()\n showDuePopups()\n try {\n subscriptions.push(\n await subscribe(\n {\n query: gql`\n subscription {\n myChange(kinds: [\"announcement\"]) {\n id\n }\n }\n `\n },\n {\n next({ data }: any) {\n if (data?.myChange) announcementsChanged()\n }\n }\n )\n )\n subscriptions.push(\n await subscribe(\n {\n query: gql`\n subscription {\n notification(subjects: [\"info\"]) {\n type\n }\n }\n `\n },\n {\n next({ data }: any) {\n if (data?.notification?.type === 'announcement') showDuePopups()\n }\n }\n )\n )\n } catch {\n /* without the live line the badge and popups still come at the next sign-in */\n }\n}\n\nexport function stopAnnouncementWatch(): void {\n for (const one of subscriptions) one.unsubscribe()\n subscriptions = []\n popup?.close()\n popup = undefined\n watching = false\n try {\n sessionStorage.removeItem(CLOSED_KEY)\n } catch {}\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import '@operato/input/ox-input-date.js';
1
2
  import '@material/web/icon/icon.js';
2
3
  import '@operato/input/ox-input-file.js';
3
4
  import '@operato/list-state/ox-page-state.js';
@@ -1,4 +1,5 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
+ import '@operato/input/ox-input-date.js';
2
3
  import '@material/web/icon/icon.js';
3
4
  import '@operato/input/ox-input-file.js';
4
5
  import '@operato/list-state/ox-page-state.js';
@@ -349,8 +350,7 @@ let AnnouncementEditor = class AnnouncementEditor extends localize(i18next)(Page
349
350
  ${form.requiresAcknowledgement
350
351
  ? html `<label
351
352
  >${t('announcement.field.acknowledge-by')}
352
- <input type="date" .value=${form.acknowledgeBy} ?disabled=${!editable} @input=${(e) => set({ acknowledgeBy: e.target.value })}
353
- /></label>`
353
+ <ox-input-date type="date" .value=${form.acknowledgeBy} ?disabled=${!editable} @change=${(e) => set({ acknowledgeBy: e.target.value })}></ox-input-date></label>`
354
354
  : nothing}
355
355
  <label class="check wide"><input type="checkbox" .checked=${form.popup} ?disabled=${!editable} @change=${(e) => set({ popup: e.target.checked })} />${t('announcement.text.popup-label')}</label>
356
356
  <label class="check wide"
@@ -376,7 +376,7 @@ let AnnouncementEditor = class AnnouncementEditor extends localize(i18next)(Page
376
376
  <button aria-label=${t('announcement.button.remove')} @click=${() => set({ added: form.added.filter((_, i) => i !== index) })}><md-icon>close</md-icon></button>
377
377
  </li>`)}
378
378
  </ul>
379
- ${editable ? html `<ox-input-file quiet hide-filelist multiple icon="attach_file" .progress=${this.progress} @change=${(e) => this.pick(e)}></ox-input-file>` : nothing}
379
+ ${editable ? html `<ox-input-file quiet hide-filelist multiple icon="attach_file" .dropTarget=${this} .progress=${this.progress} @change=${(e) => this.pick(e)}></ox-input-file>` : nothing}
380
380
  </section>
381
381
 
382
382
  <section class="page-section">
@@ -1 +1 @@
1
- {"version":3,"file":"announcement-editor.js","sourceRoot":"","sources":["../../client/pages/announcement-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/input/ox-input-file.js'\nimport '@operato/list-state/ox-page-state.js'\nimport '../components/audience-picker.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\nimport { MutationController, QueryController, uploadContext } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { notify } from '@operato/layout'\nimport { navigate, PageView, DraftController } from '@operato/shell'\nimport { renderMarkdown } from '@things-factory/ai-assistant/dist-client/index.js'\nimport { ButtonStyles, DocumentPageStyles, FormFieldStyles } from '@operato/styles'\n\nimport { chooser } from '../components/audience-picker.js'\nimport { FULL_FIELDS, type AnnouncementInput, type AnnouncementItem, type AnnouncementLink, type Audience, type FileRow } from '../utils/announcement-api.js'\nimport { CATEGORIES, categoryWord, IMPORTANCES, importanceWord, statusWord, t } from '../utils/announcement-words.js'\n\ntype Form = {\n title: string\n body: string\n category: string\n importance: string\n startsAt: string\n endsAt: string\n pinned: boolean\n requiresAcknowledgement: boolean\n acknowledgeBy: string\n popup: boolean\n sendEmail: boolean\n links: AnnouncementLink[]\n audiences: Audience[]\n /** Files picked to attach, attached ones to take off, and whether a changed one tells everyone again. */\n added: File[]\n removed: string[]\n notifyAgain: boolean\n}\n\nconst blank = (): Form => ({\n title: '',\n body: '',\n category: 'GENERAL',\n importance: 'NORMAL',\n startsAt: '',\n endsAt: '',\n pinned: false,\n requiresAcknowledgement: false,\n acknowledgeBy: '',\n popup: false,\n sendEmail: false,\n links: [],\n audiences: [],\n added: [],\n removed: [],\n notifyAgain: false\n})\n\n/** `datetime-local` speaks the reader's own clock. */\nconst pad = (n: number) => String(n).padStart(2, '0')\nfunction localOf(value?: string | null, dateOnly = false): string {\n if (!value) return ''\n const d = new Date(value)\n const day = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`\n return dateOnly ? day : `${day}T${pad(d.getHours())}:${pad(d.getMinutes())}`\n}\nconst isoOf = (local: string, endOfDay = false) => (local ? new Date(endOfDay && local.length === 10 ? `${local}T23:59:59` : local).toISOString() : null)\n\nfunction formOf(one: AnnouncementItem): Form {\n return {\n title: one.title,\n body: one.body ?? '',\n category: one.category,\n importance: one.importance,\n startsAt: localOf(one.startsAt),\n endsAt: localOf(one.endsAt),\n pinned: one.pinned,\n requiresAcknowledgement: one.requiresAcknowledgement,\n acknowledgeBy: localOf(one.acknowledgeBy, true),\n popup: one.popup,\n sendEmail: !!one.sendEmail,\n links: (one.links ?? []).map(link => ({ ...link })),\n audiences: (one.audiences ?? []).map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName })),\n added: [],\n removed: [],\n notifyAgain: false\n }\n}\n\n/**\n * 공지 작성 — what it says, to whom, when, and what it asks of its readers (ADR-0163 decisions 2-5). A new one is kept as\n * a draft until it is published; one already out is changed into a new version, and its writer may tell everyone again.\n * `?from=<id>` starts a new one as a copy.\n */\n@customElement('announcement-editor')\nexport class AnnouncementEditor extends localize(i18next)(PageView) {\n static styles = [\n FormFieldStyles,\n ButtonStyles,\n DocumentPageStyles,\n css`\n .form {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n }\n .form .wide {\n grid-column: 1 / -1;\n }\n label {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n label.check {\n flex-direction: row;\n align-items: center;\n gap: var(--spacing-small, 4px);\n }\n textarea.body {\n display: block;\n width: 100%;\n box-sizing: border-box;\n min-height: 240px;\n font-family: inherit;\n }\n /* Writing or its preview - the segmented switch of the card library (ai-dashboard), right above the body. */\n .tabs {\n display: inline-flex;\n gap: 4px;\n padding: 3px;\n margin-bottom: var(--spacing-small, 4px);\n border-radius: 10px;\n background: var(--ui-panel-2, var(--md-sys-color-surface-container));\n }\n .tabs button {\n padding: 4px 14px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n box-shadow: none;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n }\n .tabs button[aria-selected='true'] {\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n box-shadow: 0 1px 3px rgb(0 0 0 / 12%);\n }\n .preview.markdown :is(ul, ol) {\n padding-inline-start: 1.4em;\n }\n .preview {\n min-height: 240px;\n padding: var(--spacing-medium, 8px);\n border: 1px solid var(--ui-line-soft, var(--md-sys-color-outline-variant));\n border-radius: var(--border-radius, 4px);\n }\n .hint {\n font-size: var(--ui-t-small, 12px);\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n ul.files,\n ul.links {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small, 4px);\n }\n ul.files li,\n ul.links li {\n display: flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n }\n ul.links input {\n flex: 1;\n }\n ul.links input.label {\n flex: 0 1 200px;\n }\n .removed {\n text-decoration: line-through;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n .add-link {\n align-self: flex-start;\n }\n li button,\n .add-link {\n border: 0;\n background: none;\n cursor: pointer;\n color: var(--md-sys-color-primary);\n display: inline-flex;\n align-items: center;\n gap: 2px;\n font: inherit;\n padding: 0;\n }\n li button md-icon,\n .add-link md-icon {\n --md-icon-size: 18px;\n }\n `\n ]\n\n /** What the address opens: an announcement by id, a new one copied `from` another, or a new one. */\n @state() private address?: { id?: string; from?: string }\n @state() preview = false\n @state() progress?: number\n\n /* The announcement edited, or the one a new one is copied from (ADR-0190). */\n private record = new QueryController(this, gql(`query ($id: String!) { announcement(id: $id) { ${FULL_FIELDS} readCount acknowledgedCount } }`), {\n variables: () => {\n const id = this.address?.id || this.address?.from\n return id ? { id } : undefined\n }\n })\n\n /* What is typed over the announcement read - a copy starts without its days, a new one blank. */\n private draft = new DraftController<Form>(this, {\n read: () => {\n if (!this.address) return undefined\n if (!this.address.id && !this.address.from) return blank()\n const one = this.record.data?.announcement\n if (!one) return undefined\n return this.address.from && !this.address.id ? { ...formOf(one), startsAt: '', endsAt: '' } : formOf(one)\n },\n key: () => this.address\n })\n\n /* A change reads the announcement again once it is done; one that goes out or away leaves the editor. */\n private saves = {\n create: new MutationController(this, gql`mutation ($input: AnnouncementInput!, $attach: [Upload!]) { createAnnouncement(input: $input, attach: $attach) { id } }`),\n update: new MutationController(\n this,\n gql`\n mutation ($id: String!, $input: AnnouncementInput!, $attach: [Upload!], $remove: [String!], $notifyAgain: Boolean) {\n updateAnnouncement(id: $id, input: $input, attach: $attach, remove: $remove, notifyAgain: $notifyAgain) { id status }\n }\n `,\n { refetch: () => [this.record] }\n ),\n publish: new MutationController(this, gql`mutation ($id: String!) { publishAnnouncement(id: $id) { id status startsAt } }`),\n remove: new MutationController(this, gql`mutation ($id: String!) { deleteAnnouncement(id: $id) }`)\n }\n\n get announcement(): AnnouncementItem | null {\n return (this.address?.id && this.record.data?.announcement) || null\n }\n\n /** The form as it shows: each field's edit, else what was read (blank while it is read). */\n get form(): Form {\n return Object.fromEntries(Object.entries(blank()).map(([name, given]) => [name, this.draft.value(name as keyof Form) ?? given])) as Form\n }\n\n /** The files attached so far - a copy starts with none. */\n get files(): FileRow[] {\n return this.announcement?.attachments ?? []\n }\n\n /** A failed read, or an announcement the address names that is not there. */\n get error(): unknown {\n if (this.record.error) return this.record.error\n return this.record.data && !this.record.data.announcement ? new Error(t('announcement.refusal.unknown-announcement')) : null\n }\n\n get loading() {\n return this.record.loading\n }\n\n get busy() {\n return Object.values(this.saves).some(save => save.pending)\n }\n\n get out() {\n return this.announcement?.status === 'PUBLISHED'\n }\n\n get context() {\n const one = this.announcement\n const actions: any[] = []\n const draft = !one || one.status === 'DRAFT'\n if (!this.busy && !this.error && (!one || one.editable)) {\n if (draft && one) actions.push({ title: t('announcement.button.delete'), icon: 'delete', action: () => this.deleteDraft() })\n actions.push({ title: draft ? t('announcement.button.save-draft') : t('announcement.button.save'), icon: 'save', action: () => this.save(false) })\n if (draft) {\n const later = !!this.form.startsAt && new Date(this.form.startsAt).getTime() > Date.now()\n actions.push({ title: later ? t('announcement.button.schedule') : t('announcement.button.publish'), icon: 'campaign', emphasis: { raised: true }, action: () => this.save(true) })\n }\n }\n return {\n title: one ? `${t('announcement.title.edit')} · ${one.title}` : t('announcement.title.new'),\n ...(one ? { description: statusWord(one.status) } : {}),\n frame: 'document',\n /* Opened from 공지사항 or 공지 관리; the menu marks 공지사항. */\n menu: 'announcement-list',\n actions\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (!this.active || !(changes.active || changes.params)) return\n const { id, from } = lifecycle?.params ?? {}\n const address = id ? { id } : from ? { from } : {}\n if (JSON.stringify(address) === JSON.stringify(this.address)) return\n this.address = address\n this.preview = false\n }\n\n render() {\n const form = this.form\n const set = (patch: Partial<Form>) => {\n for (const [name, value] of Object.entries(patch)) this.draft.set(name as keyof Form, value)\n this.updateContext()\n }\n const editable = !this.busy && (!this.announcement || !!this.announcement.editable)\n return html`<ox-page-state .loading=${this.loading} .error=${this.error} @retry=${() => this.record.refetch()}>\n <div class=\"page\">\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.text.section-what')}</h3></header>\n <div class=\"form\">\n <label class=\"wide\"\n >${t('announcement.field.title')}\n <input .value=${form.title} maxlength=\"200\" ?disabled=${!editable} @input=${(e: any) => set({ title: e.target.value })}\n /></label>\n <label\n >${t('announcement.field.category')}\n ${chooser(\n CATEGORIES.map(code => ({ value: code, display: categoryWord(code) })),\n form.category,\n value => set({ category: value }),\n '—',\n t('announcement.field.category')\n )}\n </label>\n <label\n >${t('announcement.field.importance')}\n ${chooser(\n IMPORTANCES.map(code => ({ value: code, display: importanceWord(code) })),\n form.importance,\n /* An urgent one pops up unless its writer says not to. */\n value => set({ importance: value, ...(value === 'URGENT' ? { popup: true } : {}) }),\n '—',\n t('announcement.field.importance')\n )}\n </label>\n <div class=\"wide\">\n <div class=\"tabs\" role=\"tablist\">\n <button role=\"tab\" aria-selected=${String(!this.preview)} @click=${() => (this.preview = false)}>${t('announcement.text.write')}</button>\n <button role=\"tab\" aria-selected=${String(this.preview)} @click=${() => (this.preview = true)}>${t('announcement.text.preview')}</button>\n </div>\n ${this.preview\n ? html`<div class=\"preview markdown\">${unsafeHTML(renderMarkdown(form.body))}</div>`\n : html`<textarea class=\"body\" .value=${form.body} ?disabled=${!editable} placeholder=${t('announcement.text.body-placeholder')} @input=${(e: any) => set({ body: e.target.value })}></textarea>\n <span class=\"hint\">${t('announcement.text.markdown-hint')}</span>`}\n </div>\n </div>\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.field.audience')}</h3></header>\n <announcement-audience-picker .value=${form.audiences} ?disabled=${!editable} @change=${(e: CustomEvent) => set({ audiences: e.detail })}></announcement-audience-picker>\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.text.section-when')}</h3></header>\n <div class=\"form\">\n <label\n >${t('announcement.field.starts-at')}\n <input type=\"datetime-local\" .value=${form.startsAt} ?disabled=${!editable || this.out} @input=${(e: any) => set({ startsAt: e.target.value })} />\n <span class=\"hint\">${t('announcement.text.starts-at-hint')}</span>\n </label>\n <label\n >${t('announcement.field.ends-at')}\n <input type=\"datetime-local\" .value=${form.endsAt} ?disabled=${!editable} @input=${(e: any) => set({ endsAt: e.target.value })} />\n <span class=\"hint\">${t('announcement.text.ends-at-hint')}</span>\n </label>\n <label class=\"check wide\"><input type=\"checkbox\" .checked=${form.pinned} ?disabled=${!editable} @change=${(e: any) => set({ pinned: e.target.checked })} />${t('announcement.text.pinned-label')}</label>\n <label class=\"check wide\"\n ><input\n type=\"checkbox\"\n .checked=${form.requiresAcknowledgement}\n ?disabled=${!editable}\n @change=${(e: any) => set({ requiresAcknowledgement: e.target.checked, ...(e.target.checked ? { popup: true } : { acknowledgeBy: '' }) })}\n />${t('announcement.text.acknowledge-label')}</label\n >\n ${form.requiresAcknowledgement\n ? html`<label\n >${t('announcement.field.acknowledge-by')}\n <input type=\"date\" .value=${form.acknowledgeBy} ?disabled=${!editable} @input=${(e: any) => set({ acknowledgeBy: e.target.value })}\n /></label>`\n : nothing}\n <label class=\"check wide\"><input type=\"checkbox\" .checked=${form.popup} ?disabled=${!editable} @change=${(e: any) => set({ popup: e.target.checked })} />${t('announcement.text.popup-label')}</label>\n <label class=\"check wide\"\n ><input type=\"checkbox\" .checked=${form.sendEmail} ?disabled=${!editable} @change=${(e: any) => set({ sendEmail: e.target.checked })} />${t('announcement.text.email-label')}</label\n >\n ${form.sendEmail ? html`<span class=\"hint wide\">${t('announcement.text.email-hint')}</span>` : nothing}\n </div>\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.field.attachments')}</h3></header>\n <ul class=\"files\">\n ${this.files.map(\n file => html`<li class=${form.removed.includes(file.id) ? 'removed' : ''}>\n <md-icon>attach_file</md-icon>${file.name}\n ${editable\n ? form.removed.includes(file.id)\n ? html`<button @click=${() => set({ removed: form.removed.filter(id => id !== file.id) })}><md-icon>undo</md-icon></button>`\n : html`<button aria-label=${t('announcement.button.remove')} @click=${() => set({ removed: [...form.removed, file.id] })}><md-icon>close</md-icon></button>`\n : nothing}\n </li>`\n )}\n ${form.added.map(\n (file, index) => html`<li>\n <md-icon>upload_file</md-icon>${file.name}\n <button aria-label=${t('announcement.button.remove')} @click=${() => set({ added: form.added.filter((_, i) => i !== index) })}><md-icon>close</md-icon></button>\n </li>`\n )}\n </ul>\n ${editable ? html`<ox-input-file quiet hide-filelist multiple icon=\"attach_file\" .progress=${this.progress} @change=${(e: CustomEvent) => this.pick(e)}></ox-input-file>` : nothing}\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.field.links')}</h3></header>\n <ul class=\"links\">\n ${form.links.map(\n (link, index) => html`<li>\n <input\n class=\"label\"\n .value=${link.label}\n maxlength=\"100\"\n placeholder=${t('announcement.text.link-label')}\n ?disabled=${!editable}\n @input=${(e: any) => set({ links: form.links.map((one, i) => (i === index ? { ...one, label: e.target.value } : one)) })}\n />\n <input\n .value=${link.url}\n placeholder=${t('announcement.text.link-url')}\n ?disabled=${!editable}\n @input=${(e: any) => set({ links: form.links.map((one, i) => (i === index ? { ...one, url: e.target.value } : one)) })}\n />\n ${editable ? html`<button aria-label=${t('announcement.button.remove')} @click=${() => set({ links: form.links.filter((_, i) => i !== index) })}><md-icon>close</md-icon></button>` : nothing}\n </li>`\n )}\n </ul>\n ${editable && form.links.length < 10\n ? html`<button class=\"add-link\" @click=${() => set({ links: [...form.links, { label: '', url: '' }] })}><md-icon>add_link</md-icon>${t('announcement.button.add-link')}</button>\n <span class=\"hint\">${t('announcement.text.link-hint')}</span>`\n : nothing}\n </section>\n\n ${this.out\n ? html`<section class=\"page-section\">\n <label class=\"check\"><input type=\"checkbox\" .checked=${form.notifyAgain} @change=${(e: any) => set({ notifyAgain: e.target.checked })} />${t('announcement.text.notify-again')}</label>\n <span class=\"hint\">${t('announcement.text.new-version', { version: (this.announcement?.version ?? 1) + 1 })}</span>\n </section>`\n : nothing}\n </div>\n </ox-page-state>`\n }\n\n private pick(e: CustomEvent) {\n const picked = [...((e.detail as File[]) ?? [])]\n /* The picker's own reset says `change` again, with nothing - that one is let go. */\n if (!picked.length) return\n ;(e.target as any).reset?.()\n this.draft.set('added', [...this.form.added, ...picked])\n }\n\n private input(): AnnouncementInput {\n const form = this.form\n return {\n title: form.title,\n body: form.body,\n category: form.category,\n importance: form.importance,\n startsAt: isoOf(form.startsAt),\n endsAt: isoOf(form.endsAt),\n pinned: form.pinned,\n requiresAcknowledgement: form.requiresAcknowledgement,\n acknowledgeBy: form.requiresAcknowledgement ? isoOf(form.acknowledgeBy, true) : null,\n popup: form.popup,\n sendEmail: form.sendEmail,\n links: form.links.filter(link => link.label.trim() || link.url.trim()),\n audiences: form.audiences.map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName: targetName ?? undefined }))\n }\n }\n\n /**\n * Keeps it, then sends it out when asked - a draft that cannot go out stays kept, opened as one. Failures are told by\n * the GraphQL link.\n */\n private async save(publish: boolean) {\n if (this.busy) return\n const id = this.announcement?.id\n const { added, removed, notifyAgain } = this.form\n const context = added.length ? uploadContext(fraction => (this.progress = fraction)) : undefined\n const saving = this.draft.submit(() =>\n id\n ? this.saves.update.run({ id, input: this.input(), attach: added, remove: removed, notifyAgain }, { context })\n : this.saves.create.run({ input: this.input(), attach: added }, { context })\n )\n /* The actions wait while it is out. */\n this.updateContext()\n const saved = await saving\n this.progress = undefined\n this.updateContext()\n if (!saved) return\n const kept = id ?? saved.createAnnouncement.id\n if (publish) {\n const sent = await this.saves.publish.run({ id: kept })\n if (sent) {\n notify({ message: sent.publishAnnouncement.status === 'SCHEDULED' ? t('announcement.text.scheduled-done') : t('announcement.text.published-done') })\n navigate(`announcement-view?id=${kept}`)\n return\n }\n } else notify({ message: t('announcement.text.saved') })\n if (!id) navigate(`announcement-editor?id=${kept}`)\n }\n\n private async deleteDraft() {\n const sure = await OxPrompt.open({\n title: t('announcement.button.delete'),\n text: t('announcement.text.delete-confirm', { title: this.announcement!.title }),\n confirmButton: { text: t('announcement.button.delete') },\n cancelButton: { text: t('announcement.button.cancel') }\n })\n if (!sure) return\n if (!(await this.saves.remove.run({ id: this.announcement!.id }))) return\n notify({ message: t('announcement.text.deleted') })\n navigate('announcement-manage-list')\n }\n}\n"]}
1
+ {"version":3,"file":"announcement-editor.js","sourceRoot":"","sources":["../../client/pages/announcement-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/input/ox-input-date.js'\nimport '@material/web/icon/icon.js'\nimport '@operato/input/ox-input-file.js'\nimport '@operato/list-state/ox-page-state.js'\nimport '../components/audience-picker.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js'\n\nimport { MutationController, QueryController, uploadContext } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { notify } from '@operato/layout'\nimport { navigate, PageView, DraftController } from '@operato/shell'\nimport { renderMarkdown } from '@things-factory/ai-assistant/dist-client/index.js'\nimport { ButtonStyles, DocumentPageStyles, FormFieldStyles } from '@operato/styles'\n\nimport { chooser } from '../components/audience-picker.js'\nimport { FULL_FIELDS, type AnnouncementInput, type AnnouncementItem, type AnnouncementLink, type Audience, type FileRow } from '../utils/announcement-api.js'\nimport { CATEGORIES, categoryWord, IMPORTANCES, importanceWord, statusWord, t } from '../utils/announcement-words.js'\n\ntype Form = {\n title: string\n body: string\n category: string\n importance: string\n startsAt: string\n endsAt: string\n pinned: boolean\n requiresAcknowledgement: boolean\n acknowledgeBy: string\n popup: boolean\n sendEmail: boolean\n links: AnnouncementLink[]\n audiences: Audience[]\n /** Files picked to attach, attached ones to take off, and whether a changed one tells everyone again. */\n added: File[]\n removed: string[]\n notifyAgain: boolean\n}\n\nconst blank = (): Form => ({\n title: '',\n body: '',\n category: 'GENERAL',\n importance: 'NORMAL',\n startsAt: '',\n endsAt: '',\n pinned: false,\n requiresAcknowledgement: false,\n acknowledgeBy: '',\n popup: false,\n sendEmail: false,\n links: [],\n audiences: [],\n added: [],\n removed: [],\n notifyAgain: false\n})\n\n/** `datetime-local` speaks the reader's own clock. */\nconst pad = (n: number) => String(n).padStart(2, '0')\nfunction localOf(value?: string | null, dateOnly = false): string {\n if (!value) return ''\n const d = new Date(value)\n const day = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`\n return dateOnly ? day : `${day}T${pad(d.getHours())}:${pad(d.getMinutes())}`\n}\nconst isoOf = (local: string, endOfDay = false) => (local ? new Date(endOfDay && local.length === 10 ? `${local}T23:59:59` : local).toISOString() : null)\n\nfunction formOf(one: AnnouncementItem): Form {\n return {\n title: one.title,\n body: one.body ?? '',\n category: one.category,\n importance: one.importance,\n startsAt: localOf(one.startsAt),\n endsAt: localOf(one.endsAt),\n pinned: one.pinned,\n requiresAcknowledgement: one.requiresAcknowledgement,\n acknowledgeBy: localOf(one.acknowledgeBy, true),\n popup: one.popup,\n sendEmail: !!one.sendEmail,\n links: (one.links ?? []).map(link => ({ ...link })),\n audiences: (one.audiences ?? []).map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName })),\n added: [],\n removed: [],\n notifyAgain: false\n }\n}\n\n/**\n * 공지 작성 — what it says, to whom, when, and what it asks of its readers (ADR-0163 decisions 2-5). A new one is kept as\n * a draft until it is published; one already out is changed into a new version, and its writer may tell everyone again.\n * `?from=<id>` starts a new one as a copy.\n */\n@customElement('announcement-editor')\nexport class AnnouncementEditor extends localize(i18next)(PageView) {\n static styles = [\n FormFieldStyles,\n ButtonStyles,\n DocumentPageStyles,\n css`\n .form {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n gap: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n }\n .form .wide {\n grid-column: 1 / -1;\n }\n label {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n label.check {\n flex-direction: row;\n align-items: center;\n gap: var(--spacing-small, 4px);\n }\n textarea.body {\n display: block;\n width: 100%;\n box-sizing: border-box;\n min-height: 240px;\n font-family: inherit;\n }\n /* Writing or its preview - the segmented switch of the card library (ai-dashboard), right above the body. */\n .tabs {\n display: inline-flex;\n gap: 4px;\n padding: 3px;\n margin-bottom: var(--spacing-small, 4px);\n border-radius: 10px;\n background: var(--ui-panel-2, var(--md-sys-color-surface-container));\n }\n .tabs button {\n padding: 4px 14px;\n border: 0;\n border-radius: 8px;\n background: transparent;\n box-shadow: none;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n }\n .tabs button[aria-selected='true'] {\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n box-shadow: 0 1px 3px rgb(0 0 0 / 12%);\n }\n .preview.markdown :is(ul, ol) {\n padding-inline-start: 1.4em;\n }\n .preview {\n min-height: 240px;\n padding: var(--spacing-medium, 8px);\n border: 1px solid var(--ui-line-soft, var(--md-sys-color-outline-variant));\n border-radius: var(--border-radius, 4px);\n }\n .hint {\n font-size: var(--ui-t-small, 12px);\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n ul.files,\n ul.links {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small, 4px);\n }\n ul.files li,\n ul.links li {\n display: flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n }\n ul.links input {\n flex: 1;\n }\n ul.links input.label {\n flex: 0 1 200px;\n }\n .removed {\n text-decoration: line-through;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n .add-link {\n align-self: flex-start;\n }\n li button,\n .add-link {\n border: 0;\n background: none;\n cursor: pointer;\n color: var(--md-sys-color-primary);\n display: inline-flex;\n align-items: center;\n gap: 2px;\n font: inherit;\n padding: 0;\n }\n li button md-icon,\n .add-link md-icon {\n --md-icon-size: 18px;\n }\n `\n ]\n\n /** What the address opens: an announcement by id, a new one copied `from` another, or a new one. */\n @state() private address?: { id?: string; from?: string }\n @state() preview = false\n @state() progress?: number\n\n /* The announcement edited, or the one a new one is copied from (ADR-0190). */\n private record = new QueryController(this, gql(`query ($id: String!) { announcement(id: $id) { ${FULL_FIELDS} readCount acknowledgedCount } }`), {\n variables: () => {\n const id = this.address?.id || this.address?.from\n return id ? { id } : undefined\n }\n })\n\n /* What is typed over the announcement read - a copy starts without its days, a new one blank. */\n private draft = new DraftController<Form>(this, {\n read: () => {\n if (!this.address) return undefined\n if (!this.address.id && !this.address.from) return blank()\n const one = this.record.data?.announcement\n if (!one) return undefined\n return this.address.from && !this.address.id ? { ...formOf(one), startsAt: '', endsAt: '' } : formOf(one)\n },\n key: () => this.address\n })\n\n /* A change reads the announcement again once it is done; one that goes out or away leaves the editor. */\n private saves = {\n create: new MutationController(this, gql`mutation ($input: AnnouncementInput!, $attach: [Upload!]) { createAnnouncement(input: $input, attach: $attach) { id } }`),\n update: new MutationController(\n this,\n gql`\n mutation ($id: String!, $input: AnnouncementInput!, $attach: [Upload!], $remove: [String!], $notifyAgain: Boolean) {\n updateAnnouncement(id: $id, input: $input, attach: $attach, remove: $remove, notifyAgain: $notifyAgain) { id status }\n }\n `,\n { refetch: () => [this.record] }\n ),\n publish: new MutationController(this, gql`mutation ($id: String!) { publishAnnouncement(id: $id) { id status startsAt } }`),\n remove: new MutationController(this, gql`mutation ($id: String!) { deleteAnnouncement(id: $id) }`)\n }\n\n get announcement(): AnnouncementItem | null {\n return (this.address?.id && this.record.data?.announcement) || null\n }\n\n /** The form as it shows: each field's edit, else what was read (blank while it is read). */\n get form(): Form {\n return Object.fromEntries(Object.entries(blank()).map(([name, given]) => [name, this.draft.value(name as keyof Form) ?? given])) as Form\n }\n\n /** The files attached so far - a copy starts with none. */\n get files(): FileRow[] {\n return this.announcement?.attachments ?? []\n }\n\n /** A failed read, or an announcement the address names that is not there. */\n get error(): unknown {\n if (this.record.error) return this.record.error\n return this.record.data && !this.record.data.announcement ? new Error(t('announcement.refusal.unknown-announcement')) : null\n }\n\n get loading() {\n return this.record.loading\n }\n\n get busy() {\n return Object.values(this.saves).some(save => save.pending)\n }\n\n get out() {\n return this.announcement?.status === 'PUBLISHED'\n }\n\n get context() {\n const one = this.announcement\n const actions: any[] = []\n const draft = !one || one.status === 'DRAFT'\n if (!this.busy && !this.error && (!one || one.editable)) {\n if (draft && one) actions.push({ title: t('announcement.button.delete'), icon: 'delete', action: () => this.deleteDraft() })\n actions.push({ title: draft ? t('announcement.button.save-draft') : t('announcement.button.save'), icon: 'save', action: () => this.save(false) })\n if (draft) {\n const later = !!this.form.startsAt && new Date(this.form.startsAt).getTime() > Date.now()\n actions.push({ title: later ? t('announcement.button.schedule') : t('announcement.button.publish'), icon: 'campaign', emphasis: { raised: true }, action: () => this.save(true) })\n }\n }\n return {\n title: one ? `${t('announcement.title.edit')} · ${one.title}` : t('announcement.title.new'),\n ...(one ? { description: statusWord(one.status) } : {}),\n frame: 'document',\n /* Opened from 공지사항 or 공지 관리; the menu marks 공지사항. */\n menu: 'announcement-list',\n actions\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (!this.active || !(changes.active || changes.params)) return\n const { id, from } = lifecycle?.params ?? {}\n const address = id ? { id } : from ? { from } : {}\n if (JSON.stringify(address) === JSON.stringify(this.address)) return\n this.address = address\n this.preview = false\n }\n\n render() {\n const form = this.form\n const set = (patch: Partial<Form>) => {\n for (const [name, value] of Object.entries(patch)) this.draft.set(name as keyof Form, value)\n this.updateContext()\n }\n const editable = !this.busy && (!this.announcement || !!this.announcement.editable)\n return html`<ox-page-state .loading=${this.loading} .error=${this.error} @retry=${() => this.record.refetch()}>\n <div class=\"page\">\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.text.section-what')}</h3></header>\n <div class=\"form\">\n <label class=\"wide\"\n >${t('announcement.field.title')}\n <input .value=${form.title} maxlength=\"200\" ?disabled=${!editable} @input=${(e: any) => set({ title: e.target.value })}\n /></label>\n <label\n >${t('announcement.field.category')}\n ${chooser(\n CATEGORIES.map(code => ({ value: code, display: categoryWord(code) })),\n form.category,\n value => set({ category: value }),\n '—',\n t('announcement.field.category')\n )}\n </label>\n <label\n >${t('announcement.field.importance')}\n ${chooser(\n IMPORTANCES.map(code => ({ value: code, display: importanceWord(code) })),\n form.importance,\n /* An urgent one pops up unless its writer says not to. */\n value => set({ importance: value, ...(value === 'URGENT' ? { popup: true } : {}) }),\n '—',\n t('announcement.field.importance')\n )}\n </label>\n <div class=\"wide\">\n <div class=\"tabs\" role=\"tablist\">\n <button role=\"tab\" aria-selected=${String(!this.preview)} @click=${() => (this.preview = false)}>${t('announcement.text.write')}</button>\n <button role=\"tab\" aria-selected=${String(this.preview)} @click=${() => (this.preview = true)}>${t('announcement.text.preview')}</button>\n </div>\n ${this.preview\n ? html`<div class=\"preview markdown\">${unsafeHTML(renderMarkdown(form.body))}</div>`\n : html`<textarea class=\"body\" .value=${form.body} ?disabled=${!editable} placeholder=${t('announcement.text.body-placeholder')} @input=${(e: any) => set({ body: e.target.value })}></textarea>\n <span class=\"hint\">${t('announcement.text.markdown-hint')}</span>`}\n </div>\n </div>\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.field.audience')}</h3></header>\n <announcement-audience-picker .value=${form.audiences} ?disabled=${!editable} @change=${(e: CustomEvent) => set({ audiences: e.detail })}></announcement-audience-picker>\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.text.section-when')}</h3></header>\n <div class=\"form\">\n <label\n >${t('announcement.field.starts-at')}\n <input type=\"datetime-local\" .value=${form.startsAt} ?disabled=${!editable || this.out} @input=${(e: any) => set({ startsAt: e.target.value })} />\n <span class=\"hint\">${t('announcement.text.starts-at-hint')}</span>\n </label>\n <label\n >${t('announcement.field.ends-at')}\n <input type=\"datetime-local\" .value=${form.endsAt} ?disabled=${!editable} @input=${(e: any) => set({ endsAt: e.target.value })} />\n <span class=\"hint\">${t('announcement.text.ends-at-hint')}</span>\n </label>\n <label class=\"check wide\"><input type=\"checkbox\" .checked=${form.pinned} ?disabled=${!editable} @change=${(e: any) => set({ pinned: e.target.checked })} />${t('announcement.text.pinned-label')}</label>\n <label class=\"check wide\"\n ><input\n type=\"checkbox\"\n .checked=${form.requiresAcknowledgement}\n ?disabled=${!editable}\n @change=${(e: any) => set({ requiresAcknowledgement: e.target.checked, ...(e.target.checked ? { popup: true } : { acknowledgeBy: '' }) })}\n />${t('announcement.text.acknowledge-label')}</label\n >\n ${form.requiresAcknowledgement\n ? html`<label\n >${t('announcement.field.acknowledge-by')}\n <ox-input-date type=\"date\" .value=${form.acknowledgeBy} ?disabled=${!editable} @change=${(e: any) => set({ acknowledgeBy: e.target.value })}></ox-input-date></label>`\n : nothing}\n <label class=\"check wide\"><input type=\"checkbox\" .checked=${form.popup} ?disabled=${!editable} @change=${(e: any) => set({ popup: e.target.checked })} />${t('announcement.text.popup-label')}</label>\n <label class=\"check wide\"\n ><input type=\"checkbox\" .checked=${form.sendEmail} ?disabled=${!editable} @change=${(e: any) => set({ sendEmail: e.target.checked })} />${t('announcement.text.email-label')}</label\n >\n ${form.sendEmail ? html`<span class=\"hint wide\">${t('announcement.text.email-hint')}</span>` : nothing}\n </div>\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.field.attachments')}</h3></header>\n <ul class=\"files\">\n ${this.files.map(\n file => html`<li class=${form.removed.includes(file.id) ? 'removed' : ''}>\n <md-icon>attach_file</md-icon>${file.name}\n ${editable\n ? form.removed.includes(file.id)\n ? html`<button @click=${() => set({ removed: form.removed.filter(id => id !== file.id) })}><md-icon>undo</md-icon></button>`\n : html`<button aria-label=${t('announcement.button.remove')} @click=${() => set({ removed: [...form.removed, file.id] })}><md-icon>close</md-icon></button>`\n : nothing}\n </li>`\n )}\n ${form.added.map(\n (file, index) => html`<li>\n <md-icon>upload_file</md-icon>${file.name}\n <button aria-label=${t('announcement.button.remove')} @click=${() => set({ added: form.added.filter((_, i) => i !== index) })}><md-icon>close</md-icon></button>\n </li>`\n )}\n </ul>\n ${editable ? html`<ox-input-file quiet hide-filelist multiple icon=\"attach_file\" .dropTarget=${this} .progress=${this.progress} @change=${(e: CustomEvent) => this.pick(e)}></ox-input-file>` : nothing}\n </section>\n\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${t('announcement.field.links')}</h3></header>\n <ul class=\"links\">\n ${form.links.map(\n (link, index) => html`<li>\n <input\n class=\"label\"\n .value=${link.label}\n maxlength=\"100\"\n placeholder=${t('announcement.text.link-label')}\n ?disabled=${!editable}\n @input=${(e: any) => set({ links: form.links.map((one, i) => (i === index ? { ...one, label: e.target.value } : one)) })}\n />\n <input\n .value=${link.url}\n placeholder=${t('announcement.text.link-url')}\n ?disabled=${!editable}\n @input=${(e: any) => set({ links: form.links.map((one, i) => (i === index ? { ...one, url: e.target.value } : one)) })}\n />\n ${editable ? html`<button aria-label=${t('announcement.button.remove')} @click=${() => set({ links: form.links.filter((_, i) => i !== index) })}><md-icon>close</md-icon></button>` : nothing}\n </li>`\n )}\n </ul>\n ${editable && form.links.length < 10\n ? html`<button class=\"add-link\" @click=${() => set({ links: [...form.links, { label: '', url: '' }] })}><md-icon>add_link</md-icon>${t('announcement.button.add-link')}</button>\n <span class=\"hint\">${t('announcement.text.link-hint')}</span>`\n : nothing}\n </section>\n\n ${this.out\n ? html`<section class=\"page-section\">\n <label class=\"check\"><input type=\"checkbox\" .checked=${form.notifyAgain} @change=${(e: any) => set({ notifyAgain: e.target.checked })} />${t('announcement.text.notify-again')}</label>\n <span class=\"hint\">${t('announcement.text.new-version', { version: (this.announcement?.version ?? 1) + 1 })}</span>\n </section>`\n : nothing}\n </div>\n </ox-page-state>`\n }\n\n private pick(e: CustomEvent) {\n const picked = [...((e.detail as File[]) ?? [])]\n /* The picker's own reset says `change` again, with nothing - that one is let go. */\n if (!picked.length) return\n ;(e.target as any).reset?.()\n this.draft.set('added', [...this.form.added, ...picked])\n }\n\n private input(): AnnouncementInput {\n const form = this.form\n return {\n title: form.title,\n body: form.body,\n category: form.category,\n importance: form.importance,\n startsAt: isoOf(form.startsAt),\n endsAt: isoOf(form.endsAt),\n pinned: form.pinned,\n requiresAcknowledgement: form.requiresAcknowledgement,\n acknowledgeBy: form.requiresAcknowledgement ? isoOf(form.acknowledgeBy, true) : null,\n popup: form.popup,\n sendEmail: form.sendEmail,\n links: form.links.filter(link => link.label.trim() || link.url.trim()),\n audiences: form.audiences.map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName: targetName ?? undefined }))\n }\n }\n\n /**\n * Keeps it, then sends it out when asked - a draft that cannot go out stays kept, opened as one. Failures are told by\n * the GraphQL link.\n */\n private async save(publish: boolean) {\n if (this.busy) return\n const id = this.announcement?.id\n const { added, removed, notifyAgain } = this.form\n const context = added.length ? uploadContext(fraction => (this.progress = fraction)) : undefined\n const saving = this.draft.submit(() =>\n id\n ? this.saves.update.run({ id, input: this.input(), attach: added, remove: removed, notifyAgain }, { context })\n : this.saves.create.run({ input: this.input(), attach: added }, { context })\n )\n /* The actions wait while it is out. */\n this.updateContext()\n const saved = await saving\n this.progress = undefined\n this.updateContext()\n if (!saved) return\n const kept = id ?? saved.createAnnouncement.id\n if (publish) {\n const sent = await this.saves.publish.run({ id: kept })\n if (sent) {\n notify({ message: sent.publishAnnouncement.status === 'SCHEDULED' ? t('announcement.text.scheduled-done') : t('announcement.text.published-done') })\n navigate(`announcement-view?id=${kept}`)\n return\n }\n } else notify({ message: t('announcement.text.saved') })\n if (!id) navigate(`announcement-editor?id=${kept}`)\n }\n\n private async deleteDraft() {\n const sure = await OxPrompt.open({\n title: t('announcement.button.delete'),\n text: t('announcement.text.delete-confirm', { title: this.announcement!.title }),\n confirmButton: { text: t('announcement.button.delete') },\n cancelButton: { text: t('announcement.button.cancel') }\n })\n if (!sure) return\n if (!(await this.saves.remove.run({ id: this.announcement!.id }))) return\n notify({ message: t('announcement.text.deleted') })\n navigate('announcement-manage-list')\n }\n}\n"]}