@things-factory/notification 10.1.7 → 10.1.10

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.
@@ -5,12 +5,9 @@ export declare class NotificationItem extends LitElement {
5
5
  type?: string;
6
6
  notification: any;
7
7
  target?: string;
8
- detail?: {
9
- message: string;
10
- [key: string]: any;
11
- };
12
8
  newbie?: boolean;
9
+ private copied;
13
10
  render(): import("lit-html").TemplateResult<1>;
11
+ private copyTechnical;
14
12
  updated(changed: any): void;
15
- decipherErrorCode(): Promise<void>;
16
13
  }
@@ -1,9 +1,9 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
- import gql from 'graphql-tag';
4
3
  import { LitElement, html, css } from 'lit';
5
- import { customElement, property } from 'lit/decorators.js';
6
- import { client } from '@operato/graphql';
4
+ import { customElement, property, state } from 'lit/decorators.js';
5
+ import { i18next } from '@operato/i18n';
6
+ import { ScrollbarStyles } from '@operato/styles';
7
7
  function isOriginSameAsLocation(url) {
8
8
  function defaultPort(protocol) {
9
9
  return { 'http:': 80, 'https:': 443 }[protocol];
@@ -25,42 +25,54 @@ function isOriginSameAsLocation(url) {
25
25
  console.warn(err, url);
26
26
  }
27
27
  }
28
+ /* 이전 호출부가 message에 HTTP/GraphQL 원문을 넣은 경우에도, 이력에서는 진단 정보로 취급한다. */
29
+ function isTechnicalError(type, value) {
30
+ if (type !== 'ERROR' || typeof value !== 'string')
31
+ return false;
32
+ return /^(\[\s*\d{3}\s*:|(?:Cannot query|Response not successful:)|Error:)/.test(value) ||
33
+ /\n\s*at\s+.+\(.+\)/.test(value);
34
+ }
28
35
  let NotificationItem = class NotificationItem extends LitElement {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.copied = false;
39
+ }
29
40
  static { this.styles = [
41
+ ScrollbarStyles,
30
42
  css `
31
43
  :host {
44
+ display: block;
32
45
  position: relative;
33
- background-color: var(--md-sys-color-surface);
34
- padding: var(--spacing-medium);
35
- border-left: 0 solid transparent;
36
- border-bottom: 1px solid var(--md-sys-color-outline-variant) !important;
37
- transition:
38
- border-left 200ms ease-in-out,
39
- padding-left 200ms ease-in-out;
46
+ padding: 12px var(--spacing-medium);
47
+ border-bottom: 1px solid var(--md-sys-color-outline-variant);
48
+ transition: background-color 120ms ease;
40
49
  color: var(--md-sys-color-on-surface);
41
50
 
42
- --type-dot-size: 9px;
51
+ --type-dot-size: 8px;
43
52
  }
44
53
 
45
54
  :host([newbie]) {
46
- background-color: var(--md-sys-color-surface-variant);
55
+ background-color: var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-variant));
47
56
  }
48
57
 
49
58
  :host(:hover) {
50
- padding-left: 0.5rem;
51
- border-left: 0.2rem solid var(--status-info-color);
59
+ background-color: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface-variant));
52
60
  }
53
61
 
54
62
  [titler] {
55
- white-space: normal;
63
+ display: -webkit-box;
64
+ -webkit-box-orient: vertical;
65
+ -webkit-line-clamp: 2;
56
66
  overflow: hidden;
57
- text-overflow: ellipsis;
58
- font-size: var(--fontsize-large);
59
- font-weight: bold;
60
- color: var(--md-sys-color-secondary);
67
+ padding-right: 24px;
68
+ font-family: var(--md-sys-typescale-title-small-font, var(--theme-font, inherit));
69
+ font-size: var(--md-sys-typescale-title-small-size, 0.875rem);
70
+ line-height: var(--md-sys-typescale-title-small-line-height, 1.25rem);
71
+ font-weight: var(--md-sys-typescale-title-small-weight, 500);
72
+ color: var(--md-sys-color-on-surface);
61
73
  }
62
74
 
63
- [titler] span {
75
+ [titler] > span {
64
76
  display: inline-block;
65
77
  width: var(--type-dot-size);
66
78
  height: var(--type-dot-size);
@@ -74,61 +86,73 @@ let NotificationItem = class NotificationItem extends LitElement {
74
86
 
75
87
  [close] {
76
88
  position: absolute;
77
- top: 13px;
78
- right: 0;
79
- font-size: var(--fontsize-large);
89
+ top: 12px;
90
+ right: 12px;
91
+ --md-icon-size: 18px;
80
92
  opacity: 0.5;
81
93
  cursor: pointer;
82
94
  }
83
95
  [close]:hover {
84
96
  opacity: 1;
85
97
  }
86
- [detail] {
87
- padding: var(--spacing-small) var(--spacing-medium);
88
- border-radius: var(--border-radius);
89
- font-size: 0.85em;
90
- }
91
- span.more {
92
- margin-left: 16px;
93
- float: right;
94
- padding: 0px var(--spacing-small) 2px var(--spacing-small);
95
- border-radius: var(--border-radius);
96
- font-size: 0.8em;
97
- color: var(--md-sys-color-on-primary);
98
- --md-icon-size: 14px;
99
- }
100
- span.more * {
101
- vertical-align: middle;
98
+ [technical] {
99
+ position: relative;
100
+ margin-top: var(--spacing-small);
101
+ padding-right: 32px;
102
+ color: var(--md-sys-color-on-surface-variant);
103
+ font-family: var(--md-sys-typescale-label-small-font, var(--theme-font, inherit));
104
+ font-size: var(--md-sys-typescale-label-small-size, 0.75rem);
105
+ line-height: var(--md-sys-typescale-label-small-line-height, 1rem);
106
+ font-weight: var(--md-sys-typescale-label-small-weight, 400);
102
107
  }
103
-
104
- :host([type='ERROR']) span {
105
- background-color: var(--status-danger-color);
108
+ [technical] summary {
109
+ cursor: pointer;
106
110
  }
107
- :host([type='ERROR']) {
108
- border-color: var(--status-danger-color);
111
+ [technical] button {
112
+ position: absolute;
113
+ top: -4px;
114
+ right: 0;
115
+ display: inline-flex;
116
+ align-items: center;
117
+ justify-content: center;
118
+ width: 28px;
119
+ height: 28px;
120
+ padding: 0;
121
+ border: 0;
122
+ border-radius: 50%;
123
+ background: transparent;
124
+ color: var(--md-sys-color-on-surface-variant);
125
+ cursor: pointer;
109
126
  }
110
- :host([type='ERROR']) [detail] {
111
- border: 1px solid rgba(241, 53, 63, 0.5);
112
- background-color: rgba(241, 53, 63, 0.1);
127
+ [technical] button:hover {
128
+ background: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface-variant));
113
129
  }
114
- :host([type='WARN']) span {
115
- background-color: var(--status-warning-color);
130
+ [technical] button md-icon {
131
+ --md-icon-size: 16px;
116
132
  }
117
- :host([type='WARN']) {
118
- border-color: var(--status-warning-color);
133
+ [technical] pre {
134
+ margin: var(--spacing-small) 0 0;
135
+ padding: var(--spacing-small);
136
+ max-height: 160px;
137
+ overflow: auto;
138
+ border-radius: var(--md-sys-shape-corner-small, 4px);
139
+ background: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface-variant));
140
+ font: inherit;
141
+ white-space: pre-wrap;
142
+ overflow-wrap: anywhere;
119
143
  }
120
- :host([type='SUCCESS']) span {
121
- background-color: var(--status-success-color);
144
+ :host([type='ERROR']) [titler] > span {
145
+ background-color: var(--status-danger-color);
122
146
  }
123
- :host([type='SUCCESS']) {
124
- border-color: var(--status-success-color);
147
+ :host([type='WARN']) [titler] > span {
148
+ background-color: var(--status-warning-color);
125
149
  }
126
- :host([type='INFO']) span,
127
- :host span {
128
- background-color: var(--status-info-color);
150
+ :host([type='SUCCESS']) [titler] > span {
151
+ background-color: var(--status-success-color);
129
152
  }
130
- :host([type='INFO']) {
131
- border-color: var(--status-info-color);
153
+ :host([type='INFO']) [titler] > span,
154
+ [titler] > span {
155
+ background-color: var(--status-info-color);
132
156
  }
133
157
 
134
158
  img {
@@ -138,30 +162,41 @@ let NotificationItem = class NotificationItem extends LitElement {
138
162
  }
139
163
 
140
164
  [message] {
141
- font-size: var(--fontsize-default);
142
- color: var(--md-sys-color-secondary);
165
+ margin-top: var(--spacing-small);
166
+ font-family: var(--md-sys-typescale-body-medium-font, var(--theme-font, inherit));
167
+ font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
168
+ line-height: var(--md-sys-typescale-body-medium-line-height, 1.25rem);
169
+ font-weight: var(--md-sys-typescale-body-medium-weight, 400);
170
+ color: var(--md-sys-color-on-surface-variant);
143
171
  }
144
172
 
145
173
  [timestamp] {
174
+ margin-top: var(--spacing-small);
146
175
  white-space: nowrap;
147
- font-size: var(--fontsize-small);
176
+ font-family: var(--md-sys-typescale-label-small-font, var(--theme-font, inherit));
177
+ font-size: var(--md-sys-typescale-label-small-size, 0.75rem);
178
+ line-height: var(--md-sys-typescale-label-small-line-height, 1rem);
179
+ font-weight: var(--md-sys-typescale-label-small-weight, 400);
148
180
  color: var(--md-sys-color-on-surface-variant);
149
181
  }
150
182
  `
151
183
  ]; }
152
184
  render() {
153
- const { title, url, image, timestamp, body } = this.notification;
185
+ const { title, url, image, timestamp, body, ex } = this.notification;
154
186
  const target = this.target;
155
- const detail = this.detail;
156
- const type = this.type;
187
+ const legacyTechnical = isTechnicalError(this.type, title);
188
+ const displayTitle = legacyTechnical
189
+ ? i18next.t('text.request failed', { defaultValue: 'Request failed' })
190
+ : title;
191
+ const technical = typeof ex === 'string' ? ex : legacyTechnical ? title : '';
157
192
  return html `
158
- <div titler>
193
+ <div titler title=${displayTitle}>
159
194
  <span></span>
160
195
  ${url
161
196
  ? target
162
- ? html `<a href=${url} target=${target}>${title}</a>`
163
- : html `<a href=${url}>${title}</a>`
164
- : title}
197
+ ? html `<a href=${url} target=${target}>${displayTitle}</a>`
198
+ : html `<a href=${url}>${displayTitle}</a>`
199
+ : displayTitle}
165
200
  </div>
166
201
  <md-icon close @click=${e => this.dispatchEvent(new CustomEvent('close'))}>close</md-icon>
167
202
 
@@ -173,20 +208,42 @@ let NotificationItem = class NotificationItem extends LitElement {
173
208
  : html `<img src=${image} />`
174
209
  : html ``}
175
210
  <div message>${body}</div>
176
- ${type == 'ERROR'
177
- ? html `<div
178
- @click=${() => {
179
- this.decipherErrorCode();
180
- }}
181
- >
182
- <span class="more"><md-icon>expand_circle_down</md-icon> more</span>
183
- </div>`
211
+ ${technical
212
+ ? html `<details technical>
213
+ <summary>${i18next.t('text.technical detail', { defaultValue: 'Technical details' })}</summary>
214
+ <button
215
+ title=${i18next.t('button.copy', { defaultValue: 'Copy' })}
216
+ aria-label=${i18next.t('button.copy', { defaultValue: 'Copy' })}
217
+ @click=${event => this.copyTechnical(event, technical)}
218
+ >
219
+ <md-icon>${this.copied ? 'check' : 'content_copy'}</md-icon>
220
+ </button>
221
+ <pre>${technical}</pre>
222
+ </details>`
184
223
  : html ``}
185
- ${detail ? html `<div detail>${detail.message}</div>` : html ``}
186
224
 
187
225
  <div timestamp>${new Date(Number(timestamp)).toLocaleString()}</div>
188
226
  `;
189
227
  }
228
+ async copyTechnical(event, technical) {
229
+ event.preventDefault();
230
+ event.stopPropagation();
231
+ try {
232
+ await navigator.clipboard.writeText(technical);
233
+ }
234
+ catch {
235
+ const textarea = document.createElement('textarea');
236
+ textarea.value = technical;
237
+ textarea.style.position = 'fixed';
238
+ textarea.style.opacity = '0';
239
+ document.body.append(textarea);
240
+ textarea.select();
241
+ document.execCommand('copy');
242
+ textarea.remove();
243
+ }
244
+ this.copied = true;
245
+ window.setTimeout(() => (this.copied = false), 1500);
246
+ }
190
247
  updated(changed) {
191
248
  if (!this.notification?.confirmed) {
192
249
  this.setAttribute('newbie', '');
@@ -197,32 +254,6 @@ let NotificationItem = class NotificationItem extends LitElement {
197
254
  const url = this.notification?.url;
198
255
  this.target = url && !isOriginSameAsLocation(url) && '_blank';
199
256
  }
200
- async decipherErrorCode() {
201
- if (this.type != 'ERROR' || !this.notification) {
202
- return;
203
- }
204
- const { title, body } = this.notification;
205
- var code = `${title}`;
206
- if (body) {
207
- code += `: ${body}`;
208
- }
209
- const response = await client.query({
210
- query: gql `
211
- query ($input: CodeDecipherInput!) {
212
- decipherErrorCode(input: $input) {
213
- message
214
- }
215
- }
216
- `,
217
- variables: {
218
- input: {
219
- code,
220
- system: ''
221
- }
222
- }
223
- });
224
- this.detail = response.data.decipherErrorCode;
225
- }
226
257
  };
227
258
  __decorate([
228
259
  property({ type: String, reflect: true }),
@@ -236,14 +267,14 @@ __decorate([
236
267
  property({ type: String }),
237
268
  __metadata("design:type", String)
238
269
  ], NotificationItem.prototype, "target", void 0);
239
- __decorate([
240
- property({ type: Object }),
241
- __metadata("design:type", Object)
242
- ], NotificationItem.prototype, "detail", void 0);
243
270
  __decorate([
244
271
  property({ type: Boolean }),
245
272
  __metadata("design:type", Boolean)
246
273
  ], NotificationItem.prototype, "newbie", void 0);
274
+ __decorate([
275
+ state(),
276
+ __metadata("design:type", Object)
277
+ ], NotificationItem.prototype, "copied", void 0);
247
278
  NotificationItem = __decorate([
248
279
  customElement('notification-item')
249
280
  ], NotificationItem);
@@ -1 +1 @@
1
- {"version":3,"file":"notification-item.js","sourceRoot":"","sources":["../../client/viewparts/notification-item.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport gql from 'graphql-tag'\nimport { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { client } from '@operato/graphql'\n\nfunction isOriginSameAsLocation(url) {\n function defaultPort(protocol) {\n return { 'http:': 80, 'https:': 443 }[protocol]\n }\n\n function portOf(location) {\n return location.port || defaultPort(location.protocol || pageLocation.protocol)\n }\n\n try {\n var pageLocation = window.location\n var urlparts = new URL(url, pageLocation.href)\n\n return !!(\n urlparts.protocol &&\n urlparts.protocol == pageLocation.protocol &&\n urlparts.host &&\n urlparts.host == pageLocation.host &&\n urlparts.host &&\n portOf(urlparts) == portOf(pageLocation)\n )\n } catch (err) {\n console.warn(err, url)\n }\n}\n\n@customElement('notification-item')\nexport class NotificationItem extends LitElement {\n static styles = [\n css`\n :host {\n position: relative;\n background-color: var(--md-sys-color-surface);\n padding: var(--spacing-medium);\n border-left: 0 solid transparent;\n border-bottom: 1px solid var(--md-sys-color-outline-variant) !important;\n transition:\n border-left 200ms ease-in-out,\n padding-left 200ms ease-in-out;\n color: var(--md-sys-color-on-surface);\n\n --type-dot-size: 9px;\n }\n\n :host([newbie]) {\n background-color: var(--md-sys-color-surface-variant);\n }\n\n :host(:hover) {\n padding-left: 0.5rem;\n border-left: 0.2rem solid var(--status-info-color);\n }\n\n [titler] {\n white-space: normal;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--fontsize-large);\n font-weight: bold;\n color: var(--md-sys-color-secondary);\n }\n\n [titler] span {\n display: inline-block;\n width: var(--type-dot-size);\n height: var(--type-dot-size);\n border-radius: 50%;\n margin-right: var(--spacing-small);\n margin-bottom: var(--spacing-tiny);\n }\n [titler] * {\n vertical-align: middle;\n }\n\n [close] {\n position: absolute;\n top: 13px;\n right: 0;\n font-size: var(--fontsize-large);\n opacity: 0.5;\n cursor: pointer;\n }\n [close]:hover {\n opacity: 1;\n }\n [detail] {\n padding: var(--spacing-small) var(--spacing-medium);\n border-radius: var(--border-radius);\n font-size: 0.85em;\n }\n span.more {\n margin-left: 16px;\n float: right;\n padding: 0px var(--spacing-small) 2px var(--spacing-small);\n border-radius: var(--border-radius);\n font-size: 0.8em;\n color: var(--md-sys-color-on-primary);\n --md-icon-size: 14px;\n }\n span.more * {\n vertical-align: middle;\n }\n\n :host([type='ERROR']) span {\n background-color: var(--status-danger-color);\n }\n :host([type='ERROR']) {\n border-color: var(--status-danger-color);\n }\n :host([type='ERROR']) [detail] {\n border: 1px solid rgba(241, 53, 63, 0.5);\n background-color: rgba(241, 53, 63, 0.1);\n }\n :host([type='WARN']) span {\n background-color: var(--status-warning-color);\n }\n :host([type='WARN']) {\n border-color: var(--status-warning-color);\n }\n :host([type='SUCCESS']) span {\n background-color: var(--status-success-color);\n }\n :host([type='SUCCESS']) {\n border-color: var(--status-success-color);\n }\n :host([type='INFO']) span,\n :host span {\n background-color: var(--status-info-color);\n }\n :host([type='INFO']) {\n border-color: var(--status-info-color);\n }\n\n img {\n display: block;\n max-width: 100%;\n margin: auto;\n }\n\n [message] {\n font-size: var(--fontsize-default);\n color: var(--md-sys-color-secondary);\n }\n\n [timestamp] {\n white-space: nowrap;\n font-size: var(--fontsize-small);\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n ]\n\n @property({ type: String, reflect: true }) type?: string\n @property({ type: Object }) notification: any\n @property({ type: String }) target?: string\n @property({ type: Object }) detail?: { message: string; [key: string]: any }\n @property({ type: Boolean }) newbie?: boolean\n\n render() {\n const { title, url, image, timestamp, body } = this.notification\n const target = this.target\n const detail = this.detail\n const type = this.type\n\n return html`\n <div titler>\n <span></span>\n ${url\n ? target\n ? html`<a href=${url} target=${target}>${title}</a>`\n : html`<a href=${url}>${title}</a>`\n : title}\n </div>\n <md-icon close @click=${e => this.dispatchEvent(new CustomEvent('close'))}>close</md-icon>\n\n ${image\n ? url\n ? target\n ? html`<a href=${url} target=${target}><img src=${image} /></a>`\n : html`<a href=${url}><img src=${image} /></a>`\n : html`<img src=${image} />`\n : html``}\n <div message>${body}</div>\n ${type == 'ERROR'\n ? html`<div\n @click=${() => {\n this.decipherErrorCode()\n }}\n >\n <span class=\"more\"><md-icon>expand_circle_down</md-icon> more</span>\n </div>`\n : html``}\n ${detail ? html`<div detail>${detail.message}</div>` : html``}\n\n <div timestamp>${new Date(Number(timestamp)).toLocaleString()}</div>\n `\n }\n\n updated(changed) {\n if (!this.notification?.confirmed) {\n this.setAttribute('newbie', '')\n } else {\n this.removeAttribute('newbie')\n }\n\n const url = this.notification?.url\n this.target = url && !isOriginSameAsLocation(url) && '_blank'\n }\n\n async decipherErrorCode() {\n if (this.type != 'ERROR' || !this.notification) {\n return\n }\n\n const { title, body } = this.notification\n var code = `${title}`\n if (body) {\n code += `: ${body}`\n }\n\n const response = await client.query({\n query: gql`\n query ($input: CodeDecipherInput!) {\n decipherErrorCode(input: $input) {\n message\n }\n }\n `,\n variables: {\n input: {\n code,\n system: ''\n }\n }\n })\n\n this.detail = response.data.decipherErrorCode\n }\n}\n"]}
1
+ {"version":3,"file":"notification-item.js","sourceRoot":"","sources":["../../client/viewparts/notification-item.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { LitElement, html, css } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { i18next } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nfunction isOriginSameAsLocation(url) {\n function defaultPort(protocol) {\n return { 'http:': 80, 'https:': 443 }[protocol]\n }\n\n function portOf(location) {\n return location.port || defaultPort(location.protocol || pageLocation.protocol)\n }\n\n try {\n var pageLocation = window.location\n var urlparts = new URL(url, pageLocation.href)\n\n return !!(\n urlparts.protocol &&\n urlparts.protocol == pageLocation.protocol &&\n urlparts.host &&\n urlparts.host == pageLocation.host &&\n urlparts.host &&\n portOf(urlparts) == portOf(pageLocation)\n )\n } catch (err) {\n console.warn(err, url)\n }\n}\n\n/* 이전 호출부가 message에 HTTP/GraphQL 원문을 넣은 경우에도, 이력에서는 진단 정보로 취급한다. */\nfunction isTechnicalError(type: string | undefined, value: unknown) {\n if (type !== 'ERROR' || typeof value !== 'string') return false\n\n return /^(\\[\\s*\\d{3}\\s*:|(?:Cannot query|Response not successful:)|Error:)/.test(value) ||\n /\\n\\s*at\\s+.+\\(.+\\)/.test(value)\n}\n\n@customElement('notification-item')\nexport class NotificationItem extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n position: relative;\n padding: 12px var(--spacing-medium);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n transition: background-color 120ms ease;\n color: var(--md-sys-color-on-surface);\n\n --type-dot-size: 8px;\n }\n\n :host([newbie]) {\n background-color: var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-variant));\n }\n\n :host(:hover) {\n background-color: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface-variant));\n }\n\n [titler] {\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n overflow: hidden;\n padding-right: 24px;\n font-family: var(--md-sys-typescale-title-small-font, var(--theme-font, inherit));\n font-size: var(--md-sys-typescale-title-small-size, 0.875rem);\n line-height: var(--md-sys-typescale-title-small-line-height, 1.25rem);\n font-weight: var(--md-sys-typescale-title-small-weight, 500);\n color: var(--md-sys-color-on-surface);\n }\n\n [titler] > span {\n display: inline-block;\n width: var(--type-dot-size);\n height: var(--type-dot-size);\n border-radius: 50%;\n margin-right: var(--spacing-small);\n margin-bottom: var(--spacing-tiny);\n }\n [titler] * {\n vertical-align: middle;\n }\n\n [close] {\n position: absolute;\n top: 12px;\n right: 12px;\n --md-icon-size: 18px;\n opacity: 0.5;\n cursor: pointer;\n }\n [close]:hover {\n opacity: 1;\n }\n [technical] {\n position: relative;\n margin-top: var(--spacing-small);\n padding-right: 32px;\n color: var(--md-sys-color-on-surface-variant);\n font-family: var(--md-sys-typescale-label-small-font, var(--theme-font, inherit));\n font-size: var(--md-sys-typescale-label-small-size, 0.75rem);\n line-height: var(--md-sys-typescale-label-small-line-height, 1rem);\n font-weight: var(--md-sys-typescale-label-small-weight, 400);\n }\n [technical] summary {\n cursor: pointer;\n }\n [technical] button {\n position: absolute;\n top: -4px;\n right: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n background: transparent;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n [technical] button:hover {\n background: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface-variant));\n }\n [technical] button md-icon {\n --md-icon-size: 16px;\n }\n [technical] pre {\n margin: var(--spacing-small) 0 0;\n padding: var(--spacing-small);\n max-height: 160px;\n overflow: auto;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface-variant));\n font: inherit;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n }\n :host([type='ERROR']) [titler] > span {\n background-color: var(--status-danger-color);\n }\n :host([type='WARN']) [titler] > span {\n background-color: var(--status-warning-color);\n }\n :host([type='SUCCESS']) [titler] > span {\n background-color: var(--status-success-color);\n }\n :host([type='INFO']) [titler] > span,\n [titler] > span {\n background-color: var(--status-info-color);\n }\n\n img {\n display: block;\n max-width: 100%;\n margin: auto;\n }\n\n [message] {\n margin-top: var(--spacing-small);\n font-family: var(--md-sys-typescale-body-medium-font, var(--theme-font, inherit));\n font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);\n line-height: var(--md-sys-typescale-body-medium-line-height, 1.25rem);\n font-weight: var(--md-sys-typescale-body-medium-weight, 400);\n color: var(--md-sys-color-on-surface-variant);\n }\n\n [timestamp] {\n margin-top: var(--spacing-small);\n white-space: nowrap;\n font-family: var(--md-sys-typescale-label-small-font, var(--theme-font, inherit));\n font-size: var(--md-sys-typescale-label-small-size, 0.75rem);\n line-height: var(--md-sys-typescale-label-small-line-height, 1rem);\n font-weight: var(--md-sys-typescale-label-small-weight, 400);\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n ]\n\n @property({ type: String, reflect: true }) type?: string\n @property({ type: Object }) notification: any\n @property({ type: String }) target?: string\n @property({ type: Boolean }) newbie?: boolean\n @state() private copied = false\n\n render() {\n const { title, url, image, timestamp, body, ex } = this.notification\n const target = this.target\n const legacyTechnical = isTechnicalError(this.type, title)\n const displayTitle = legacyTechnical\n ? i18next.t('text.request failed', { defaultValue: 'Request failed' })\n : title\n const technical = typeof ex === 'string' ? ex : legacyTechnical ? title : ''\n\n return html`\n <div titler title=${displayTitle}>\n <span></span>\n ${url\n ? target\n ? html`<a href=${url} target=${target}>${displayTitle}</a>`\n : html`<a href=${url}>${displayTitle}</a>`\n : displayTitle}\n </div>\n <md-icon close @click=${e => this.dispatchEvent(new CustomEvent('close'))}>close</md-icon>\n\n ${image\n ? url\n ? target\n ? html`<a href=${url} target=${target}><img src=${image} /></a>`\n : html`<a href=${url}><img src=${image} /></a>`\n : html`<img src=${image} />`\n : html``}\n <div message>${body}</div>\n ${technical\n ? html`<details technical>\n <summary>${i18next.t('text.technical detail', { defaultValue: 'Technical details' })}</summary>\n <button\n title=${i18next.t('button.copy', { defaultValue: 'Copy' })}\n aria-label=${i18next.t('button.copy', { defaultValue: 'Copy' })}\n @click=${event => this.copyTechnical(event, technical)}\n >\n <md-icon>${this.copied ? 'check' : 'content_copy'}</md-icon>\n </button>\n <pre>${technical}</pre>\n </details>`\n : html``}\n\n <div timestamp>${new Date(Number(timestamp)).toLocaleString()}</div>\n `\n }\n\n private async copyTechnical(event: Event, technical: string) {\n event.preventDefault()\n event.stopPropagation()\n\n try {\n await navigator.clipboard.writeText(technical)\n } catch {\n const textarea = document.createElement('textarea')\n textarea.value = technical\n textarea.style.position = 'fixed'\n textarea.style.opacity = '0'\n document.body.append(textarea)\n textarea.select()\n document.execCommand('copy')\n textarea.remove()\n }\n\n this.copied = true\n window.setTimeout(() => (this.copied = false), 1500)\n }\n\n updated(changed) {\n if (!this.notification?.confirmed) {\n this.setAttribute('newbie', '')\n } else {\n this.removeAttribute('newbie')\n }\n\n const url = this.notification?.url\n this.target = url && !isOriginSameAsLocation(url) && '_blank'\n }\n\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import '@material/web/icon/icon.js';
2
- import '@material/web/button/elevated-button.js';
2
+ import '@material/web/button/text-button.js';
3
3
  import './notification-item';
4
4
  import { LitElement } from 'lit';
5
5
  declare const NotificationList_base: (new (...args: any[]) => LitElement) & typeof LitElement;
@@ -1,6 +1,6 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
- import '@material/web/button/elevated-button.js';
3
+ import '@material/web/button/text-button.js';
4
4
  import './notification-item';
5
5
  import { LitElement, html, css } from 'lit';
6
6
  import { customElement, property } from 'lit/decorators.js';
@@ -16,34 +16,41 @@ let NotificationList = class NotificationList extends localize(i18next)(LitEleme
16
16
  css `
17
17
  :host {
18
18
  display: block;
19
- background-color: var(--md-sys-color-surface);
20
- box-shadow: var(--box-shadow);
21
- margin-right: var(--spacing-large);
22
- padding: var(--spacing-medium);
23
19
  max-height: 100%;
24
20
  overflow-x: hidden;
25
21
  overflow-y: auto;
22
+ background-color: var(--md-sys-color-surface, #ffffff);
23
+ color: var(--md-sys-color-on-surface);
26
24
  }
27
25
 
28
26
  [notifications-wrap] {
29
27
  display: flex;
30
28
  flex-direction: column;
31
29
  justify-content: flex-start;
30
+ background-color: var(--md-sys-color-surface, #ffffff);
32
31
  }
33
- [notifications-wrap] div {
34
- align-items: stretch;
35
- border-bottom: 1px solid var(--md-sys-color-primary);
32
+ [header] {
33
+ position: sticky;
34
+ top: 0;
35
+ z-index: 1;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: space-between;
39
+ min-height: 48px;
40
+ padding: 0 var(--spacing-medium);
41
+ background-color: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface, #ffffff));
42
+ border-bottom: 1px solid var(--md-sys-color-outline-variant);
36
43
  }
37
- [notifications-wrap] strong {
38
- color: var(--md-sys-color-primary);
39
- text-transform: capitalize;
40
- line-height: 2;
44
+ [header] strong {
45
+ font-family: var(--md-sys-typescale-title-small-font, var(--theme-font, inherit));
46
+ font-size: var(--md-sys-typescale-title-small-size, 0.875rem);
47
+ line-height: var(--md-sys-typescale-title-small-line-height, 1.25rem);
48
+ font-weight: var(--md-sys-typescale-title-small-weight, 600);
49
+ color: var(--md-sys-color-on-surface);
41
50
  }
42
- [notifications-wrap] md-elevated-button {
43
- --md-elevated-button-container-height: 24px;
44
- float: right;
45
- padding-inline-start: 6px;
46
- padding-inline-end: 12px;
51
+ [header] md-text-button {
52
+ --md-text-button-container-height: 32px;
53
+ --md-text-button-label-text-size: 0.8125rem;
47
54
  }
48
55
  [no-notifications] {
49
56
  margin: 0;
@@ -53,7 +60,7 @@ let NotificationList = class NotificationList extends localize(i18next)(LitEleme
53
60
  font-weight: bold;
54
61
  color: var(--md-sys-color-secondary);
55
62
  }
56
- div md-icon {
63
+ [no-notifications] md-icon {
57
64
  display: block;
58
65
  opacity: 0.3;
59
66
  }
@@ -66,14 +73,15 @@ let NotificationList = class NotificationList extends localize(i18next)(LitEleme
66
73
  `
67
74
  ]; }
68
75
  render() {
69
- var history = this.history.reverse();
76
+ /* reverse()는 store에서 받은 배열 자체를 뒤집는다. 렌더링만 최신순으로 보인다. */
77
+ const history = [...this.history].reverse();
70
78
  return history.length > 0
71
79
  ? html `
72
80
  <div notifications-wrap>
73
- <div>
81
+ <div header>
74
82
  <strong>${i18next.t('label.notification list')}</strong>
75
- <md-elevated-button outlined dense @click=${e => this.onclearall()}
76
- ><md-icon slot="icon">delete_outline</md-icon>${String(i18next.t('label.clear all'))}</md-elevated-button
83
+ <md-text-button @click=${e => this.onclearall()}
84
+ ><md-icon slot="icon">delete_outline</md-icon>${String(i18next.t('label.clear all'))}</md-text-button
77
85
  >
78
86
  </div>
79
87
  ${history.map(notification => html `
@@ -1 +1 @@
1
- {"version":3,"file":"notification-list.js","sourceRoot":"","sources":["../../client/viewparts/notification-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport './notification-item'\n\nimport { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { store, notificationStore } from '@operato/shell'\nimport { i18next, localize } from '@operato/i18n'\nimport { UPDATE_NOTIFICATION } from '../actions/notification-fcm'\n\n@customElement('notification-list')\nexport class NotificationList extends localize(i18next)(LitElement) {\n static styles = [\n css`\n :host {\n display: block;\n background-color: var(--md-sys-color-surface);\n box-shadow: var(--box-shadow);\n margin-right: var(--spacing-large);\n padding: var(--spacing-medium);\n max-height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n }\n\n [notifications-wrap] {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n }\n [notifications-wrap] div {\n align-items: stretch;\n border-bottom: 1px solid var(--md-sys-color-primary);\n }\n [notifications-wrap] strong {\n color: var(--md-sys-color-primary);\n text-transform: capitalize;\n line-height: 2;\n }\n [notifications-wrap] md-elevated-button {\n --md-elevated-button-container-height: 24px;\n float: right;\n padding-inline-start: 6px;\n padding-inline-end: 12px;\n }\n [no-notifications] {\n margin: 0;\n padding: var(--spacing-large);\n text-align: center;\n font-size: var(--fontsize-default);\n font-weight: bold;\n color: var(--md-sys-color-secondary);\n }\n div md-icon {\n display: block;\n opacity: 0.3;\n }\n @media screen and (max-width: 480px) {\n :host {\n height: 100%;\n width: 100vw;\n }\n }\n `\n ]\n\n @property({ type: Array }) history: any[] = []\n\n render() {\n var history = this.history.reverse()\n\n return history.length > 0\n ? html`\n <div notifications-wrap>\n <div>\n <strong>${i18next.t('label.notification list')}</strong>\n <md-elevated-button outlined dense @click=${e => this.onclearall()}\n ><md-icon slot=\"icon\">delete_outline</md-icon>${String(\n i18next.t('label.clear all')\n )}</md-elevated-button\n >\n </div>\n ${history.map(\n notification => html`\n <notification-item\n @close=${e => {\n this.onClose(notification)\n }}\n .type=${notification.type}\n .notification=${notification}\n ></notification-item>\n `\n )}\n </div>\n `\n : html`\n <div no-notifications @click=${e => window.history.back()}>\n <md-icon>notifications_off</md-icon>${i18next.t('text.no notification available')}\n </div>\n `\n }\n\n onClose(notification) {\n const { id } = notification\n\n store.dispatch((async dispatch => {\n if (notification) {\n await notificationStore.delete(id)\n }\n\n const history = await notificationStore.getAll()\n\n dispatch({\n type: UPDATE_NOTIFICATION,\n history: [...history]\n })\n }) as any)\n }\n\n onclearall() {\n store.dispatch((async dispatch => {\n await notificationStore.clear()\n const history = await notificationStore.getAll()\n\n dispatch({\n type: UPDATE_NOTIFICATION,\n history: [...history]\n })\n }) as any)\n }\n\n private _unsubscribe?: () => void\n\n\n private _applyState() {\n\n const __state__ = store.getState() as any\n this.history = __state__.notification.history\n\n }\n\n\n connectedCallback() {\n\n super.connectedCallback()\n\n this._applyState()\n\n this._unsubscribe = store.subscribe(() => this._applyState())\n\n }\n\n\n async disconnectedCallback() {\n\n super.disconnectedCallback()\n\n this._unsubscribe?.()\n\n await Promise.all(\n this.history\n .filter(notification => !notification.confirmed)\n .map(async notification => {\n return await notificationStore.put({\n ...notification,\n confirmed: true\n })\n })\n )\n\n store.dispatch((async dispatch => {\n const history = await notificationStore.getAll()\n\n dispatch({\n type: UPDATE_NOTIFICATION,\n history: [...history]\n })\n }) as any)\n }\n}\n"]}
1
+ {"version":3,"file":"notification-list.js","sourceRoot":"","sources":["../../client/viewparts/notification-list.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,qCAAqC,CAAA;AAC5C,OAAO,qBAAqB,CAAA;AAE5B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACzD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAG1D,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAA5D;;QA8DsB,YAAO,GAAU,EAAE,CAAA;IAkHhD,CAAC;aA/KQ,WAAM,GAAG;QACd,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyDF;KACF,AA3DY,CA2DZ;IAID,MAAM;QACJ,wDAAwD;QACxD,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;QAE3C,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC;YACvB,CAAC,CAAC,IAAI,CAAA;;;wBAGY,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;uCACrB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE;gEACG,MAAM,CACpD,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAC7B;;;cAGH,OAAO,CAAC,GAAG,CACX,YAAY,CAAC,EAAE,CAAC,IAAI,CAAA;;2BAEP,CAAC,CAAC,EAAE;gBACX,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;YAC5B,CAAC;0BACO,YAAY,CAAC,IAAI;kCACT,YAAY;;eAE/B,CACF;;SAEJ;YACH,CAAC,CAAC,IAAI,CAAA;yCAC6B,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;kDACjB,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;;SAEpF,CAAA;IACP,CAAC;IAED,OAAO,CAAC,YAAY;QAClB,MAAM,EAAE,EAAE,EAAE,GAAG,YAAY,CAAA;QAE3B,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAC,QAAQ,EAAC,EAAE;YAC/B,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YACpC,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAA;YAEhD,QAAQ,CAAC;gBACP,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;aACtB,CAAC,CAAA;QACJ,CAAC,CAAQ,CAAC,CAAA;IACZ,CAAC;IAED,UAAU;QACR,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAC,QAAQ,EAAC,EAAE;YAC/B,MAAM,iBAAiB,CAAC,KAAK,EAAE,CAAA;YAC/B,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAA;YAEhD,QAAQ,CAAC;gBACP,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;aACtB,CAAC,CAAA;QACJ,CAAC,CAAQ,CAAC,CAAA;IACZ,CAAC;IAKO,WAAW;QAEjB,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,EAAS,CAAA;QACzC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,YAAY,CAAC,OAAO,CAAA;IAE/C,CAAC;IAGD,iBAAiB;QAEf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,IAAI,CAAC,WAAW,EAAE,CAAA;QAElB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;IAE/D,CAAC;IAGD,KAAK,CAAC,oBAAoB;QAExB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,YAAY,EAAE,EAAE,CAAA;QAErB,MAAM,OAAO,CAAC,GAAG,CACf,IAAI,CAAC,OAAO;aACT,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC;aAC/C,GAAG,CAAC,KAAK,EAAC,YAAY,EAAC,EAAE;YACxB,OAAO,MAAM,iBAAiB,CAAC,GAAG,CAAC;gBACjC,GAAG,YAAY;gBACf,SAAS,EAAE,IAAI;aAChB,CAAC,CAAA;QACJ,CAAC,CAAC,CACL,CAAA;QAED,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAC,QAAQ,EAAC,EAAE;YAC/B,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAA;YAEhD,QAAQ,CAAC;gBACP,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;aACtB,CAAC,CAAA;QACJ,CAAC,CAAQ,CAAC,CAAA;IACZ,CAAC;;AAjH0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;iDAAoB;AA9DnC,gBAAgB;IAD5B,aAAa,CAAC,mBAAmB,CAAC;GACtB,gBAAgB,CAgL5B","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/text-button.js'\nimport './notification-item'\n\nimport { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { store, notificationStore } from '@operato/shell'\nimport { i18next, localize } from '@operato/i18n'\nimport { UPDATE_NOTIFICATION } from '../actions/notification-fcm'\n\n@customElement('notification-list')\nexport class NotificationList extends localize(i18next)(LitElement) {\n static styles = [\n css`\n :host {\n display: block;\n max-height: 100%;\n overflow-x: hidden;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface, #ffffff);\n color: var(--md-sys-color-on-surface);\n }\n\n [notifications-wrap] {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n background-color: var(--md-sys-color-surface, #ffffff);\n }\n [header] {\n position: sticky;\n top: 0;\n z-index: 1;\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 48px;\n padding: 0 var(--spacing-medium);\n background-color: var(--md-sys-color-surface-container-high, var(--md-sys-color-surface, #ffffff));\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n [header] strong {\n font-family: var(--md-sys-typescale-title-small-font, var(--theme-font, inherit));\n font-size: var(--md-sys-typescale-title-small-size, 0.875rem);\n line-height: var(--md-sys-typescale-title-small-line-height, 1.25rem);\n font-weight: var(--md-sys-typescale-title-small-weight, 600);\n color: var(--md-sys-color-on-surface);\n }\n [header] md-text-button {\n --md-text-button-container-height: 32px;\n --md-text-button-label-text-size: 0.8125rem;\n }\n [no-notifications] {\n margin: 0;\n padding: var(--spacing-large);\n text-align: center;\n font-size: var(--fontsize-default);\n font-weight: bold;\n color: var(--md-sys-color-secondary);\n }\n [no-notifications] md-icon {\n display: block;\n opacity: 0.3;\n }\n @media screen and (max-width: 480px) {\n :host {\n height: 100%;\n width: 100vw;\n }\n }\n `\n ]\n\n @property({ type: Array }) history: any[] = []\n\n render() {\n /* reverse()는 store에서 받은 배열 자체를 뒤집는다. 렌더링만 최신순으로 보인다. */\n const history = [...this.history].reverse()\n\n return history.length > 0\n ? html`\n <div notifications-wrap>\n <div header>\n <strong>${i18next.t('label.notification list')}</strong>\n <md-text-button @click=${e => this.onclearall()}\n ><md-icon slot=\"icon\">delete_outline</md-icon>${String(\n i18next.t('label.clear all')\n )}</md-text-button\n >\n </div>\n ${history.map(\n notification => html`\n <notification-item\n @close=${e => {\n this.onClose(notification)\n }}\n .type=${notification.type}\n .notification=${notification}\n ></notification-item>\n `\n )}\n </div>\n `\n : html`\n <div no-notifications @click=${e => window.history.back()}>\n <md-icon>notifications_off</md-icon>${i18next.t('text.no notification available')}\n </div>\n `\n }\n\n onClose(notification) {\n const { id } = notification\n\n store.dispatch((async dispatch => {\n if (notification) {\n await notificationStore.delete(id)\n }\n\n const history = await notificationStore.getAll()\n\n dispatch({\n type: UPDATE_NOTIFICATION,\n history: [...history]\n })\n }) as any)\n }\n\n onclearall() {\n store.dispatch((async dispatch => {\n await notificationStore.clear()\n const history = await notificationStore.getAll()\n\n dispatch({\n type: UPDATE_NOTIFICATION,\n history: [...history]\n })\n }) as any)\n }\n\n private _unsubscribe?: () => void\n\n\n private _applyState() {\n\n const __state__ = store.getState() as any\n this.history = __state__.notification.history\n\n }\n\n\n connectedCallback() {\n\n super.connectedCallback()\n\n this._applyState()\n\n this._unsubscribe = store.subscribe(() => this._applyState())\n\n }\n\n\n async disconnectedCallback() {\n\n super.disconnectedCallback()\n\n this._unsubscribe?.()\n\n await Promise.all(\n this.history\n .filter(notification => !notification.confirmed)\n .map(async notification => {\n return await notificationStore.put({\n ...notification,\n confirmed: true\n })\n })\n )\n\n store.dispatch((async dispatch => {\n const history = await notificationStore.getAll()\n\n dispatch({\n type: UPDATE_NOTIFICATION,\n history: [...history]\n })\n }) as any)\n }\n}\n"]}