@things-factory/notification 8.0.0 → 9.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist-client/tsconfig.tsbuildinfo +1 -1
  2. package/dist-server/tsconfig.tsbuildinfo +1 -1
  3. package/package.json +9 -9
  4. package/client/actions/notification-fcm.ts +0 -148
  5. package/client/bootstrap.ts +0 -135
  6. package/client/index.ts +0 -6
  7. package/client/pages/notification/notification-list-page.ts +0 -258
  8. package/client/pages/notification-rule/notification-rule-importer.ts +0 -87
  9. package/client/pages/notification-rule/notification-rule-list-page.ts +0 -386
  10. package/client/reducers/notification.ts +0 -27
  11. package/client/route.ts +0 -10
  12. package/client/tsconfig.json +0 -13
  13. package/client/viewparts/notification-badge.ts +0 -54
  14. package/client/viewparts/notification-item.ts +0 -246
  15. package/client/viewparts/notification-list.ts +0 -160
  16. package/client/viewparts/notification-sender.ts +0 -142
  17. package/client/viewparts/notification-setting-let.ts +0 -222
  18. package/docs/images/config-app-1.png +0 -0
  19. package/docs/images/config-app-2.png +0 -0
  20. package/docs/images/config-server-key.png +0 -0
  21. package/docs/images/config-service-account.png +0 -0
  22. package/docs/images/config-vapidkey-1.png +0 -0
  23. package/docs/images/config-vapidkey-2-get-public-key.png +0 -0
  24. package/docs/images/config-vapidkey-3-get-private-key.png +0 -0
  25. package/docs/images/element-notification-badge.png +0 -0
  26. package/docs/images/element-notification-list.png +0 -0
  27. package/docs/images/element-notification-setting-let.png +0 -0
  28. package/docs/images/push-test-on-chrome-1.png +0 -0
  29. package/docs/images/push-test-on-chrome-2.png +0 -0
  30. package/docs/images/push-test-on-firebase-1.png +0 -0
  31. package/docs/images/push-test-on-firebase-2.png +0 -0
  32. package/docs/images/push-test-on-firebase-3.png +0 -0
  33. package/docs/images/push-test-on-firebase-4.png +0 -0
  34. package/server/controllers/fcm.ts +0 -214
  35. package/server/controllers/index.ts +0 -1
  36. package/server/index.ts +0 -5
  37. package/server/middlewares/index.ts +0 -5
  38. package/server/middlewares/notification-middleware.ts +0 -73
  39. package/server/routers/notification-router.ts +0 -67
  40. package/server/routes.ts +0 -11
  41. package/server/service/index.ts +0 -42
  42. package/server/service/notification/directive-notification.ts +0 -71
  43. package/server/service/notification/index.ts +0 -14
  44. package/server/service/notification/notification-mutation.ts +0 -119
  45. package/server/service/notification/notification-query.ts +0 -76
  46. package/server/service/notification/notification-subscription.ts +0 -44
  47. package/server/service/notification/notification-type.ts +0 -55
  48. package/server/service/notification/notification.ts +0 -105
  49. package/server/service/notification-rule/event-subscriber.ts +0 -20
  50. package/server/service/notification-rule/index.ts +0 -9
  51. package/server/service/notification-rule/notification-rule-history.ts +0 -136
  52. package/server/service/notification-rule/notification-rule-mutation.ts +0 -203
  53. package/server/service/notification-rule/notification-rule-query.ts +0 -65
  54. package/server/service/notification-rule/notification-rule-type.ts +0 -71
  55. package/server/service/notification-rule/notification-rule.ts +0 -125
  56. package/server/tsconfig.json +0 -9
