@servicetitan/notifications 41.0.0 → 41.2.0
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/dist/api/notifications.api.d.ts +1 -1
- package/dist/api/notifications.api.d.ts.map +1 -1
- package/dist/api/notifications.api.js.map +1 -1
- package/dist/common.d.ts +1 -1
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js.map +1 -1
- package/dist/components/notifications.d.ts +2 -2
- package/dist/components/notifications.d.ts.map +1 -1
- package/dist/components/notifications.js.map +1 -1
- package/dist/demo/action-button-preview.d.ts +1 -1
- package/dist/demo/action-button-preview.d.ts.map +1 -1
- package/dist/demo/action-button-preview.js.map +1 -1
- package/dist/demo/action-button.d.ts +1 -1
- package/dist/demo/action-button.d.ts.map +1 -1
- package/dist/demo/action-button.js.map +1 -1
- package/dist/demo/basic-preview.d.ts +1 -1
- package/dist/demo/basic-preview.d.ts.map +1 -1
- package/dist/demo/basic-preview.js.map +1 -1
- package/dist/demo/basic.d.ts +1 -1
- package/dist/demo/basic.d.ts.map +1 -1
- package/dist/demo/basic.js.map +1 -1
- package/dist/demo/container.d.ts +3 -3
- package/dist/demo/container.d.ts.map +1 -1
- package/dist/demo/container.js.map +1 -1
- package/dist/demo/duration-preview.d.ts +1 -1
- package/dist/demo/duration-preview.d.ts.map +1 -1
- package/dist/demo/duration-preview.js.map +1 -1
- package/dist/demo/duration.d.ts +1 -1
- package/dist/demo/duration.d.ts.map +1 -1
- package/dist/demo/duration.js.map +1 -1
- package/dist/demo/mock-notifications-api.d.ts +3 -2
- package/dist/demo/mock-notifications-api.d.ts.map +1 -1
- package/dist/demo/mock-notifications-api.js.map +1 -1
- package/dist/demo/multiline-message-preview.d.ts +1 -1
- package/dist/demo/multiline-message-preview.d.ts.map +1 -1
- package/dist/demo/multiline-message-preview.js.map +1 -1
- package/dist/demo/multiline-message.d.ts +1 -1
- package/dist/demo/multiline-message.d.ts.map +1 -1
- package/dist/demo/multiline-message.js.map +1 -1
- package/dist/demo/prevent-duplicates-preview.d.ts +1 -1
- package/dist/demo/prevent-duplicates-preview.d.ts.map +1 -1
- package/dist/demo/prevent-duplicates-preview.js.map +1 -1
- package/dist/demo/prevent-duplicates.d.ts +1 -1
- package/dist/demo/prevent-duplicates.d.ts.map +1 -1
- package/dist/demo/prevent-duplicates.js.map +1 -1
- package/dist/demo/progress-preview.d.ts +1 -1
- package/dist/demo/progress-preview.d.ts.map +1 -1
- package/dist/demo/progress-preview.js.map +1 -1
- package/dist/demo/progress.d.ts +1 -1
- package/dist/demo/progress.d.ts.map +1 -1
- package/dist/demo/progress.js.map +1 -1
- package/dist/demo/server-custom.d.ts +1 -1
- package/dist/demo/server-custom.d.ts.map +1 -1
- package/dist/demo/server-custom.js.map +1 -1
- package/dist/demo/server-default.d.ts +1 -1
- package/dist/demo/server-default.d.ts.map +1 -1
- package/dist/demo/server-default.js.map +1 -1
- package/dist/demo/server-on-load.d.ts +1 -1
- package/dist/demo/server-on-load.d.ts.map +1 -1
- package/dist/demo/server-on-load.js.map +1 -1
- package/dist/demo/status-variations-preview.d.ts +1 -1
- package/dist/demo/status-variations-preview.d.ts.map +1 -1
- package/dist/demo/status-variations-preview.js.map +1 -1
- package/dist/demo/status-variations.d.ts +1 -1
- package/dist/demo/status-variations.d.ts.map +1 -1
- package/dist/demo/status-variations.js.map +1 -1
- package/dist/intercept.d.ts +1 -1
- package/dist/intercept.d.ts.map +1 -1
- package/dist/intercept.js.map +1 -1
- package/dist/notifications-service.d.ts +1 -1
- package/dist/notifications-service.d.ts.map +1 -1
- package/dist/notifications-service.js.map +1 -1
- package/dist/notifications.stories.d.ts.map +1 -1
- package/dist/stores/notifications.store.d.ts +3 -3
- package/dist/stores/notifications.store.d.ts.map +1 -1
- package/dist/stores/notifications.store.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/notifications-service.test.ts +3 -2
- package/src/api/notifications.api.ts +1 -1
- package/src/common.ts +1 -1
- package/src/components/__tests__/notifications.test.tsx +2 -1
- package/src/components/notifications.tsx +4 -10
- package/src/demo/action-button-preview.tsx +1 -1
- package/src/demo/action-button.tsx +1 -1
- package/src/demo/basic-preview.tsx +1 -1
- package/src/demo/basic.tsx +1 -1
- package/src/demo/container.tsx +5 -8
- package/src/demo/duration-preview.tsx +1 -1
- package/src/demo/duration.tsx +1 -1
- package/src/demo/mock-notifications-api.ts +3 -2
- package/src/demo/multiline-message-preview.tsx +1 -1
- package/src/demo/multiline-message.tsx +1 -1
- package/src/demo/prevent-duplicates-preview.tsx +1 -1
- package/src/demo/prevent-duplicates.tsx +1 -1
- package/src/demo/progress-preview.tsx +1 -1
- package/src/demo/progress.tsx +1 -1
- package/src/demo/server-custom.tsx +2 -1
- package/src/demo/server-default.tsx +1 -1
- package/src/demo/server-on-load.tsx +5 -6
- package/src/demo/status-variations-preview.tsx +1 -1
- package/src/demo/status-variations.tsx +1 -1
- package/src/intercept.ts +1 -1
- package/src/notifications-service.ts +2 -1
- package/src/notifications.stories.tsx +2 -1
- package/src/stores/__tests__/notifications.store.test.ts +6 -8
- package/src/stores/notifications.store.ts +10 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status-variations.d.ts","sourceRoot":"","sources":["../../src/demo/status-variations.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"status-variations.d.ts","sourceRoot":"","sources":["../../src/demo/status-variations.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAKhC,eAAO,MAAM,uBAAuB,EAAE,EAErC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/demo/status-variations.tsx"],"sourcesContent":["import { FC } from 'react';\n\nimport { Container } from './container';\nimport { StatusVariationsPreview } from './status-variations-preview';\n\nexport const StatusVariationsExample: FC = () => (\n <Container>{() => <StatusVariationsPreview />}</Container>\n);\n"],"names":["Container","StatusVariationsPreview","StatusVariationsExample"],"mappings":";AAEA,SAASA,SAAS,QAAQ,cAAc;AACxC,SAASC,uBAAuB,QAAQ,8BAA8B;AAEtE,OAAO,MAAMC,0BAA8B,kBACvC,KAACF;kBAAW,kBAAM,KAACC;OACrB"}
|
|
1
|
+
{"version":3,"sources":["../../src/demo/status-variations.tsx"],"sourcesContent":["import type { FC } from 'react';\n\nimport { Container } from './container';\nimport { StatusVariationsPreview } from './status-variations-preview';\n\nexport const StatusVariationsExample: FC = () => (\n <Container>{() => <StatusVariationsPreview />}</Container>\n);\n"],"names":["Container","StatusVariationsPreview","StatusVariationsExample"],"mappings":";AAEA,SAASA,SAAS,QAAQ,cAAc;AACxC,SAASC,uBAAuB,QAAQ,8BAA8B;AAEtE,OAAO,MAAMC,0BAA8B,kBACvC,KAACF;kBAAW,kBAAM,KAACC;OACrB"}
|
package/dist/intercept.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DefaultNotificationOptions, Notification } from './common';
|
|
1
|
+
import type { DefaultNotificationOptions, Notification } from './common';
|
|
2
2
|
export type NotificationInterceptor<T extends Record<keyof any, any> = {}> = (notification: Notification<T>, dismiss: () => void) => Notification<DefaultNotificationOptions> | undefined;
|
|
3
3
|
export declare function intercept<T extends Record<keyof any, any> = {}>(type: string, fn?: NotificationInterceptor<T>): void;
|
|
4
4
|
//# sourceMappingURL=intercept.d.ts.map
|
package/dist/intercept.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intercept.d.ts","sourceRoot":"","sources":["../src/intercept.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"intercept.d.ts","sourceRoot":"","sources":["../src/intercept.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGzE,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,CACzE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,EAC7B,OAAO,EAAE,MAAM,IAAI,KAClB,YAAY,CAAC,0BAA0B,CAAC,GAAG,SAAS,CAAC;AAE1D,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,EAC3D,IAAI,EAAE,MAAM,EACZ,EAAE,CAAC,EAAE,uBAAuB,CAAC,CAAC,CAAC,QAGlC"}
|
package/dist/intercept.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/intercept.ts"],"sourcesContent":["import { DefaultNotificationOptions, Notification } from './common';\nimport { NotificationsStore } from './stores/notifications.store';\n\nexport type NotificationInterceptor<T extends Record<keyof any, any> = {}> = (\n notification: Notification<T>,\n dismiss: () => void\n) => Notification<DefaultNotificationOptions> | undefined;\n\nexport function intercept<T extends Record<keyof any, any> = {}>(\n type: string,\n fn?: NotificationInterceptor<T>\n) {\n NotificationsStore.intercept(type, fn);\n}\n"],"names":["NotificationsStore","intercept","type","fn"],"mappings":"AACA,SAASA,kBAAkB,QAAQ,+BAA+B;AAOlE,OAAO,SAASC,UACZC,IAAY,EACZC,EAA+B;IAE/BH,mBAAmBC,SAAS,CAACC,MAAMC;AACvC"}
|
|
1
|
+
{"version":3,"sources":["../src/intercept.ts"],"sourcesContent":["import type { DefaultNotificationOptions, Notification } from './common';\nimport { NotificationsStore } from './stores/notifications.store';\n\nexport type NotificationInterceptor<T extends Record<keyof any, any> = {}> = (\n notification: Notification<T>,\n dismiss: () => void\n) => Notification<DefaultNotificationOptions> | undefined;\n\nexport function intercept<T extends Record<keyof any, any> = {}>(\n type: string,\n fn?: NotificationInterceptor<T>\n) {\n NotificationsStore.intercept(type, fn);\n}\n"],"names":["NotificationsStore","intercept","type","fn"],"mappings":"AACA,SAASA,kBAAkB,QAAQ,+BAA+B;AAOlE,OAAO,SAASC,UACZC,IAAY,EACZC,EAA+B;IAE/BH,mBAAmBC,SAAS,CAACC,MAAMC;AACvC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DefaultNotificationOptions } from './common';
|
|
1
|
+
import type { DefaultNotificationOptions } from './common';
|
|
2
2
|
import { NotificationsStore } from './stores/notifications.store';
|
|
3
3
|
type OptionsWithoutStatus = Omit<DefaultNotificationOptions, 'status'>;
|
|
4
4
|
export interface INotificationsService {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications-service.d.ts","sourceRoot":"","sources":["../src/notifications-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"notifications-service.d.ts","sourceRoot":"","sources":["../src/notifications-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAG3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,KAAK,oBAAoB,GAAG,IAAI,CAAC,0BAA0B,EAAE,QAAQ,CAAC,CAAC;AAEvE,MAAM,WAAW,qBAAqB;IAClC,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7E,IAAI,CAAC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACvE,OAAO,CAAC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1E,OAAO,CAAC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1E,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3E;AAED,qBACa,oBAAqB,YAAW,qBAAqB;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,kBAAkB;IAElF,UAAU,GAAU,eAAU,mBAE5B;IAEF,IAAI,GAAI,SAAS,0BAA0B,EAAE,oBAAoB,OAAO,UAEtE;IAEF,IAAI,GAAI,SAAS,oBAAoB,EAAE,oBAAoB,OAAO,UAEhE;IAEF,OAAO,GAAI,SAAS,oBAAoB,EAAE,oBAAoB,OAAO,UAEnE;IAEF,OAAO,GAAI,SAAS,oBAAoB,EAAE,oBAAoB,OAAO,UAEnE;IAEF,KAAK,GAAI,SAAS,oBAAoB,EAAE,oBAAoB,OAAO,UAEjE;CACL"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/notifications-service.ts"],"sourcesContent":["import { injectable, inject } from '@servicetitan/react-ioc';\n\nimport { DefaultNotificationOptions
|
|
1
|
+
{"version":3,"sources":["../src/notifications-service.ts"],"sourcesContent":["import { injectable, inject } from '@servicetitan/react-ioc';\n\nimport type { DefaultNotificationOptions } from './common';\nimport { Status } from './common';\n\nimport { NotificationsStore } from './stores/notifications.store';\n\ntype OptionsWithoutStatus = Omit<DefaultNotificationOptions, 'status'>;\n\nexport interface INotificationsService {\n initialize(userId?: number): Promise<void>;\n show(options: DefaultNotificationOptions, preventDuplicates?: boolean): void;\n info(options: OptionsWithoutStatus, preventDuplicates?: boolean): void;\n success(options: OptionsWithoutStatus, preventDuplicates?: boolean): void;\n warning(options: OptionsWithoutStatus, preventDuplicates?: boolean): void;\n error(options: OptionsWithoutStatus, preventDuplicates?: boolean): void;\n}\n\n@injectable()\nexport class NotificationsService implements INotificationsService {\n constructor(@inject(NotificationsStore) private readonly store: NotificationsStore) {}\n\n initialize = async (userId = 0) => {\n await this.store.initialize(userId);\n };\n\n show = (options: DefaultNotificationOptions, preventDuplicates?: boolean) => {\n this.store.add(options, preventDuplicates);\n };\n\n info = (options: OptionsWithoutStatus, preventDuplicates?: boolean) => {\n this.store.add({ ...options, status: Status.Info }, preventDuplicates);\n };\n\n success = (options: OptionsWithoutStatus, preventDuplicates?: boolean) => {\n this.store.add({ ...options, status: Status.Success }, preventDuplicates);\n };\n\n warning = (options: OptionsWithoutStatus, preventDuplicates?: boolean) => {\n this.store.add({ ...options, status: Status.Warning }, preventDuplicates);\n };\n\n error = (options: OptionsWithoutStatus, preventDuplicates?: boolean) => {\n this.store.add({ ...options, status: Status.Error }, preventDuplicates);\n };\n}\n"],"names":["injectable","inject","Status","NotificationsStore","NotificationsService","store","initialize","show","info","success","warning","error","userId","options","preventDuplicates","add","status","Info","Success","Warning","Error"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAASA,UAAU,EAAEC,MAAM,QAAQ,0BAA0B;AAG7D,SAASC,MAAM,QAAQ,WAAW;AAElC,SAASC,kBAAkB,QAAQ,+BAA+B;AAclE,OAAO,MAAMC;IACT,YAAY,AAA6CC,KAAyB,CAAE;;QAEpFC,uBAAAA,cAAAA,KAAAA;QAIAC,uBAAAA,QAAAA,KAAAA;QAIAC,uBAAAA,QAAAA,KAAAA;QAIAC,uBAAAA,WAAAA,KAAAA;QAIAC,uBAAAA,WAAAA,KAAAA;QAIAC,uBAAAA,SAAAA,KAAAA;aAtByDN,QAAAA;aAEzDC,aAAa,OAAOM,SAAS,CAAC;YAC1B,MAAM,IAAI,CAACP,KAAK,CAACC,UAAU,CAACM;QAChC;aAEAL,OAAO,CAACM,SAAqCC;YACzC,IAAI,CAACT,KAAK,CAACU,GAAG,CAACF,SAASC;QAC5B;aAEAN,OAAO,CAACK,SAA+BC;YACnC,IAAI,CAACT,KAAK,CAACU,GAAG,CAAC;gBAAE,GAAGF,OAAO;gBAAEG,QAAQd,OAAOe,IAAI;YAAC,GAAGH;QACxD;aAEAL,UAAU,CAACI,SAA+BC;YACtC,IAAI,CAACT,KAAK,CAACU,GAAG,CAAC;gBAAE,GAAGF,OAAO;gBAAEG,QAAQd,OAAOgB,OAAO;YAAC,GAAGJ;QAC3D;aAEAJ,UAAU,CAACG,SAA+BC;YACtC,IAAI,CAACT,KAAK,CAACU,GAAG,CAAC;gBAAE,GAAGF,OAAO;gBAAEG,QAAQd,OAAOiB,OAAO;YAAC,GAAGL;QAC3D;aAEAH,QAAQ,CAACE,SAA+BC;YACpC,IAAI,CAACT,KAAK,CAACU,GAAG,CAAC;gBAAE,GAAGF,OAAO;gBAAEG,QAAQd,OAAOkB,KAAK;YAAC,GAAGN;QACzD;IAxBqF;AAyBzF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.stories.d.ts","sourceRoot":"","sources":["../src/notifications.stories.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"notifications.stories.d.ts","sourceRoot":"","sources":["../src/notifications.stories.tsx"],"names":[],"mappings":";;;AAkBA,wBAEE;AAEF,eAAO,MAAM,KAAK,+CAAoC,CAAC;AACvD,eAAO,MAAM,gBAAgB,+CAAqD,CAAC;AACnF,eAAO,MAAM,QAAQ,+CAAoC,CAAC;AAC1D,eAAO,MAAM,YAAY,+CAA6C,CAAC;AACvE,eAAO,MAAM,QAAQ,+CAAoC,CAAC;AAC1D,eAAO,MAAM,iBAAiB,+CAAuD,CAAC;AACtF,eAAO,MAAM,gBAAgB,+CAAqD,CAAC;AACnF,eAAO,MAAM,aAAa,+CAA+C,CAAC;AAC1E,eAAO,MAAM,YAAY,+CAA6C,CAAC;AAEvE,eAAO,MAAM,YAAY,+CAAqE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Toaster } from '@servicetitan/anvil2';
|
|
2
|
-
import { ComponentProps } from 'react';
|
|
2
|
+
import type { ComponentProps } from 'react';
|
|
3
3
|
import { NotificationsApi } from '../api/notifications.api';
|
|
4
|
-
import { DefaultNotificationOptions, Notification } from '../common';
|
|
5
|
-
import { NotificationInterceptor } from '../intercept';
|
|
4
|
+
import type { DefaultNotificationOptions, Notification } from '../common';
|
|
5
|
+
import type { NotificationInterceptor } from '../intercept';
|
|
6
6
|
import type { NotificationsChannel } from '../notifications-channel';
|
|
7
7
|
type NavigateCallback = (path: string) => void;
|
|
8
8
|
type ToastEvent = Parameters<NonNullable<ComponentProps<typeof Toaster>['onToastEvent']>>[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.store.d.ts","sourceRoot":"","sources":["../../src/stores/notifications.store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"notifications.store.d.ts","sourceRoot":"","sources":["../../src/stores/notifications.store.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAM5C,OAAO,EACH,gBAAgB,EAEnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,0BAA0B,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAmBrE,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAI/C,KAAK,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,cAAc,CAAC,OAAO,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7F,qBACa,kBAAkB;;IAce,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAGxE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IAhB1C,MAAM,CAAC,QAAQ,CAAC,YAAY,uCAA8C;IAE1E,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAE7C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyC;IACvE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAyC;gBAKlB,gBAAgB,CAAC,EAAE,gBAAgB,YAAA,EAGzE,oBAAoB,CAAC,EAAE,oBAAoB,YAAA;IAMhE,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,uBAAuB;IAQ3D,OAAO,KAAK,SAAS,GAEpB;IAED,IAAI,QAAQ,IAAI,gBAAgB,GAAG,SAAS,CAE3C;IAED,IAAI,QAAQ,CAAC,EAAE,EAAE,gBAAgB,EAEhC;IAED,UAAU,GAAU,QAAQ,MAAM,mBAoBhC;IAEF,OAAO,aAQL;IAGF,GAAG,GAAI,SAAS,0BAA0B,EAAE,oBAAoB,OAAO,UA2BrE;IAGF,IAAI,GAAI,cAAc,YAAY,UAsBhC;IAEF,YAAY,GAAI,YAAY,UAAU,UAQpC;IAGF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAU/B;IAEF,OAAO,CAAC,0BAA0B;IAQlC,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,oBAAoB;IA0B5B,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,UAAU;CASrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/stores/notifications.store.ts"],"sourcesContent":["import { toast, toastProps, Toaster } from '@servicetitan/anvil2';\nimport { injectable, inject, optional } from '@servicetitan/react-ioc';\nimport { action, runInAction, comparer, makeObservable } from 'mobx';\nimport { ComponentProps } from 'react';\n\nimport {\n DefaultServerNotificationPayload,\n NotificationsApi,\n Notification as ServerNotification,\n NotificationProcessStatus as ServerNotificationStatus,\n} from '../api/notifications.api';\nimport { DefaultNotificationOptions, Notification, Status, isLinkAction, isNewer } from '../common';\nimport { NotificationInterceptor } from '../intercept';\nimport type { NotificationsChannel } from '../notifications-channel';\nimport { NOTIFICATIONS_CHANNEL_TOKEN } from '../notifications-channel';\nimport { dateFromString } from '../utils/date-from-string';\n\nconst EVENT_NAME = 'NotificationEvent';\nconst CLIENT_NOTIFICATION_TYPE = 'ClientNotification';\nconst CLIENT_NOTIFICATION_VERSION = 1;\nconst DAY_INTERVAL = 24 * 60 * 60 * 1000;\n\ninterface ClosedNotification {\n status: ServerNotificationStatus;\n timestamp: number;\n}\n\ninterface ClientNotification extends Notification<DefaultNotificationOptions> {\n toastId?: string;\n toastActive?: boolean;\n}\n\ntype NavigateCallback = (path: string) => void;\n\ntype ToastMethod = 'info' | 'success' | 'warning' | 'danger';\n\ntype ToastEvent = Parameters<NonNullable<ComponentProps<typeof Toaster>['onToastEvent']>>[0];\n\n@injectable()\nexport class NotificationsStore {\n static readonly interceptors = new Map<string, NotificationInterceptor>();\n\n private index = -1;\n private userId = 0;\n private intervalId?: number;\n private readonly timers: Map<number, number>;\n\n private readonly notifications = new Map<number, ClientNotification>();\n private readonly closedNotifications = new Map<number, ClosedNotification>();\n\n #navigate?: NavigateCallback;\n\n constructor(\n @inject(NotificationsApi) @optional() private readonly notificationsApi?: NotificationsApi,\n @inject(NOTIFICATIONS_CHANNEL_TOKEN)\n @optional()\n private readonly notificationsChannel?: NotificationsChannel\n ) {\n makeObservable(this);\n this.timers = new Map();\n }\n\n static intercept(type: string, fn?: NotificationInterceptor) {\n if (fn) {\n NotificationsStore.interceptors.set(type, fn);\n } else {\n NotificationsStore.interceptors.delete(type);\n }\n }\n\n private get publisher() {\n return this.notificationsChannel?.();\n }\n\n get navigate(): NavigateCallback | undefined {\n return this.#navigate;\n }\n\n set navigate(fn: NavigateCallback) {\n this.#navigate = fn;\n }\n\n initialize = async (userId: number) => {\n this.userId = userId;\n\n if (this.publisher) {\n this.publisher.bind(EVENT_NAME, this.onPublisherEvent);\n }\n\n this.intervalId = window.setInterval(() => this.cleanupClosedNotifications(), DAY_INTERVAL);\n\n if (!this.notificationsApi) {\n return;\n }\n\n const notifications = (await this.notificationsApi.getNotifications(false)).data;\n\n runInAction(() => {\n for (const notification of notifications) {\n this.updateIfNewer(notification);\n }\n });\n };\n\n dispose = () => {\n if (this.publisher) {\n this.publisher.global_emitter.unbind(EVENT_NAME, this.onPublisherEvent);\n }\n\n window.clearInterval(this.intervalId);\n Object.values(this.timers).forEach(timer => window.clearTimeout(timer));\n this.timers.clear();\n };\n\n @action\n add = (options: DefaultNotificationOptions, preventDuplicates?: boolean) => {\n const notification: ClientNotification = {\n id: this.index,\n userId: this.userId,\n type: CLIENT_NOTIFICATION_TYPE,\n status: ServerNotificationStatus.Info,\n isRead: false,\n createdOn: new Date(),\n modifiedOn: new Date(),\n version: CLIENT_NOTIFICATION_VERSION,\n payload: { ...options },\n };\n\n if (preventDuplicates) {\n if (\n [...this.notifications.values()].some(({ payload }) =>\n comparer.structural(payload, notification.payload)\n )\n ) {\n return;\n }\n this.notifications.set(notification.id, notification);\n }\n\n const method = this.getToastMethod(notification);\n notification.toastId = toast[method](this.getToastProps(notification));\n this.index -= 1;\n };\n\n @action\n read = (notification: Notification) => {\n const id = notification.id;\n if (!this.notifications.get(id)) {\n return;\n }\n\n if (id > 0) {\n this.clearTimer(notification);\n\n if (notification.status === ServerNotificationStatus.InProgress) {\n this.closedNotifications.set(id, {\n status: notification.status,\n timestamp: Date.now(),\n });\n }\n\n if (this.notificationsApi) {\n this.notificationsApi.changeIsReadProperty(id, true, notification.version);\n }\n }\n\n this.notifications.delete(id);\n };\n\n onToastEvent = (toastEvent: ToastEvent) => {\n if (toastEvent.eventType === 'add') {\n for (const [id, { toastId }] of Array.from(this.notifications)) {\n if (toastId === toastEvent.id) {\n this.notifications.get(id)!.toastActive = true;\n }\n }\n }\n };\n\n @action\n private readonly onPublisherEvent = (notification: ServerNotification) => {\n if (notification.userId !== this.userId) {\n return;\n }\n\n this.updateIfNewer({\n ...notification,\n createdOn: dateFromString(notification.createdOn),\n modifiedOn: dateFromString(notification.modifiedOn),\n });\n };\n\n private cleanupClosedNotifications() {\n for (const [id, { timestamp }] of Array.from(this.closedNotifications)) {\n if (Date.now() - timestamp > DAY_INTERVAL) {\n this.closedNotifications.delete(id);\n }\n }\n }\n\n private updateIfNewer(notification: ServerNotification) {\n const closed = this.closedNotifications.get(notification.id);\n if (closed) {\n if (closed.status === notification.status) {\n return;\n }\n\n this.closedNotifications.delete(notification.id);\n }\n\n const clientNotification = this.toClientNotification(notification);\n if (!clientNotification) {\n return;\n }\n\n const existing = this.notifications.get(notification.id);\n if (existing) {\n if (!isNewer(existing, notification)) {\n return;\n }\n if (\n notification.status === existing.status ||\n notification.status === ServerNotificationStatus.InProgress\n ) {\n toast.update(existing.toastId!, this.getToastProps(clientNotification));\n clientNotification.toastId = existing.toastId;\n this.notifications.set(notification.id, clientNotification);\n this.setTimer(clientNotification);\n return;\n }\n toast.dismiss(existing.toastId);\n }\n\n const method = this.getToastMethod(clientNotification);\n clientNotification.toastId = toast[method](this.getToastProps(clientNotification));\n this.notifications.set(notification.id, clientNotification);\n this.setTimer(clientNotification);\n }\n\n private getToastMethod({ payload: { status } }: ClientNotification): ToastMethod {\n switch (status) {\n case Status.Success:\n return 'success';\n case Status.Error:\n return 'danger';\n case Status.Warning:\n return 'warning';\n default:\n return 'info';\n }\n }\n\n private getToastProps(notification: ClientNotification): toastProps {\n const { action, duration = 8000, message = '', progress, title } = notification.payload;\n return {\n actions: this.getToastActions(notification),\n duration: action ? false : duration,\n message,\n onClose: () => this.handleClose(notification),\n onDismiss: () => this.handleDismiss(notification),\n progress,\n title,\n };\n }\n\n private getToastActions(notification: ClientNotification): toastProps['actions'] | undefined {\n const { action } = notification.payload;\n if (!action) {\n return;\n }\n\n return {\n primary: {\n label: action.label,\n onClick: () => this.handleClick(notification),\n },\n };\n }\n\n private handleClick({ payload: { action }, toastId }: ClientNotification) {\n if (action) {\n if (isLinkAction(action)) {\n if (action.external) {\n window.open(action.link);\n } else {\n this.navigate?.(action.link);\n }\n } else {\n action.onClick();\n }\n }\n\n toast.dismiss(toastId);\n }\n\n private handleClose(notification: Notification) {\n this.read(notification);\n }\n\n private handleDismiss(notification: Notification) {\n if (process.env.NODE_ENV !== 'production') {\n /*\n * StrictMode's double-rendering trigger's multiple onDismiss callbacks.\n * Ignore any that arrive before the toast is displayed.\n */\n if (!this.notifications.get(notification.id)?.toastActive) {\n return;\n }\n }\n\n this.handleClose(notification);\n }\n\n private toClientNotification(\n serverNotification: ServerNotification\n ): ClientNotification | undefined {\n const result: Notification<DefaultServerNotificationPayload> = {\n ...serverNotification,\n payload: {\n ...JSON.parse(serverNotification.payload ?? '{}'),\n status: this.toClientStatus(serverNotification.status),\n },\n };\n\n const interceptor = NotificationsStore.interceptors.get(serverNotification.type);\n if (!interceptor) {\n return result;\n }\n\n const dismiss = () => {\n const toastId = this.notifications.get(result.id)?.toastId;\n if (toastId) {\n toast.dismiss(toastId);\n }\n };\n\n return interceptor(result, dismiss);\n }\n\n private toClientStatus(status: ServerNotificationStatus) {\n switch (status) {\n case ServerNotificationStatus.Success:\n return Status.Success;\n case ServerNotificationStatus.Failure:\n return Status.Error;\n default:\n return Status.Info;\n }\n }\n\n private setTimer(notification: ClientNotification) {\n this.clearTimer(notification);\n\n const { duration = 0 } = notification.payload;\n if (duration <= 0) {\n return;\n }\n\n this.timers.set(\n notification.id,\n window.setTimeout(() => this.read(notification), duration)\n );\n }\n\n private clearTimer({ id }: Notification) {\n const timer = this.timers.get(id);\n if (!timer) {\n return;\n }\n\n this.timers.delete(id);\n window.clearTimeout(timer);\n }\n}\n"],"names":["toast","injectable","inject","optional","action","runInAction","comparer","makeObservable","NotificationsApi","NotificationProcessStatus","ServerNotificationStatus","Status","isLinkAction","isNewer","NOTIFICATIONS_CHANNEL_TOKEN","dateFromString","EVENT_NAME","CLIENT_NOTIFICATION_TYPE","CLIENT_NOTIFICATION_VERSION","DAY_INTERVAL","NotificationsStore","intercept","type","fn","interceptors","set","delete","publisher","notificationsChannel","navigate","cleanupClosedNotifications","id","timestamp","Array","from","closedNotifications","Date","now","updateIfNewer","notification","closed","get","status","clientNotification","toClientNotification","existing","notifications","InProgress","update","toastId","getToastProps","setTimer","dismiss","method","getToastMethod","payload","Success","Error","Warning","duration","message","progress","title","actions","getToastActions","onClose","handleClose","onDismiss","handleDismiss","primary","label","onClick","handleClick","external","window","open","link","read","process","env","NODE_ENV","toastActive","serverNotification","result","JSON","parse","toClientStatus","interceptor","Failure","Info","clearTimer","timers","setTimeout","timer","clearTimeout","notificationsApi","index","userId","intervalId","initialize","dispose","add","onToastEvent","onPublisherEvent","Map","bind","setInterval","getNotifications","data","global_emitter","unbind","clearInterval","Object","values","forEach","clear","options","preventDuplicates","isRead","createdOn","modifiedOn","version","some","structural","changeIsReadProperty","toastEvent","eventType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/stores/notifications.store.ts"],"sourcesContent":["import type { toastProps } from '@servicetitan/anvil2';\nimport { toast, Toaster } from '@servicetitan/anvil2';\nimport { injectable, inject, optional } from '@servicetitan/react-ioc';\nimport { action, runInAction, comparer, makeObservable } from 'mobx';\nimport type { ComponentProps } from 'react';\n\nimport type {\n DefaultServerNotificationPayload,\n Notification as ServerNotification,\n} from '../api/notifications.api';\nimport {\n NotificationsApi,\n NotificationProcessStatus as ServerNotificationStatus,\n} from '../api/notifications.api';\nimport type { DefaultNotificationOptions, Notification } from '../common';\nimport { Status, isLinkAction, isNewer } from '../common';\nimport type { NotificationInterceptor } from '../intercept';\nimport type { NotificationsChannel } from '../notifications-channel';\nimport { NOTIFICATIONS_CHANNEL_TOKEN } from '../notifications-channel';\nimport { dateFromString } from '../utils/date-from-string';\n\nconst EVENT_NAME = 'NotificationEvent';\nconst CLIENT_NOTIFICATION_TYPE = 'ClientNotification';\nconst CLIENT_NOTIFICATION_VERSION = 1;\nconst DAY_INTERVAL = 24 * 60 * 60 * 1000;\n\ninterface ClosedNotification {\n status: ServerNotificationStatus;\n timestamp: number;\n}\n\ninterface ClientNotification extends Notification<DefaultNotificationOptions> {\n toastId?: string;\n toastActive?: boolean;\n}\n\ntype NavigateCallback = (path: string) => void;\n\ntype ToastMethod = 'info' | 'success' | 'warning' | 'danger';\n\ntype ToastEvent = Parameters<NonNullable<ComponentProps<typeof Toaster>['onToastEvent']>>[0];\n\n@injectable()\nexport class NotificationsStore {\n static readonly interceptors = new Map<string, NotificationInterceptor>();\n\n private index = -1;\n private userId = 0;\n private intervalId?: number;\n private readonly timers: Map<number, number>;\n\n private readonly notifications = new Map<number, ClientNotification>();\n private readonly closedNotifications = new Map<number, ClosedNotification>();\n\n #navigate?: NavigateCallback;\n\n constructor(\n @inject(NotificationsApi) @optional() private readonly notificationsApi?: NotificationsApi,\n @inject(NOTIFICATIONS_CHANNEL_TOKEN)\n @optional()\n private readonly notificationsChannel?: NotificationsChannel\n ) {\n makeObservable(this);\n this.timers = new Map();\n }\n\n static intercept(type: string, fn?: NotificationInterceptor) {\n if (fn) {\n NotificationsStore.interceptors.set(type, fn);\n } else {\n NotificationsStore.interceptors.delete(type);\n }\n }\n\n private get publisher() {\n return this.notificationsChannel?.();\n }\n\n get navigate(): NavigateCallback | undefined {\n return this.#navigate;\n }\n\n set navigate(fn: NavigateCallback) {\n this.#navigate = fn;\n }\n\n initialize = async (userId: number) => {\n this.userId = userId;\n\n if (this.publisher) {\n this.publisher.bind(EVENT_NAME, this.onPublisherEvent);\n }\n\n this.intervalId = window.setInterval(() => this.cleanupClosedNotifications(), DAY_INTERVAL);\n\n if (!this.notificationsApi) {\n return;\n }\n\n const notifications = (await this.notificationsApi.getNotifications(false)).data;\n\n runInAction(() => {\n for (const notification of notifications) {\n this.updateIfNewer(notification);\n }\n });\n };\n\n dispose = () => {\n if (this.publisher) {\n this.publisher.global_emitter.unbind(EVENT_NAME, this.onPublisherEvent);\n }\n\n window.clearInterval(this.intervalId);\n Object.values(this.timers).forEach(timer => window.clearTimeout(timer));\n this.timers.clear();\n };\n\n @action\n add = (options: DefaultNotificationOptions, preventDuplicates?: boolean) => {\n const notification: ClientNotification = {\n id: this.index,\n userId: this.userId,\n type: CLIENT_NOTIFICATION_TYPE,\n status: ServerNotificationStatus.Info,\n isRead: false,\n createdOn: new Date(),\n modifiedOn: new Date(),\n version: CLIENT_NOTIFICATION_VERSION,\n payload: { ...options },\n };\n\n if (preventDuplicates) {\n if (\n [...this.notifications.values()].some(({ payload }) =>\n comparer.structural(payload, notification.payload)\n )\n ) {\n return;\n }\n this.notifications.set(notification.id, notification);\n }\n\n const method = this.getToastMethod(notification);\n notification.toastId = toast[method](this.getToastProps(notification));\n this.index -= 1;\n };\n\n @action\n read = (notification: Notification) => {\n const id = notification.id;\n if (!this.notifications.get(id)) {\n return;\n }\n\n if (id > 0) {\n this.clearTimer(notification);\n\n if (notification.status === ServerNotificationStatus.InProgress) {\n this.closedNotifications.set(id, {\n status: notification.status,\n timestamp: Date.now(),\n });\n }\n\n if (this.notificationsApi) {\n this.notificationsApi.changeIsReadProperty(id, true, notification.version);\n }\n }\n\n this.notifications.delete(id);\n };\n\n onToastEvent = (toastEvent: ToastEvent) => {\n if (toastEvent.eventType === 'add') {\n for (const [id, { toastId }] of Array.from(this.notifications)) {\n if (toastId === toastEvent.id) {\n this.notifications.get(id)!.toastActive = true;\n }\n }\n }\n };\n\n @action\n private readonly onPublisherEvent = (notification: ServerNotification) => {\n if (notification.userId !== this.userId) {\n return;\n }\n\n this.updateIfNewer({\n ...notification,\n createdOn: dateFromString(notification.createdOn),\n modifiedOn: dateFromString(notification.modifiedOn),\n });\n };\n\n private cleanupClosedNotifications() {\n for (const [id, { timestamp }] of Array.from(this.closedNotifications)) {\n if (Date.now() - timestamp > DAY_INTERVAL) {\n this.closedNotifications.delete(id);\n }\n }\n }\n\n private updateIfNewer(notification: ServerNotification) {\n const closed = this.closedNotifications.get(notification.id);\n if (closed) {\n if (closed.status === notification.status) {\n return;\n }\n\n this.closedNotifications.delete(notification.id);\n }\n\n const clientNotification = this.toClientNotification(notification);\n if (!clientNotification) {\n return;\n }\n\n const existing = this.notifications.get(notification.id);\n if (existing) {\n if (!isNewer(existing, notification)) {\n return;\n }\n if (\n notification.status === existing.status ||\n notification.status === ServerNotificationStatus.InProgress\n ) {\n toast.update(existing.toastId!, this.getToastProps(clientNotification));\n clientNotification.toastId = existing.toastId;\n this.notifications.set(notification.id, clientNotification);\n this.setTimer(clientNotification);\n return;\n }\n toast.dismiss(existing.toastId);\n }\n\n const method = this.getToastMethod(clientNotification);\n clientNotification.toastId = toast[method](this.getToastProps(clientNotification));\n this.notifications.set(notification.id, clientNotification);\n this.setTimer(clientNotification);\n }\n\n private getToastMethod({ payload: { status } }: ClientNotification): ToastMethod {\n switch (status) {\n case Status.Success:\n return 'success';\n case Status.Error:\n return 'danger';\n case Status.Warning:\n return 'warning';\n default:\n return 'info';\n }\n }\n\n private getToastProps(notification: ClientNotification): toastProps {\n const { action, duration = 8000, message = '', progress, title } = notification.payload;\n return {\n actions: this.getToastActions(notification),\n duration: action ? false : duration,\n message,\n onClose: () => this.handleClose(notification),\n onDismiss: () => this.handleDismiss(notification),\n progress,\n title,\n };\n }\n\n private getToastActions(notification: ClientNotification): toastProps['actions'] | undefined {\n const { action } = notification.payload;\n if (!action) {\n return;\n }\n\n return {\n primary: {\n label: action.label,\n onClick: () => this.handleClick(notification),\n },\n };\n }\n\n private handleClick({ payload: { action }, toastId }: ClientNotification) {\n if (action) {\n if (isLinkAction(action)) {\n if (action.external) {\n window.open(action.link);\n } else {\n this.navigate?.(action.link);\n }\n } else {\n action.onClick();\n }\n }\n\n toast.dismiss(toastId);\n }\n\n private handleClose(notification: Notification) {\n this.read(notification);\n }\n\n private handleDismiss(notification: Notification) {\n if (process.env.NODE_ENV !== 'production') {\n /*\n * StrictMode's double-rendering trigger's multiple onDismiss callbacks.\n * Ignore any that arrive before the toast is displayed.\n */\n if (!this.notifications.get(notification.id)?.toastActive) {\n return;\n }\n }\n\n this.handleClose(notification);\n }\n\n private toClientNotification(\n serverNotification: ServerNotification\n ): ClientNotification | undefined {\n const result: Notification<DefaultServerNotificationPayload> = {\n ...serverNotification,\n payload: {\n ...JSON.parse(serverNotification.payload ?? '{}'),\n status: this.toClientStatus(serverNotification.status),\n },\n };\n\n const interceptor = NotificationsStore.interceptors.get(serverNotification.type);\n if (!interceptor) {\n return result;\n }\n\n const dismiss = () => {\n const toastId = this.notifications.get(result.id)?.toastId;\n if (toastId) {\n toast.dismiss(toastId);\n }\n };\n\n return interceptor(result, dismiss);\n }\n\n private toClientStatus(status: ServerNotificationStatus) {\n switch (status) {\n case ServerNotificationStatus.Success:\n return Status.Success;\n case ServerNotificationStatus.Failure:\n return Status.Error;\n default:\n return Status.Info;\n }\n }\n\n private setTimer(notification: ClientNotification) {\n this.clearTimer(notification);\n\n const { duration = 0 } = notification.payload;\n if (duration <= 0) {\n return;\n }\n\n this.timers.set(\n notification.id,\n window.setTimeout(() => this.read(notification), duration)\n );\n }\n\n private clearTimer({ id }: Notification) {\n const timer = this.timers.get(id);\n if (!timer) {\n return;\n }\n\n this.timers.delete(id);\n window.clearTimeout(timer);\n }\n}\n"],"names":["toast","injectable","inject","optional","action","runInAction","comparer","makeObservable","NotificationsApi","NotificationProcessStatus","ServerNotificationStatus","Status","isLinkAction","isNewer","NOTIFICATIONS_CHANNEL_TOKEN","dateFromString","EVENT_NAME","CLIENT_NOTIFICATION_TYPE","CLIENT_NOTIFICATION_VERSION","DAY_INTERVAL","NotificationsStore","intercept","type","fn","interceptors","set","delete","publisher","notificationsChannel","navigate","cleanupClosedNotifications","id","timestamp","Array","from","closedNotifications","Date","now","updateIfNewer","notification","closed","get","status","clientNotification","toClientNotification","existing","notifications","InProgress","update","toastId","getToastProps","setTimer","dismiss","method","getToastMethod","payload","Success","Error","Warning","duration","message","progress","title","actions","getToastActions","onClose","handleClose","onDismiss","handleDismiss","primary","label","onClick","handleClick","external","window","open","link","read","process","env","NODE_ENV","toastActive","serverNotification","result","JSON","parse","toClientStatus","interceptor","Failure","Info","clearTimer","timers","setTimeout","timer","clearTimeout","notificationsApi","index","userId","intervalId","initialize","dispose","add","onToastEvent","onPublisherEvent","Map","bind","setInterval","getNotifications","data","global_emitter","unbind","clearInterval","Object","values","forEach","clear","options","preventDuplicates","isRead","createdOn","modifiedOn","version","some","structural","changeIsReadProperty","toastEvent","eventType"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/notifications",
|
|
3
|
-
"version": "41.
|
|
3
|
+
"version": "41.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"homepage": "https://docs.st.dev/docs/frontend/notifications-center",
|
|
6
6
|
"repository": {
|
|
@@ -19,17 +19,17 @@
|
|
|
19
19
|
"react-shadow-dom-retarget-events": "~1.1.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"@servicetitan/anvil2": "^
|
|
22
|
+
"@servicetitan/anvil2": "^3.8.0",
|
|
23
23
|
"@servicetitan/design-system": "~14.5.1",
|
|
24
|
-
"@servicetitan/react-ioc": "^
|
|
25
|
-
"@servicetitan/testing-library": "^6.
|
|
24
|
+
"@servicetitan/react-ioc": "^38.0.0",
|
|
25
|
+
"@servicetitan/testing-library": "^6.6.0",
|
|
26
26
|
"@testing-library/jest-dom": "^6.4.2",
|
|
27
27
|
"@testing-library/react": "^14.2.1",
|
|
28
28
|
"@types/react": "~18.2.55",
|
|
29
29
|
"@types/react-dom": "^18.2.19",
|
|
30
|
-
"@types/react-router": "
|
|
30
|
+
"@types/react-router": "^5.1.20",
|
|
31
31
|
"@types/react-shadow-dom-retarget-events": "~1.0.0",
|
|
32
|
-
"axios": "~0.
|
|
32
|
+
"axios": "~0.33.0",
|
|
33
33
|
"mobx": "~6.10.2",
|
|
34
34
|
"mobx-react": "^9.2.0",
|
|
35
35
|
"react": "^18.2.0",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"cli": {
|
|
53
53
|
"webpack": false
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "a27c08d5c4a695eb24110ec1477fa23ccf28a148"
|
|
56
56
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { DefaultNotificationOptions
|
|
2
|
-
import {
|
|
1
|
+
import type { DefaultNotificationOptions } from '../common';
|
|
2
|
+
import { Status } from '../common';
|
|
3
|
+
import type { NotificationsStore } from '../stores/notifications.store';
|
|
3
4
|
|
|
4
5
|
import { NotificationsService } from '../notifications-service';
|
|
5
6
|
|
package/src/common.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { injectable, useOptionalDependencies } from '@servicetitan/react-ioc';
|
|
2
2
|
import { mockComponent } from '@servicetitan/testing-library';
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
|
-
import { FC
|
|
4
|
+
import type { FC } from 'react';
|
|
5
|
+
import { Fragment } from 'react';
|
|
5
6
|
|
|
6
7
|
import { NotificationsApi } from '../../api/notifications.api';
|
|
7
8
|
import { NotificationsStore } from '../../stores/notifications.store';
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { Toaster } from '@servicetitan/anvil2';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
useCallback,
|
|
7
|
-
useEffect,
|
|
8
|
-
useRef,
|
|
9
|
-
useState,
|
|
10
|
-
useSyncExternalStore,
|
|
11
|
-
} from 'react';
|
|
2
|
+
import type { interfaces } from '@servicetitan/react-ioc';
|
|
3
|
+
import { Provider, useDependencies } from '@servicetitan/react-ioc';
|
|
4
|
+
import type { FC, PropsWithChildren } from 'react';
|
|
5
|
+
import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
12
6
|
|
|
13
7
|
import { NotificationsApi } from '../api/notifications.api';
|
|
14
8
|
import { NotificationsStore } from '../stores/notifications.store';
|
package/src/demo/basic.tsx
CHANGED
package/src/demo/container.tsx
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import { useEffect, useMemo } from 'react';
|
|
2
3
|
|
|
3
4
|
import { Provider, useDependencies } from '@servicetitan/react-ioc';
|
|
4
5
|
|
|
5
|
-
import { Notification } from '../api/notifications.api';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
Notifications,
|
|
9
|
-
NotificationsProps,
|
|
10
|
-
NotificationsService,
|
|
11
|
-
} from '..';
|
|
6
|
+
import type { Notification } from '../api/notifications.api';
|
|
7
|
+
import type { NotificationsProps } from '..';
|
|
8
|
+
import { NOTIFICATIONS_CHANNEL_TOKEN, Notifications, NotificationsService } from '..';
|
|
12
9
|
|
|
13
10
|
type EventCallback = (notification: Notification) => void;
|
|
14
11
|
|
package/src/demo/duration.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { AxiosPromise, CancelToken } from 'axios';
|
|
2
|
-
import { Notification
|
|
1
|
+
import type { AxiosPromise, CancelToken } from 'axios';
|
|
2
|
+
import type { Notification } from '../api/notifications.api';
|
|
3
|
+
import { NotificationsApi } from '../api/notifications.api';
|
|
3
4
|
|
|
4
5
|
export class MockNotificationsApi extends NotificationsApi {
|
|
5
6
|
private readonly localStorageKey = 'MockNotificationsApi.notifications';
|
package/src/demo/progress.tsx
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Button, Flex } from '@servicetitan/anvil2';
|
|
2
|
-
import { FC
|
|
2
|
+
import type { FC } from 'react';
|
|
3
|
+
import { useMemo } from 'react';
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
NotificationProcessStatus,
|
|
7
|
-
} from '../api/notifications.api';
|
|
5
|
+
import type { DefaultServerNotificationPayload } from '../api/notifications.api';
|
|
6
|
+
import { NotificationProcessStatus } from '../api/notifications.api';
|
|
8
7
|
import { Container } from './container';
|
|
9
8
|
import { MockNotificationsApi } from './mock-notifications-api';
|
|
10
|
-
import { LinkAction } from '../common';
|
|
9
|
+
import type { LinkAction } from '../common';
|
|
11
10
|
|
|
12
11
|
const BASIC =
|
|
13
12
|
"This toast disappears automatically.\n\nIt won't reappear when the page is reloaded, unless the reload happens before the toast disappears.";
|
package/src/intercept.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DefaultNotificationOptions, Notification } from './common';
|
|
1
|
+
import type { DefaultNotificationOptions, Notification } from './common';
|
|
2
2
|
import { NotificationsStore } from './stores/notifications.store';
|
|
3
3
|
|
|
4
4
|
export type NotificationInterceptor<T extends Record<keyof any, any> = {}> = (
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { injectable, inject } from '@servicetitan/react-ioc';
|
|
2
2
|
|
|
3
|
-
import { DefaultNotificationOptions
|
|
3
|
+
import type { DefaultNotificationOptions } from './common';
|
|
4
|
+
import { Status } from './common';
|
|
4
5
|
|
|
5
6
|
import { NotificationsStore } from './stores/notifications.store';
|
|
6
7
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { FC, PropsWithChildren
|
|
1
|
+
import type { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { StrictMode } from 'react';
|
|
2
3
|
import { BrowserRouter } from 'react-router-dom';
|
|
3
4
|
import { Text, Frame, Page } from '@servicetitan/design-system';
|
|
4
5
|
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { toast } from '@servicetitan/anvil2';
|
|
2
|
-
import { MouseEventHandler } from 'react';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from '../../api/notifications.api';
|
|
9
|
-
import { DefaultNotificationOptions, FunctionAction, LinkAction, Status } from '../../common';
|
|
2
|
+
import type { MouseEventHandler } from 'react';
|
|
3
|
+
|
|
4
|
+
import type { Notification, NotificationsApi } from '../../api/notifications.api';
|
|
5
|
+
import { NotificationProcessStatus } from '../../api/notifications.api';
|
|
6
|
+
import type { DefaultNotificationOptions, FunctionAction, LinkAction } from '../../common';
|
|
7
|
+
import { Status } from '../../common';
|
|
10
8
|
import { MockNotificationsChannel } from '../__mocks__/mock-notifications-channel';
|
|
11
9
|
|
|
12
10
|
import { NotificationsStore } from '../notifications.store';
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { toastProps } from '@servicetitan/anvil2';
|
|
2
|
+
import { toast, Toaster } from '@servicetitan/anvil2';
|
|
2
3
|
import { injectable, inject, optional } from '@servicetitan/react-ioc';
|
|
3
4
|
import { action, runInAction, comparer, makeObservable } from 'mobx';
|
|
4
|
-
import { ComponentProps } from 'react';
|
|
5
|
+
import type { ComponentProps } from 'react';
|
|
5
6
|
|
|
6
|
-
import {
|
|
7
|
+
import type {
|
|
7
8
|
DefaultServerNotificationPayload,
|
|
8
|
-
NotificationsApi,
|
|
9
9
|
Notification as ServerNotification,
|
|
10
|
+
} from '../api/notifications.api';
|
|
11
|
+
import {
|
|
12
|
+
NotificationsApi,
|
|
10
13
|
NotificationProcessStatus as ServerNotificationStatus,
|
|
11
14
|
} from '../api/notifications.api';
|
|
12
|
-
import { DefaultNotificationOptions, Notification
|
|
13
|
-
import {
|
|
15
|
+
import type { DefaultNotificationOptions, Notification } from '../common';
|
|
16
|
+
import { Status, isLinkAction, isNewer } from '../common';
|
|
17
|
+
import type { NotificationInterceptor } from '../intercept';
|
|
14
18
|
import type { NotificationsChannel } from '../notifications-channel';
|
|
15
19
|
import { NOTIFICATIONS_CHANNEL_TOKEN } from '../notifications-channel';
|
|
16
20
|
import { dateFromString } from '../utils/date-from-string';
|