@things-factory/announcement 10.1.259 → 10.1.261

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/client/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { generateAnnouncementBadge, refreshAnnouncementBadge } from './utils/announcement-badge.js'
2
+ export { AudiencePicker } from './components/audience-picker.js'
@@ -1,11 +1,9 @@
1
1
  import '@material/web/icon/icon.js'
2
2
  import '@operato/data-grist/ox-grist.js'
3
3
  import '@operato/data-grist/ox-filters-form.js'
4
- import '@operato/input/ox-select.js'
5
- import '@operato/popup/ox-popup-list.js'
6
4
 
7
5
  import gql from 'graphql-tag'
8
- import { css, html } from 'lit'
6
+ import { html } from 'lit'
9
7
  import { customElement, query, state } from 'lit/decorators.js'
10
8
 
11
9
  import { DataGrist, FetchOption } from '@operato/data-grist'
@@ -17,6 +15,7 @@ import { isMobileDevice } from '@operato/utils'
17
15
  import { hasPrivilege } from '@things-factory/auth-base/dist-client'
18
16
 
19
17
  import { LIST_FIELDS } from '../utils/announcement-api.js'
18
+ import { announcementPeriodOf } from '../utils/announcement-list-query.js'
20
19
  import { CATEGORIES, categoryWord, importanceWord, readerStateWord, t, when } from '../utils/announcement-words.js'
21
20
 
22
21
  /**
@@ -29,22 +28,10 @@ export class AnnouncementList extends localize(i18next)(PageView) {
29
28
  WorkSurfacePageStyles,
30
29
  CommonGristStyles,
31
30
  CommonHeaderStyles,
32
- ScrollbarStyles,
33
- css`
34
- .filters {
35
- display: flex;
36
- flex-wrap: wrap;
37
- align-items: center;
38
- gap: var(--spacing-medium, 8px);
39
- }
40
- ox-select {
41
- min-width: 140px;
42
- }
43
- `
31
+ ScrollbarStyles
44
32
  ]
45
33
 
46
34
  @state() gristConfig: any
47
- @state() period: 'current' | 'past' = 'current'
48
35
  /* A writer manages and writes from here - the menu offers one entry, and a reader sees no group of one. */
49
36
  @state() writer = false
50
37
  @query('ox-grist') private grist!: DataGrist
@@ -74,29 +61,14 @@ export class AnnouncementList extends localize(i18next)(PageView) {
74
61
  }
75
62
  }
76
63
 