@@ -1,246 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
-
3
- import gql from 'graphql-tag'
4
- import { LitElement, html, css } from 'lit'
5
- import { customElement, property } from 'lit/decorators.js'
6
- import { client } from '@operato/graphql'
7
-
8
- function isOriginSameAsLocation(url) {
9
- function defaultPort(protocol) {
10
- return { 'http:': 80, 'https:': 443 }[protocol]
11
- }
12
-
13
- function portOf(location) {
14
- return location.port || defaultPort(location.protocol || pageLocation.protocol)
15
- }
16
-
17
- try {
18
- var pageLocation = window.location
19
- var urlparts = new URL(url, pageLocation.href)
20
-
21
- return !!(
22
- urlparts.protocol &&
23
- urlparts.protocol == pageLocation.protocol &&
24
- urlparts.host &&
25
- urlparts.host == pageLocation.host &&
26
- urlparts.host &&
27
- portOf(urlparts) == portOf(pageLocation)
28
- )
29
- } catch (err) {
30
- console.warn(err, url)
31
- }
32
- }
33
-
34
- @customElement('notification-item')
35
- export class NotificationItem extends LitElement {
36
- static styles = [
37
- css`
38
- :host {
39
- position: relative;
40
- background-color: var(--md-sys-color-surface);
41
- padding: var(--spacing-medium);
42
- border-left: 0 solid transparent;
43
- border-bottom: 1px solid var(--md-sys-color-outline-variant) !important;
44
- transition:
45
- border-left 200ms ease-in-out,
46
- padding-left 200ms ease-in-out;
47
- color: var(--md-sys-color-on-surface);
48
-
49
- --type-dot-size: 9px;
50
- }
51
-
52
- :host([newbie]) {
53
- background-color: var(--md-sys-color-surface-variant);
54
- }
55
-
56
- :host(:hover) {
57
- padding-left: 0.5rem;
58
- border-left: 0.2rem solid var(--status-info-color);
59
- }
60
-
61
- [titler] {
62
- white-space: normal;
63
- overflow: hidden;
64
- text-overflow: ellipsis;
65
- font-size: var(--fontsize-large);
66
- font-weight: bold;
67
- color: var(--md-sys-color-secondary);
68
- }
69
-
70
- [titler] span {
71
- display: inline-block;
72
- width: var(--type-dot-size);
73
- height: var(--type-dot-size);
74
- border-radius: 50%;
75
- margin-right: var(--spacing-small);
76
- margin-bottom: var(--spacing-tiny);
77
- }
78
- [titler] * {
79
- vertical-align: middle;
80
- }
81
-
82
- [close] {
83
- position: absolute;
84
- top: 13px;
85
- right: 0;
86
- font-size: var(--fontsize-large);
87
- opacity: 0.5;
88
- cursor: pointer;
89
- }
90
- [close]:hover {
91
- opacity: 1;
92
- }
93
- [detail] {
94
- padding: var(--spacing-small) var(--spacing-medium);
95
- border-radius: var(--border-radius);
96
- font-size: 0.85em;
97
- }
98
- span.more {
99
- margin-left: 16px;
100
- float: right;
101
- padding: 0px var(--spacing-small) 2px var(--spacing-small);
102
- border-radius: var(--border-radius);
103
- font-size: 0.8em;
104
- color: var(--md-sys-color-on-primary);
105
- --md-icon-size: 14px;
106
- }
107
- span.more * {
108
- vertical-align: middle;
109
- }
110
-
111
- :host([type='ERROR']) span {
112
- background-color: var(--status-danger-color);
113
- }
114
- :host([type='ERROR']) {
115
- border-color: var(--status-danger-color);
116
- }
117
- :host([type='ERROR']) [detail] {
118
- border: 1px solid rgba(241, 53, 63, 0.5);
119
- background-color: rgba(241, 53, 63, 0.1);
120
- }
121
- :host([type='WARN']) span {
122
- background-color: var(--status-warning-color);
123
- }
124
- :host([type='WARN']) {
125
- border-color: var(--status-warning-color);
126
- }
127
- :host([type='SUCCESS']) span {
128
- background-color: var(--status-success-color);
129
- }
130
- :host([type='SUCCESS']) {
131
- border-color: var(--status-success-color);
132
- }
133
- :host([type='INFO']) span,
134
- :host span {
135
- background-color: var(--status-info-color);
136
- }
137
- :host([type='INFO']) {
138
- border-color: var(--status-info-color);
139
- }
140
-
141
- img {
142
- display: block;
143
- max-width: 100%;
144
- margin: auto;
145
- }
146
-
147
- [message] {
148
- font-size: var(--fontsize-default);
149
- color: var(--md-sys-color-secondary);
150
- }
151
-
152
- [timestamp] {
153
- white-space: nowrap;
154
- font-size: var(--fontsize-small);
155
- color: var(--md-sys-color-on-surface-variant);
156
- }
157
- `
158
- ]
159
-
160
- @property({ type: String, reflect: true }) type?: string
161
- @property({ type: Object }) notification: any
162
- @property({ type: String }) target?: string
163
- @property({ type: Object }) detail?: { message: string; [key: string]: any }
164
- @property({ type: Boolean }) newbie?: boolean
165
-
166
- render() {
167
- const { title, url, image, timestamp, body } = this.notification
168
- const target = this.target
169
- const detail = this.detail
170
- const type = this.type
171
-
172
- return html`
173
- <div titler>
174
- <span></span>
175
- ${url
176
- ? target
177
- ? html`<a href=${url} target=${target}>${title}</a>`
178
- : html`<a href=${url}>${title}</a>`
179
- : title}
180
- </div>
181
- <md-icon close @click=${e => this.dispatchEvent(new CustomEvent('close'))}>close</md-icon>
182
-
183
- ${image
184
- ? url
185
- ? target
186
- ? html`<a href=${url} target=${target}><img src=${image} /></a>`
187
- : html`<a href=${url}><img src=${image} /></a>`
188
- : html`<img src=${image} />`
189
- : html``}
190
- <div message>${body}</div>
191
- ${type == 'ERROR'
192
- ? html`<div
193
- @click=${() => {
194
- this.decipherErrorCode()
195
- }}
196
- >
197
- <span class="more"><md-icon>expand_circle_down</md-icon> more</span>
198
- </div>`
199
- : html``}
200
- ${detail ? html`<div detail>${detail.message}</div>` : html``}
201
-
202
- <div timestamp>${new Date(Number(timestamp)).toLocaleString()}</div>
203
- `
204
- }
205
-
206
- updated(changed) {
207
- if (!this.notification?.confirmed) {
208
- this.setAttribute('newbie', '')
209
- } else {
210
- this.removeAttribute('newbie')
211
- }
212
-
213
- const url = this.notification?.url
214
- this.target = url && !isOriginSameAsLocation(url) && '_blank'
215
- }
216
-
217
- async decipherErrorCode() {
218
- if (this.type != 'ERROR' || !this.notification) {
219
- return
220
- }
221
-
222
- const { title, body } = this.notification
223
- var code = `${title}`
224
- if (body) {
225
- code += `: ${body}`
226
- }
227
-
228
- const response = await client.query({
229
- query: gql`
230
- query ($input: CodeDecipherInput!) {
231
- decipherErrorCode(input: $input) {
232
- message
233
- }
234
- }
235
- `,
236
- variables: {
237
- input: {
238
- code,
239
- system: ''
240
- }
241
- }
242
- })
243
-
244
- this.detail = response.data.decipherErrorCode
245
- }
246
- }
@@ -1,160 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
- import '@material/web/button/elevated-button.js'
3
- import './notification-item'
4
-
5
- import { LitElement, html, css } from 'lit'
6
- import { customElement, property } from 'lit/decorators.js'
7
- import { connect } from 'pwa-helpers'
8
- import { store, notificationStore } from '@operato/shell'
9
- import { i18next, localize } from '@operato/i18n'
10
- import { UPDATE_NOTIFICATION } from '../actions/notification-fcm'
11
-
12
- @customElement('notification-list')
13
- export class NotificationList extends connect(store)(localize(i18next)(LitElement)) {
14
- static styles = [
15
- css`
16
- :host {
17
- display: block;
18
- background-color: var(--md-sys-color-surface);
19
- box-shadow: var(--box-shadow);
20
- margin-right: var(--spacing-large);
21
- padding: var(--spacing-medium);
22
- max-height: 100%;
23
- overflow-x: hidden;
24
- overflow-y: auto;
25
- }
26
-
27
- [notifications-wrap] {
28
- display: flex;
29
- flex-direction: column;
30
- justify-content: flex-start;
31
- }
32
- [notifications-wrap] div {
33
- align-items: stretch;
34
- border-bottom: 1px solid var(--md-sys-color-primary);
35
- }
36
- [notifications-wrap] strong {
37
- color: var(--md-sys-color-primary);
38
- text-transform: capitalize;
39
- line-height: 2;
40
- }
41
- [notifications-wrap] md-elevated-button {
42
- --md-elevated-button-container-height: 24px;
43
- float: right;
44
- padding-inline-start: 6px;
45
- padding-inline-end: 12px;
46
- }
47
- [no-notifications] {
48
- margin: 0;
49
- padding: var(--spacing-large);
50
- text-align: center;
51
- font-size: var(--fontsize-default);
52
- font-weight: bold;
53
- color: var(--md-sys-color-secondary);
54
- }
55
- div md-icon {
56
- display: block;
57
- opacity: 0.3;
58
- }
59
- @media screen and (max-width: 480px) {
60
- :host {
61
- height: 100%;
62
- width: 100vw;
63
- }
64
- }
65
- `
66
- ]
67
-
68
- @property({ type: Array }) history: any[] = []
69
-
70
- render() {
71
- var history = this.history.reverse()
72
-
73
- return history.length > 0
74
- ? html`
75
- <div notifications-wrap>
76
- <div>
77
- <strong>${i18next.t('label.notification list')}</strong>
78
- <md-elevated-button outlined dense @click=${e => this.onclearall()}
79
- ><md-icon slot="icon">delete_outline</md-icon>${String(
80
- i18next.t('label.clear all')
81
- )}</md-elevated-button
82
- >
83
- </div>
84
- ${history.map(
85
- notification => html`
86
- <notification-item
87
- @close=${e => {
88
- this.onClose(notification)
89
- }}
90
- .type=${notification.type}
91
- .notification=${notification}
92
- ></notification-item>
93
- `
94
- )}
95
- </div>
96
- `
97
- : html`
98
- <div no-notifications @click=${e => window.history.back()}>
99
- <md-icon>notifications_off</md-icon>${i18next.t('text.no notification available')}
100
- </div>
101
- `
102
- }
103
-
104
- onClose(notification) {
105
- const { id } = notification
106
-
107
- store.dispatch((async dispatch => {
108
- if (notification) {
109
- await notificationStore.delete(id)
110
- }
111
-
112
- const history = await notificationStore.getAll()
113
-
114
- dispatch({
115
- type: UPDATE_NOTIFICATION,
116
- history: [...history]
117
- })
118
- }) as any)
119
- }
120
-
121
- onclearall() {
122
- store.dispatch((async dispatch => {
123
- await notificationStore.clear()
124
- const history = await notificationStore.getAll()
125
-
126
- dispatch({
127
- type: UPDATE_NOTIFICATION,
128
- history: [...history]
129
- })
130
- }) as any)
131
- }
132
-
133
- stateChanged(state) {
134
- this.history = state.notification.history
135
- }
136
-
137
- async disconnectedCallback() {
138
- super.disconnectedCallback()
139
-
140
- await Promise.all(
141
- this.history
142
- .filter(notification => !notification.confirmed)
143
- .map(async notification => {
144
- return await notificationStore.put({
145
- ...notification,
146
- confirmed: true
147
- })
148
- })
149
- )
150
-
151
- store.dispatch((async dispatch => {
152
- const history = await notificationStore.getAll()
153
-
154
- dispatch({
155
- type: UPDATE_NOTIFICATION,
156
- history: [...history]
157
- })
158
- }) as any)
159
- }
160
- }
@@ -1,142 +0,0 @@
1
- import '@material/web/button/elevated-button.js'
2
- import '@material/web/checkbox/checkbox.js'
3
- import '@material/web/textfield/filled-text-field.js'
4
- import '@operato/i18n/ox-i18n.js'
5
-
6
- import { css, html, LitElement } from 'lit'
7
- import { customElement } from 'lit/decorators.js'
8
- import { auth } from '@things-factory/auth-base/dist-client/auth.js'
9
-
10
- import { i18next, localize } from '@operato/i18n'
11
- import { ScrollbarStyles } from '@operato/styles'
12
-
13
- import { notify as webpushNotify } from '../actions/notification-fcm'
14
-
15
- @customElement('notification-sender')
16
- export class NotificationSender extends localize(i18next)(LitElement) {
17
- static styles = [
18
- ScrollbarStyles,
19
- css`
20
- :host {
21
- display: flex;
22
- padding: var(--spacing-large);
23
- background-color: var(--md-sys-color-background);
24
- color: var(--md-sys-color-on-background);
25
- }
26
-
27
- form {
28
- flex: 1;
29
- display: flex;
30
- flex-direction: column;
31
- }
32
-
33
- [content] > * {
34
- margin: var(--spacing-medium);
35
- }
36
-
37
- [content] {
38
- flex: 1;
39
- flex-direction: column;
40
- display: flex;
41
- overflow: auto;
42
- }
43
-
44
- [buttons] {
45
- margin-top: auto;
46
- display: flex;
47
- flex-direction: row-reverse;
48
- }
49
-
50
- [name='body'] {
51
- resize: vertical;
52
- }
53
-
54
- md-elevated-button {
55
- margin-left: var(--spacing-medium);
56
- }
57
-
58
- label {
59
- display: flex;
60
- gap: var(--spacing-medium);
61
- align-items: center;
62
- }
63
-
64
- @media screen and (max-width: 480px) {
65
- :host {
66
- padding: var(--spacing-medium);
67
- }
68
- }
69
- `
70
- ]
71
-
72
- render() {
73
- return html`
74
- <form>
75
- <div content>
76
- <md-filled-text-field
77
- type="text"
78
- name="receivers"
79
- label=${String(i18next.t('field.receivers'))}
80
- placeholder=${auth.credential?.email}
81
- required
82
- ><md-icon slot="leading-icon">account_circle</md-icon></md-filled-text-field
83
- >
84
- <md-filled-text-field type="text" name="title" label=${String(i18next.t('field.title'))} required
85
- ><md-icon slot="leading-icon">notifications_none</md-icon></md-filled-text-field
86
- >
87
-
88
- <md-filled-text-field type="text" name="image" label=${String(i18next.t('field.image'))}
89
- ><md-icon slot="leading-icon">insert_photo</md-icon></md-filled-text-field
90
- >
91
- <md-filled-text-field type="text" name="url" label=${String(i18next.t('field.url'))}
92
- ><md-icon slot="leading-icon">link</md-icon></md-filled-text-field
93
- >
94
- <md-filled-text-field
95
- type="textarea"
96
- name="body"
97
- label=${String(i18next.t('field.body'))}
98
- required
99
- rows="5"
100
- ></md-filled-text-field>
101
- <label>
102
- <md-checkbox name="inappmsg"></md-checkbox>
103
- In-App Message
104
- </label>
105
- </div>
106
-
107
- <div buttons>
108
- <md-elevated-button raised icon="send" @click=${e => this.ontest()}>
109
- <ox-i18n msgid="button.notification-send"> </ox-i18n>
110
- </md-elevated-button>
111
-
112
- <md-elevated-button type="reset" outlined @click=${e => this.onReset()}>
113
- <ox-i18n msgid="button.reset"> </ox-i18n>
114
- </md-elevated-button>
115
- </div>
116
- </form>
117
- `
118
- }
119
-
120
- ontest() {
121
- const [receivers, title, body, image, url] = ['receivers', 'title', 'body', 'image', 'url'].map(
122
- key => (this.renderRoot.querySelector(`[name="${key}"]`)! as any).value
123
- )
124
- const mode = (this.renderRoot.querySelector(`[name="inappmsg"]`)! as any).checked ? 'inapp' : 'background'
125
-
126
- webpushNotify({
127
- receivers,
128
- title,
129
- body,
130
- image,
131
- mode,
132
- url
133
- })
134
- }
135
-
136
- onReset() {
137
- ;['receivers', 'title', 'body', 'image', 'url'].map(
138
- key => ((this.renderRoot.querySelector(`[name="${key}"]`)! as any).value = '')
139
- )
140
- ;(this.renderRoot.querySelector(`[name="inappmsg"]`)! as any).checked = false
141
- }
142
- }