64
+ /*
65
+ * The period, the category, search and page are the grid's own, kept in the address (FOOTER-BUTTON-REVIEW G09): a
66
+ * shared link, coming back and reloading read the same list, and a change of them reads page 1 again.
67
+ */
77
68
  render() {
78
- const periods = [
79
- { value: 'current', display: t('announcement.text.period-current') },
80
- { value: 'past', display: t('announcement.text.period-past') }
81
- ]
82
- return html`<ox-grist class="page-fill" search-mode="term" .mode=${isMobileDevice() ? 'CARD' : 'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
69
+ return html`<ox-grist class="page-fill" search-mode="term" .mode=${isMobileDevice() ? 'CARD' : 'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${this.active}>
83
70
  <div slot="headroom" class="header">
84
- <div class="filters">
85
- <ox-select
86
- .value=${this.period}
87
- aria-label=${t('announcement.text.period')}
88
- @change=${(e: CustomEvent) => {
89
- const next = e.detail === 'past' ? 'past' : 'current'
90
- if (next === this.period) return
91
- this.period = next
92
- this.grist.fetch()
93
- }}
94
- >
95
- <span slot="label">${periods.find(one => one.value === this.period)?.display}</span>
96
- <ox-popup-list align-left nowrap with-search>${periods.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>
97
- </ox-select>
98
- <ox-filters-form without-search autofocus></ox-filters-form>
99
- </div>
71
+ <div class="filters"><ox-filters-form without-search autofocus></ox-filters-form></div>
100
72
  </div>
101
73
  </ox-grist>`
102
74
  }
@@ -111,10 +83,6 @@ export class AnnouncementList extends localize(i18next)(PageView) {
111
83
  super.disconnectedCallback()
112
84
  }
113
85
 
114
- async pageUpdated(changes: any) {
115
- if (this.active && changes.active && this.gristConfig) this.grist?.fetch()
116
- }
117
-
118
86
  async pageInitialized() {
119
87
  hasPrivilege({ category: 'announcement', privilege: 'mutation', domainOwnerGranted: true }).then(writer => {
120
88
  this.writer = !!writer
@@ -128,6 +96,23 @@ export class AnnouncementList extends localize(i18next)(PageView) {
128
96
  emptyNote: { title: t('announcement.text.empty'), description: t('announcement.text.empty-description') },
129
97
  list: { fields: ['title', 'readerState'], details: ['category', 'publishedAt'] },
130
98
  columns: [
99
+ /* Current or past - a filter of its own, on no column shown; the list is always one of the two. */
100
+ {
101
+ type: 'string',
102
+ name: 'period',
103
+ header: t('announcement.text.period'),
104
+ hidden: true,
105
+ record: { editable: false },
106
+ filter: {
107
+ type: 'select',
108
+ operator: 'eq',
109
+ value: 'current',
110
+ options: [
111
+ { value: 'current', display: t('announcement.text.period-current') },
112
+ { value: 'past', display: t('announcement.text.period-past') }
113
+ ]
114
+ }
115
+ },
131
116
  {
132
117
  type: 'string',
133
118
  name: 'pinned',
@@ -177,7 +162,7 @@ export class AnnouncementList extends localize(i18next)(PageView) {
177
162
  }
178
163
 
179
164
  private isPast() {
180
- return this.period === 'past'
165
+ return announcementPeriodOf(this.grist?.filters) === 'past'
181
166
  }
182
167
 
183
168
  async fetchHandler({ page = 1, limit = 50, filters = [], search }: FetchOption) {
@@ -191,7 +176,7 @@ export class AnnouncementList extends localize(i18next)(PageView) {
191
176
  }
192
177
  `,
193
178
  /* The period is the reader's own filter - the assistant narrows the same list the same way. */
194
- variables: { filters: [...filters, { name: 'period', operator: 'eq', value: this.period }], pagination: { page, limit }, search: search?.trim() || undefined },
179
+ variables: { filters: [...filters.filter(one => one.name !== 'period'), { name: 'period', operator: 'eq', value: announcementPeriodOf(filters) }], pagination: { page, limit }, search: search?.trim() || undefined },
195
180
  fetchPolicy: 'network-only'
196
181
  })
197
182
  if (response.errors?.length) throw response
@@ -0,0 +1,8 @@
1
+ /*
2
+ * The announcement list's query as its grid keeps it (FOOTER-BUTTON-REVIEW G09). Pure - no imports, so a test holds it.
3
+ */
4
+
5
+ /** The period the grid's `period` filter names - past, else current (a cleared choice is the current ones). Pure. */
6
+ export function announcementPeriodOf(filters: readonly { name: string; value?: any }[] | undefined): 'current' | 'past' {
7
+ return filters?.find(one => one.name === 'period')?.value === 'past' ? 'past' : 'current'
8
+ }
@@ -1 +1,2 @@
1
1
  export { generateAnnouncementBadge, refreshAnnouncementBadge } from './utils/announcement-badge.js';
2
+ export { AudiencePicker } from './components/audience-picker.js';
@@ -1,2 +1,3 @@
1
1
  export { generateAnnouncementBadge, refreshAnnouncementBadge } from './utils/announcement-badge.js';
2
+ export { AudiencePicker } from './components/audience-picker.js';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA","sourcesContent":["export { generateAnnouncementBadge, refreshAnnouncementBadge } from './utils/announcement-badge.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA","sourcesContent":["export { generateAnnouncementBadge, refreshAnnouncementBadge } from './utils/announcement-badge.js'\nexport { AudiencePicker } from './components/audience-picker.js'\n"]}
@@ -1,8 +1,6 @@
1
1
  import '@material/web/icon/icon.js';
2
2
  import '@operato/data-grist/ox-grist.js';
3
3
  import '@operato/data-grist/ox-filters-form.js';
4
- import '@operato/input/ox-select.js';
5
- import '@operato/popup/ox-popup-list.js';
6
4
  import { FetchOption } from '@operato/data-grist';
7
5
  import { PageView } from '@operato/shell';
8
6
  declare const AnnouncementList_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
@@ -13,7 +11,6 @@ declare const AnnouncementList_base: (new (...args: any[]) => import("lit").LitE
13
11
  export declare class AnnouncementList extends AnnouncementList_base {
14
12
  static styles: import("lit").CSSResult[];
15
13
  gristConfig: any;
16
- period: 'current' | 'past';
17
14
  writer: boolean;
18
15
  private grist;
19
16
  private onChanged;
@@ -43,7 +40,6 @@ export declare class AnnouncementList extends AnnouncementList_base {
43
40
  render(): import("lit-html").TemplateResult<1>;
44
41
  connectedCallback(): void;
45
42
  disconnectedCallback(): void;
46
- pageUpdated(changes: any): Promise<void>;
47
43
  pageInitialized(): Promise<void>;
48
44
  private isPast;
49
45
  fetchHandler({ page, limit, filters, search }: FetchOption): Promise<{
@@ -2,10 +2,8 @@ import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
3
  import '@operato/data-grist/ox-grist.js';
4
4
  import '@operato/data-grist/ox-filters-form.js';
5
- import '@operato/input/ox-select.js';
6
- import '@operato/popup/ox-popup-list.js';
7
5
  import gql from 'graphql-tag';
8
- import { css, html } from 'lit';
6
+ import { html } from 'lit';
9
7
  import { customElement, query, state } from 'lit/decorators.js';
10
8
  import { DataGrist } from '@operato/data-grist';
11
9
  import { client } from '@operato/graphql';
@@ -15,6 +13,7 @@ import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePage
15
13
  import { isMobileDevice } from '@operato/utils';
16
14
  import { hasPrivilege } from '@things-factory/auth-base/dist-client';
17
15
  import { LIST_FIELDS } from '../utils/announcement-api.js';
16
+ import { announcementPeriodOf } from '../utils/announcement-list-query.js';
18
17
  import { CATEGORIES, categoryWord, importanceWord, readerStateWord, t, when } from '../utils/announcement-words.js';
19
18
  /**
20
19
  * 공지 — the announcements addressed to the person: the current ones, pinned, urgent and important first, or the past
@@ -23,7 +22,6 @@ import { CATEGORIES, categoryWord, importanceWord, readerStateWord, t, when } fr
23
22
  let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView) {
24
23
  constructor() {
25
24
  super(...arguments);
26
- this.period = 'current';
27
25
  /* A writer manages and writes from here - the menu offers one entry, and a reader sees no group of one. */
28
26
  this.writer = false;
29
27
  this.onChanged = () => this.grist?.fetch();
@@ -32,18 +30,7 @@ let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView
32
30
  WorkSurfacePageStyles,
33
31
  CommonGristStyles,
34
32
  CommonHeaderStyles,
35
- ScrollbarStyles,
36
- css `
37
- .filters {
38
- display: flex;
39
- flex-wrap: wrap;
40
- align-items: center;
41
- gap: var(--spacing-medium, 8px);
42
- }
43
- ox-select {
44
- min-width: 140px;
45
- }
46
- `
33
+ ScrollbarStyles
47
34
  ]; }
48
35
  get context() {
49
36
  return {
@@ -67,30 +54,14 @@ let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView
67
54
  : []
68
55
  };
69
56
  }
57
+ /*
58
+ * The period, the category, search and page are the grid's own, kept in the address (FOOTER-BUTTON-REVIEW G09): a
59
+ * shared link, coming back and reloading read the same list, and a change of them reads page 1 again.
60
+ */
70
61
  render() {
71
- const periods = [
72
- { value: 'current', display: t('announcement.text.period-current') },
73
- { value: 'past', display: t('announcement.text.period-past') }
74
- ];
75
- return html `<ox-grist class="page-fill" search-mode="term" .mode=${isMobileDevice() ? 'CARD' : 'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
62
+ return html `<ox-grist class="page-fill" search-mode="term" .mode=${isMobileDevice() ? 'CARD' : 'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${this.active}>
76
63
  <div slot="headroom" class="header">
77
- <div class="filters">
78
- <ox-select
79
- .value=${this.period}
80
- aria-label=${t('announcement.text.period')}
81
- @change=${(e) => {
82
- const next = e.detail === 'past' ? 'past' : 'current';
83
- if (next === this.period)
84
- return;
85
- this.period = next;
86
- this.grist.fetch();
87
- }}
88
- >
89
- <span slot="label">${periods.find(one => one.value === this.period)?.display}</span>
90
- <ox-popup-list align-left nowrap with-search>${periods.map(one => html `<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>
91
- </ox-select>
92
- <ox-filters-form without-search autofocus></ox-filters-form>
93
- </div>
64
+ <div class="filters"><ox-filters-form without-search autofocus></ox-filters-form></div>
94
65
  </div>
95
66
  </ox-grist>`;
96
67
  }
@@ -102,10 +73,6 @@ let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView
102
73
  window.removeEventListener('announcements-changed', this.onChanged);
103
74
  super.disconnectedCallback();
104
75
  }
105
- async pageUpdated(changes) {
106
- if (this.active && changes.active && this.gristConfig)
107
- this.grist?.fetch();
108
- }
109
76
  async pageInitialized() {
110
77
  hasPrivilege({ category: 'announcement', privilege: 'mutation', domainOwnerGranted: true }).then(writer => {
111
78
  this.writer = !!writer;
@@ -119,6 +86,23 @@ let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView
119
86
  emptyNote: { title: t('announcement.text.empty'), description: t('announcement.text.empty-description') },
120
87
  list: { fields: ['title', 'readerState'], details: ['category', 'publishedAt'] },
121
88
  columns: [
89
+ /* Current or past - a filter of its own, on no column shown; the list is always one of the two. */
90
+ {
91
+ type: 'string',
92
+ name: 'period',
93
+ header: t('announcement.text.period'),
94
+ hidden: true,
95
+ record: { editable: false },
96
+ filter: {
97
+ type: 'select',
98
+ operator: 'eq',
99
+ value: 'current',
100
+ options: [
101
+ { value: 'current', display: t('announcement.text.period-current') },
102
+ { value: 'past', display: t('announcement.text.period-past') }
103
+ ]
104
+ }
105
+ },
122
106
  {
123
107
  type: 'string',
124
108
  name: 'pinned',
@@ -165,7 +149,7 @@ let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView
165
149
  };
166
150
  }
167
151
  isPast() {
168
- return this.period === 'past';
152
+ return announcementPeriodOf(this.grist?.filters) === 'past';
169
153
  }
170
154
  async fetchHandler({ page = 1, limit = 50, filters = [], search }) {
171
155
  const response = await client.query({
@@ -178,7 +162,7 @@ let AnnouncementList = class AnnouncementList extends localize(i18next)(PageView
178
162
  }
179
163
  `,
180
164
  /* The period is the reader's own filter - the assistant narrows the same list the same way. */
181
- variables: { filters: [...filters, { name: 'period', operator: 'eq', value: this.period }], pagination: { page, limit }, search: search?.trim() || undefined },
165
+ variables: { filters: [...filters.filter(one => one.name !== 'period'), { name: 'period', operator: 'eq', value: announcementPeriodOf(filters) }], pagination: { page, limit }, search: search?.trim() || undefined },
182
166
  fetchPolicy: 'network-only'
183
167
  });
184
168
  if (response.errors?.length)
@@ -190,10 +174,6 @@ __decorate([
190
174
  state(),
191
175
  __metadata("design:type", Object)
192
176
  ], AnnouncementList.prototype, "gristConfig", void 0);
193
- __decorate([
194
- state(),
195
- __metadata("design:type", String)
196
- ], AnnouncementList.prototype, "period", void 0);
197
177
  __decorate([
198
178
  state(),
199
179
  __metadata("design:type", Object)
@@ -1 +1 @@
1
- {"version":3,"file":"announcement-list.js","sourceRoot":"","sources":["../../client/pages/announcement-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { hasPrivilege } from '@things-factory/auth-base/dist-client'\n\nimport { LIST_FIELDS } from '../utils/announcement-api.js'\nimport { CATEGORIES, categoryWord, importanceWord, readerStateWord, t, when } from '../utils/announcement-words.js'\n\n/**\n * 공지 — the announcements addressed to the person: the current ones, pinned, urgent and important first, or the past\n * ones (ADR-0163 decision 5). Those not read yet are bold; a row opens the announcement.\n */\n@customElement('announcement-list')\nexport class AnnouncementList extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n ScrollbarStyles,\n css`\n .filters {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n }\n ox-select {\n min-width: 140px;\n }\n `\n ]\n\n @state() gristConfig: any\n @state() period: 'current' | 'past' = 'current'\n /* A writer manages and writes from here - the menu offers one entry, and a reader sees no group of one. */\n @state() writer = false\n @query('ox-grist') private grist!: DataGrist\n\n private onChanged = () => this.grist?.fetch()\n\n get context() {\n return {\n title: t('announcement.title.list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: this.writer\n ? [\n { title: t('announcement.title.manage'), icon: 'edit_note', action: () => navigate('announcement-manage-list') },\n { title: t('announcement.button.new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('announcement-editor') }\n ]\n : []\n }\n }\n\n render() {\n const periods = [\n { value: 'current', display: t('announcement.text.period-current') },\n { value: 'past', display: t('announcement.text.period-past') }\n ]\n return html`<ox-grist class=\"page-fill\" search-mode=\"term\" .mode=${isMobileDevice() ? 'CARD' : 'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-select\n .value=${this.period}\n aria-label=${t('announcement.text.period')}\n @change=${(e: CustomEvent) => {\n const next = e.detail === 'past' ? 'past' : 'current'\n if (next === this.period) return\n this.period = next\n this.grist.fetch()\n }}\n >\n <span slot=\"label\">${periods.find(one => one.value === this.period)?.display}</span>\n <ox-popup-list align-left nowrap with-search>${periods.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>\n <ox-filters-form without-search autofocus></ox-filters-form>\n </div>\n </div>\n </ox-grist>`\n }\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('announcements-changed', this.onChanged)\n }\n\n disconnectedCallback() {\n window.removeEventListener('announcements-changed', this.onChanged)\n super.disconnectedCallback()\n }\n\n async pageUpdated(changes: any) {\n if (this.active && changes.active && this.gristConfig) this.grist?.fetch()\n }\n\n async pageInitialized() {\n hasPrivilege({ category: 'announcement', privilege: 'mutation', domainOwnerGranted: true }).then(writer => {\n this.writer = !!writer\n this.updateContext()\n })\n const open = (record: any) => record?.id && navigate(`announcement-view?id=${record.id}`)\n const owed = (record: any) => record?.readerState === 'unread' || record?.readerState === 'to-acknowledge'\n this.gristConfig = {\n rows: { appendable: false, selectable: false, handlers: { click: (_c: any, _d: any, _col: any, record: any) => open(record) } },\n pagination: { limit: 50, pages: [50, 100] },\n emptyNote: { title: t('announcement.text.empty'), description: t('announcement.text.empty-description') },\n list: { fields: ['title', 'readerState'], details: ['category', 'publishedAt'] },\n columns: [\n {\n type: 'string',\n name: 'pinned',\n header: '',\n width: 34,\n record: {\n editable: false,\n renderer: (_v: any, _c: any, record: any) =>\n record?.pinned && !this.isPast()\n ? html`<md-icon style=\"--md-icon-size:16px\" title=${t('announcement.field.pinned')}>push_pin</md-icon>`\n : record?.importance === 'URGENT'\n ? html`<md-icon style=\"--md-icon-size:16px;color:var(--md-sys-color-error)\" title=${importanceWord('URGENT')}>priority_high</md-icon>`\n : ''\n }\n },\n {\n type: 'string',\n name: 'category',\n header: t('announcement.field.category'),\n width: 90,\n record: { editable: false, renderer: (value: string) => categoryWord(value) },\n filter: { type: 'select', operator: 'eq', options: [{ display: '', value: '' }, ...CATEGORIES.map(code => ({ display: categoryWord(code), value: code }))] }\n },\n {\n type: 'string',\n name: 'title',\n header: t('announcement.field.title'),\n width: 320,\n record: {\n editable: false,\n renderer: (value: string, _c: any, record: any) =>\n html`<span style=${owed(record) ? 'font-weight:600' : ''}>${record?.importance === 'IMPORTANT' ? `[${importanceWord('IMPORTANT')}] ` : ''}${value}</span>`\n }\n },\n {\n type: 'string',\n name: 'readerState',\n header: t('announcement.field.reader-state'),\n width: 100,\n record: { editable: false, renderer: (value: string) => html`<span style=${value === 'unread' || value === 'to-acknowledge' ? 'color:var(--md-sys-color-primary);font-weight:600' : ''}>${readerStateWord(value)}</span>` }\n },\n { type: 'string', name: 'publisher', header: t('announcement.field.publisher'), width: 110, record: { editable: false, renderer: (value: any) => value?.name ?? '' } },\n { type: 'string', name: 'publishedAt', header: t('announcement.field.published-at'), width: 110, record: { editable: false, renderer: (value: string) => when(value, false) } },\n { type: 'string', name: 'endsAt', header: t('announcement.field.ends-at'), width: 110, record: { editable: false, renderer: (value: string) => when(value, false) } }\n ]\n }\n }\n\n private isPast() {\n return this.period === 'past'\n }\n\n async fetchHandler({ page = 1, limit = 50, filters = [], search }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $search: String) {\n responses: announcements(filters: $filters, pagination: $pagination, search: $search) {\n items { ${LIST_FIELDS} }\n total\n }\n }\n `,\n /* The period is the reader's own filter - the assistant narrows the same list the same way. */\n variables: { filters: [...filters, { name: 'period', operator: 'eq', value: this.period }], pagination: { page, limit }, search: search?.trim() || undefined },\n fetchPolicy: 'network-only'\n })\n if (response.errors?.length) throw response\n return { total: response.data.responses.total, records: response.data.responses.items }\n }\n}\n"]}
1
+ {"version":3,"file":"announcement-list.js","sourceRoot":"","sources":["../../client/pages/announcement-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\n\nimport gql from 'graphql-tag'\nimport { html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { hasPrivilege } from '@things-factory/auth-base/dist-client'\n\nimport { LIST_FIELDS } from '../utils/announcement-api.js'\nimport { announcementPeriodOf } from '../utils/announcement-list-query.js'\nimport { CATEGORIES, categoryWord, importanceWord, readerStateWord, t, when } from '../utils/announcement-words.js'\n\n/**\n * 공지 — the announcements addressed to the person: the current ones, pinned, urgent and important first, or the past\n * ones (ADR-0163 decision 5). Those not read yet are bold; a row opens the announcement.\n */\n@customElement('announcement-list')\nexport class AnnouncementList extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n ScrollbarStyles\n ]\n\n @state() gristConfig: any\n /* A writer manages and writes from here - the menu offers one entry, and a reader sees no group of one. */\n @state() writer = false\n @query('ox-grist') private grist!: DataGrist\n\n private onChanged = () => this.grist?.fetch()\n\n get context() {\n return {\n title: t('announcement.title.list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: this.writer\n ? [\n { title: t('announcement.title.manage'), icon: 'edit_note', action: () => navigate('announcement-manage-list') },\n { title: t('announcement.button.new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('announcement-editor') }\n ]\n : []\n }\n }\n\n /*\n * The period, the category, search and page are the grid's own, kept in the address (FOOTER-BUTTON-REVIEW G09): a\n * shared link, coming back and reloading read the same list, and a change of them reads page 1 again.\n */\n render() {\n return html`<ox-grist class=\"page-fill\" search-mode=\"term\" .mode=${isMobileDevice() ? 'CARD' : 'GRID'} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)} ?url-params-sensitive=${this.active}>\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\"><ox-filters-form without-search autofocus></ox-filters-form></div>\n </div>\n </ox-grist>`\n }\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('announcements-changed', this.onChanged)\n }\n\n disconnectedCallback() {\n window.removeEventListener('announcements-changed', this.onChanged)\n super.disconnectedCallback()\n }\n\n async pageInitialized() {\n hasPrivilege({ category: 'announcement', privilege: 'mutation', domainOwnerGranted: true }).then(writer => {\n this.writer = !!writer\n this.updateContext()\n })\n const open = (record: any) => record?.id && navigate(`announcement-view?id=${record.id}`)\n const owed = (record: any) => record?.readerState === 'unread' || record?.readerState === 'to-acknowledge'\n this.gristConfig = {\n rows: { appendable: false, selectable: false, handlers: { click: (_c: any, _d: any, _col: any, record: any) => open(record) } },\n pagination: { limit: 50, pages: [50, 100] },\n emptyNote: { title: t('announcement.text.empty'), description: t('announcement.text.empty-description') },\n list: { fields: ['title', 'readerState'], details: ['category', 'publishedAt'] },\n columns: [\n /* Current or past - a filter of its own, on no column shown; the list is always one of the two. */\n {\n type: 'string',\n name: 'period',\n header: t('announcement.text.period'),\n hidden: true,\n record: { editable: false },\n filter: {\n type: 'select',\n operator: 'eq',\n value: 'current',\n options: [\n { value: 'current', display: t('announcement.text.period-current') },\n { value: 'past', display: t('announcement.text.period-past') }\n ]\n }\n },\n {\n type: 'string',\n name: 'pinned',\n header: '',\n width: 34,\n record: {\n editable: false,\n renderer: (_v: any, _c: any, record: any) =>\n record?.pinned && !this.isPast()\n ? html`<md-icon style=\"--md-icon-size:16px\" title=${t('announcement.field.pinned')}>push_pin</md-icon>`\n : record?.importance === 'URGENT'\n ? html`<md-icon style=\"--md-icon-size:16px;color:var(--md-sys-color-error)\" title=${importanceWord('URGENT')}>priority_high</md-icon>`\n : ''\n }\n },\n {\n type: 'string',\n name: 'category',\n header: t('announcement.field.category'),\n width: 90,\n record: { editable: false, renderer: (value: string) => categoryWord(value) },\n filter: { type: 'select', operator: 'eq', options: [{ display: '', value: '' }, ...CATEGORIES.map(code => ({ display: categoryWord(code), value: code }))] }\n },\n {\n type: 'string',\n name: 'title',\n header: t('announcement.field.title'),\n width: 320,\n record: {\n editable: false,\n renderer: (value: string, _c: any, record: any) =>\n html`<span style=${owed(record) ? 'font-weight:600' : ''}>${record?.importance === 'IMPORTANT' ? `[${importanceWord('IMPORTANT')}] ` : ''}${value}</span>`\n }\n },\n {\n type: 'string',\n name: 'readerState',\n header: t('announcement.field.reader-state'),\n width: 100,\n record: { editable: false, renderer: (value: string) => html`<span style=${value === 'unread' || value === 'to-acknowledge' ? 'color:var(--md-sys-color-primary);font-weight:600' : ''}>${readerStateWord(value)}</span>` }\n },\n { type: 'string', name: 'publisher', header: t('announcement.field.publisher'), width: 110, record: { editable: false, renderer: (value: any) => value?.name ?? '' } },\n { type: 'string', name: 'publishedAt', header: t('announcement.field.published-at'), width: 110, record: { editable: false, renderer: (value: string) => when(value, false) } },\n { type: 'string', name: 'endsAt', header: t('announcement.field.ends-at'), width: 110, record: { editable: false, renderer: (value: string) => when(value, false) } }\n ]\n }\n }\n\n private isPast() {\n return announcementPeriodOf(this.grist?.filters) === 'past'\n }\n\n async fetchHandler({ page = 1, limit = 50, filters = [], search }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $search: String) {\n responses: announcements(filters: $filters, pagination: $pagination, search: $search) {\n items { ${LIST_FIELDS} }\n total\n }\n }\n `,\n /* The period is the reader's own filter - the assistant narrows the same list the same way. */\n variables: { filters: [...filters.filter(one => one.name !== 'period'), { name: 'period', operator: 'eq', value: announcementPeriodOf(filters) }], pagination: { page, limit }, search: search?.trim() || undefined },\n fetchPolicy: 'network-only'\n })\n if (response.errors?.length) throw response\n return { total: response.data.responses.total, records: response.data.responses.items }\n }\n}\n"]}