@peassoft/mnr-web-topline 3.0.0 → 4.0.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.
Files changed (93) hide show
  1. package/README.md +105 -18
  2. package/dist/css/index.css +2 -2
  3. package/dist/en/modules/keyboard-navigation/key-codes.d.ts +16 -18
  4. package/dist/en/modules/keyboard-navigation/key-codes.js +17 -18
  5. package/dist/en/modules/keyboard-navigation/vertical-menu.d.ts +1 -1
  6. package/dist/en/modules/keyboard-navigation/vertical-menu.js +8 -8
  7. package/dist/en/modules/local-db/actions/delete-all-data/index.js +2 -2
  8. package/dist/en/modules/local-db/actions/get-all-data/index.js +2 -2
  9. package/dist/en/modules/local-db/actions/get-is-user-known/index.d.ts +5 -0
  10. package/dist/en/modules/local-db/actions/get-is-user-known/index.js +33 -0
  11. package/dist/en/modules/local-db/actions/update-grant-token/index.js +3 -3
  12. package/dist/en/modules/local-db/actions/update-is-user-known/index.d.ts +5 -0
  13. package/dist/en/modules/local-db/actions/update-is-user-known/index.js +27 -0
  14. package/dist/en/modules/local-db/actions/update-refresh-token/index.js +3 -3
  15. package/dist/en/modules/local-db/actions/update-user/index.js +3 -3
  16. package/dist/en/modules/local-db/index.d.ts +2 -0
  17. package/dist/en/modules/local-db/index.js +3 -1
  18. package/dist/en/modules/local-db/init-db.d.ts +2 -1
  19. package/dist/en/modules/local-db/init-db.js +19 -10
  20. package/dist/en/modules/topline-service/index.d.ts +3 -1
  21. package/dist/en/modules/topline-service/index.js +6 -0
  22. package/dist/en/modules/topline-service/inner-service.d.ts +6 -1
  23. package/dist/en/modules/topline-service/inner-service.js +18 -0
  24. package/dist/en/modules/topline-service/types.d.ts +12 -0
  25. package/dist/en/modules/topline-service/types.js +4 -0
  26. package/dist/en/parts/login/actions/perform-login/index.d.ts +1 -15
  27. package/dist/en/parts/login/actions/perform-login/index.js +8 -17
  28. package/dist/en/parts/password-recovery/actions/save-password/index.d.ts +1 -15
  29. package/dist/en/parts/password-recovery/actions/save-password/index.js +8 -17
  30. package/dist/en/parts/profile/ui/password-change-confirmation/index.js +1 -0
  31. package/dist/en/parts/profile/ui/password-change-form/use-state-with-validation-reset.js +1 -1
  32. package/dist/en/parts/shell/context.d.ts +1 -1
  33. package/dist/en/parts/shell/ui/logged-out-user-menu/index.js +2 -0
  34. package/dist/en/parts/shell/ui/loggeg-in-user-menu/index.js +2 -0
  35. package/dist/en/parts/shell/ui/shell/index.js +11 -5
  36. package/dist/en/parts/shell/ui/user-menu-item/index.d.ts +1 -0
  37. package/dist/en/parts/shell/ui/user-menu-item/index.js +2 -0
  38. package/dist/en/parts/signup/actions/perform-signup/index.d.ts +1 -15
  39. package/dist/en/parts/signup/actions/perform-signup/index.js +8 -17
  40. package/dist/en/shared/components/modal/index.js +2 -2
  41. package/dist/en/shared/procedures/process-response.d.ts +13 -0
  42. package/dist/en/shared/procedures/process-response.js +53 -0
  43. package/dist/en/topline.d.ts +1 -1
  44. package/dist/en/types/result.d.ts +9 -0
  45. package/dist/en/types/result.js +12 -0
  46. package/dist/ru/modules/keyboard-navigation/key-codes.d.ts +16 -18
  47. package/dist/ru/modules/keyboard-navigation/key-codes.js +17 -18
  48. package/dist/ru/modules/keyboard-navigation/vertical-menu.d.ts +1 -1
  49. package/dist/ru/modules/keyboard-navigation/vertical-menu.js +8 -8
  50. package/dist/ru/modules/local-db/actions/delete-all-data/index.js +2 -2
  51. package/dist/ru/modules/local-db/actions/get-all-data/index.js +2 -2
  52. package/dist/ru/modules/local-db/actions/get-is-user-known/index.d.ts +5 -0
  53. package/dist/ru/modules/local-db/actions/get-is-user-known/index.js +33 -0
  54. package/dist/ru/modules/local-db/actions/update-grant-token/index.js +3 -3
  55. package/dist/ru/modules/local-db/actions/update-is-user-known/index.d.ts +5 -0
  56. package/dist/ru/modules/local-db/actions/update-is-user-known/index.js +27 -0
  57. package/dist/ru/modules/local-db/actions/update-refresh-token/index.js +3 -3
  58. package/dist/ru/modules/local-db/actions/update-user/index.js +3 -3
  59. package/dist/ru/modules/local-db/index.d.ts +2 -0
  60. package/dist/ru/modules/local-db/index.js +3 -1
  61. package/dist/ru/modules/local-db/init-db.d.ts +2 -1
  62. package/dist/ru/modules/local-db/init-db.js +19 -10
  63. package/dist/ru/modules/topline-service/index.d.ts +3 -1
  64. package/dist/ru/modules/topline-service/index.js +6 -0
  65. package/dist/ru/modules/topline-service/inner-service.d.ts +6 -1
  66. package/dist/ru/modules/topline-service/inner-service.js +18 -0
  67. package/dist/ru/modules/topline-service/types.d.ts +12 -0
  68. package/dist/ru/modules/topline-service/types.js +4 -0
  69. package/dist/ru/parts/login/actions/perform-login/index.d.ts +1 -15
  70. package/dist/ru/parts/login/actions/perform-login/index.js +8 -17
  71. package/dist/ru/parts/password-recovery/actions/save-password/index.d.ts +1 -15
  72. package/dist/ru/parts/password-recovery/actions/save-password/index.js +8 -17
  73. package/dist/ru/parts/profile/ui/password-change-confirmation/index.js +1 -0
  74. package/dist/ru/parts/profile/ui/password-change-form/use-state-with-validation-reset.js +1 -1
  75. package/dist/ru/parts/shell/context.d.ts +1 -1
  76. package/dist/ru/parts/shell/ui/logged-out-user-menu/index.js +2 -0
  77. package/dist/ru/parts/shell/ui/loggeg-in-user-menu/index.js +2 -0
  78. package/dist/ru/parts/shell/ui/shell/index.js +11 -5
  79. package/dist/ru/parts/shell/ui/user-menu-item/index.d.ts +1 -0
  80. package/dist/ru/parts/shell/ui/user-menu-item/index.js +2 -0
  81. package/dist/ru/parts/signup/actions/perform-signup/index.d.ts +1 -15
  82. package/dist/ru/parts/signup/actions/perform-signup/index.js +8 -17
  83. package/dist/ru/shared/components/modal/index.js +2 -2
  84. package/dist/ru/shared/procedures/process-response.d.ts +13 -0
  85. package/dist/ru/shared/procedures/process-response.js +53 -0
  86. package/dist/ru/topline.d.ts +1 -1
  87. package/dist/ru/types/result.d.ts +9 -0
  88. package/dist/ru/types/result.js +12 -0
  89. package/package.json +10 -4
  90. package/dist/en/shared/procedures/process-successful-response/index.d.ts +0 -30
  91. package/dist/en/shared/procedures/process-successful-response/index.js +0 -66
  92. package/dist/ru/shared/procedures/process-successful-response/index.d.ts +0 -30
  93. package/dist/ru/shared/procedures/process-successful-response/index.js +0 -66
@@ -1,4 +1,4 @@
1
- import { getDb, STORE_NAME } from '../../init-db.js';
1
+ import { getDb, MAIN_STORE_NAME } from '../../init-db.js';
2
2
  import createRequestError from '../../create-request-error.js';
3
3
  import { logError } from '../../../logger/index.js';
4
4
  /**
@@ -15,7 +15,7 @@ export default function getAllData() {
15
15
  });
16
16
  return;
17
17
  }
18
- const req = db.transaction(STORE_NAME).objectStore(STORE_NAME).getAll();
18
+ const req = db.transaction(MAIN_STORE_NAME).objectStore(MAIN_STORE_NAME).getAll();
19
19
  req.onsuccess = function () {
20
20
  const recordset = this.result;
21
21
  let user = null;
@@ -0,0 +1,5 @@
1
+ import { type Result } from '../../../../types/result.js';
2
+ /**
3
+ * Retrieve the value of flag `isUserKnown`.
4
+ */
5
+ export default function getIsUserKnown(): Promise<Result<boolean, never>>;
@@ -0,0 +1,33 @@
1
+ import { getDb, PERSISTENT_STORE_NAME } from '../../init-db.js';
2
+ import createRequestError from '../../create-request-error.js';
3
+ import { logError } from '../../../logger/index.js';
4
+ import { Ok } from '../../../../types/result.js';
5
+ /**
6
+ * Retrieve the value of flag `isUserKnown`.
7
+ */
8
+ export default function getIsUserKnown() {
9
+ return new Promise(resolve => {
10
+ const db = getDb();
11
+ if (!db) {
12
+ // If something is wrong with the DB, we would be better off returning "true"
13
+ // to prevent presenting the user the default set of content when it might
14
+ // be unreasonable.
15
+ resolve(Ok(true));
16
+ return;
17
+ }
18
+ const req = db.transaction(PERSISTENT_STORE_NAME).objectStore(PERSISTENT_STORE_NAME).get('isUserKnown');
19
+ req.onsuccess = function () {
20
+ const record = this.result;
21
+ if (record) {
22
+ resolve(Ok(record.isUserKnown));
23
+ } else {
24
+ resolve(Ok(false));
25
+ }
26
+ };
27
+ req.onerror = () => {
28
+ logError(createRequestError('getIsUserKnown'));
29
+ // For reasoning for returning "true" see comment on the "db" instance absence above.
30
+ resolve(Ok(true));
31
+ };
32
+ });
33
+ }
@@ -1,4 +1,4 @@
1
- import { getDb, STORE_NAME } from '../../init-db.js';
1
+ import { getDb, MAIN_STORE_NAME } from '../../init-db.js';
2
2
  import createRequestError from '../../create-request-error.js';
3
3
  import { logError } from '../../../logger/index.js';
4
4
  /**
@@ -11,13 +11,13 @@ export default function updateGrantToken(grantToken) {
11
11
  resolve();
12
12
  return;
13
13
  }
14
- const transaction = db.transaction(STORE_NAME, 'readwrite');
14
+ const transaction = db.transaction(MAIN_STORE_NAME, 'readwrite');
15
15
  transaction.oncomplete = () => resolve();
16
16
  transaction.onerror = () => {
17
17
  logError(createRequestError('updateGrantToken'));
18
18
  resolve();
19
19
  };
20
- const objectStore = transaction.objectStore(STORE_NAME);
20
+ const objectStore = transaction.objectStore(MAIN_STORE_NAME);
21
21
  objectStore.put({
22
22
  entityType: 'grantToken',
23
23
  grantToken
@@ -0,0 +1,5 @@
1
+ import { type Result } from '../../../../types/result.js';
2
+ /**
3
+ * Update the value of flag `isUserKnown`.
4
+ */
5
+ export default function updateIsUserKnown(value: boolean): Promise<Result<void, never>>;
@@ -0,0 +1,27 @@
1
+ import { getDb, PERSISTENT_STORE_NAME } from '../../init-db.js';
2
+ import createRequestError from '../../create-request-error.js';
3
+ import { logError } from '../../../logger/index.js';
4
+ import { Ok } from '../../../../types/result.js';
5
+ /**
6
+ * Update the value of flag `isUserKnown`.
7
+ */
8
+ export default function updateIsUserKnown(value) {
9
+ return new Promise(resolve => {
10
+ const db = getDb();
11
+ if (!db) {
12
+ resolve(Ok(undefined));
13
+ return;
14
+ }
15
+ const transaction = db.transaction(PERSISTENT_STORE_NAME, 'readwrite');
16
+ transaction.oncomplete = () => resolve(Ok(undefined));
17
+ transaction.onerror = () => {
18
+ logError(createRequestError('updateRefreshToken'));
19
+ resolve(Ok(undefined));
20
+ };
21
+ const objectStore = transaction.objectStore(PERSISTENT_STORE_NAME);
22
+ objectStore.put({
23
+ entityType: 'isUserKnown',
24
+ isUserKnown: value
25
+ });
26
+ });
27
+ }
@@ -1,4 +1,4 @@
1
- import { getDb, STORE_NAME } from '../../init-db.js';
1
+ import { getDb, MAIN_STORE_NAME } from '../../init-db.js';
2
2
  import createRequestError from '../../create-request-error.js';
3
3
  import { logError } from '../../../logger/index.js';
4
4
  /**
@@ -11,13 +11,13 @@ export default function updateRefreshToken(refreshToken) {
11
11
  resolve();
12
12
  return;
13
13
  }
14
- const transaction = db.transaction(STORE_NAME, 'readwrite');
14
+ const transaction = db.transaction(MAIN_STORE_NAME, 'readwrite');
15
15
  transaction.oncomplete = () => resolve();
16
16
  transaction.onerror = () => {
17
17
  logError(createRequestError('updateRefreshToken'));
18
18
  resolve();
19
19
  };
20
- const objectStore = transaction.objectStore(STORE_NAME);
20
+ const objectStore = transaction.objectStore(MAIN_STORE_NAME);
21
21
  objectStore.put({
22
22
  entityType: 'refreshToken',
23
23
  refreshToken
@@ -1,4 +1,4 @@
1
- import { getDb, STORE_NAME } from '../../init-db.js';
1
+ import { getDb, MAIN_STORE_NAME } from '../../init-db.js';
2
2
  import createRequestError from '../../create-request-error.js';
3
3
  import { logError } from '../../../logger/index.js';
4
4
  /**
@@ -11,13 +11,13 @@ export default function updateUser(user) {
11
11
  resolve();
12
12
  return;
13
13
  }
14
- const transaction = db.transaction(STORE_NAME, 'readwrite');
14
+ const transaction = db.transaction(MAIN_STORE_NAME, 'readwrite');
15
15
  transaction.oncomplete = () => resolve();
16
16
  transaction.onerror = () => {
17
17
  logError(createRequestError('updateUser'));
18
18
  resolve();
19
19
  };
20
- const objectStore = transaction.objectStore(STORE_NAME);
20
+ const objectStore = transaction.objectStore(MAIN_STORE_NAME);
21
21
  objectStore.put({
22
22
  entityType: 'user',
23
23
  user
@@ -4,3 +4,5 @@ export { default as deleteAllData } from './actions/delete-all-data/index.js';
4
4
  export { default as updateUser } from './actions/update-user/index.js';
5
5
  export { default as updateGrantToken } from './actions/update-grant-token/index.js';
6
6
  export { default as updateRefreshToken } from './actions/update-refresh-token/index.js';
7
+ export { default as getIsUserKnown } from './actions/get-is-user-known/index.js';
8
+ export { default as updateIsUserKnown } from './actions/update-is-user-known/index.js';
@@ -3,4 +3,6 @@ export { default as getAllData } from './actions/get-all-data/index.js';
3
3
  export { default as deleteAllData } from './actions/delete-all-data/index.js';
4
4
  export { default as updateUser } from './actions/update-user/index.js';
5
5
  export { default as updateGrantToken } from './actions/update-grant-token/index.js';
6
- export { default as updateRefreshToken } from './actions/update-refresh-token/index.js';
6
+ export { default as updateRefreshToken } from './actions/update-refresh-token/index.js';
7
+ export { default as getIsUserKnown } from './actions/get-is-user-known/index.js';
8
+ export { default as updateIsUserKnown } from './actions/update-is-user-known/index.js';
@@ -1,4 +1,5 @@
1
- export declare const STORE_NAME = "main";
1
+ export declare const MAIN_STORE_NAME = "main";
2
+ export declare const PERSISTENT_STORE_NAME = "persistent";
2
3
  /**
3
4
  * Get IndexedDb database object
4
5
  *
@@ -1,7 +1,10 @@
1
1
  import WebError from '@memnrev/web-error';
2
2
  const DB_NAME = 'mnr_topline';
3
- const DB_VERSION = 1;
4
- export const STORE_NAME = 'main';
3
+ const DB_VERSION = 2;
4
+ // Main store data is deleted when a user logs out.
5
+ export const MAIN_STORE_NAME = 'main';
6
+ // Persistent store is not cleaned up when a user logs out.
7
+ export const PERSISTENT_STORE_NAME = 'persistent';
5
8
  let _db = null;
6
9
  /**
7
10
  * Get IndexedDb database object
@@ -33,14 +36,20 @@ export function initDb() {
33
36
  resolve();
34
37
  };
35
38
  openDbReq.onupgradeneeded = function (e) {
36
- if (e.oldVersion < DB_VERSION) {
37
- const db = this.result;
38
- for (const objectStoreName of db.objectStoreNames) {
39
- db.deleteObjectStore(objectStoreName);
40
- }
41
- db.createObjectStore(STORE_NAME, {
42
- keyPath: 'entityType'
43
- });
39
+ const db = this.result;
40
+ switch (e.oldVersion) {
41
+ case 0:
42
+ db.createObjectStore(MAIN_STORE_NAME, {
43
+ keyPath: 'entityType'
44
+ });
45
+ db.createObjectStore(PERSISTENT_STORE_NAME, {
46
+ keyPath: 'entityType'
47
+ });
48
+ break;
49
+ case 1:
50
+ db.createObjectStore(PERSISTENT_STORE_NAME, {
51
+ keyPath: 'entityType'
52
+ });
44
53
  }
45
54
  };
46
55
  openDbReq.onblocked = function () {
@@ -1,4 +1,4 @@
1
- import { type LogoutListener, type UserChangeListener, type SyncNotificationListener, ToplineEventName } from './types.js';
1
+ import { type LoginListener, type SignupListener, type LogoutListener, type UserChangeListener, type SyncNotificationListener, ToplineEventName } from './types.js';
2
2
  export { ToplineEventName, InnerToplineEventName } from './types.js';
3
3
  export { default as innerToplineService, type InnerService } from './inner-service.js';
4
4
  /**
@@ -13,6 +13,8 @@ declare class _ToplineService {
13
13
  /** Upgrade grant token with refresh token */
14
14
  upgradeGrantToken(): Promise<string | null>;
15
15
  /** Register an event listener */
16
+ on(eventName: ToplineEventName.Login, cb: LoginListener): this;
17
+ on(eventName: ToplineEventName.Signup, cb: SignupListener): this;
16
18
  on(eventName: ToplineEventName.Logout, cb: LogoutListener): this;
17
19
  on(eventName: ToplineEventName.UserChange, cb: UserChangeListener): this;
18
20
  on(eventName: ToplineEventName.SyncNotification, cb: SyncNotificationListener): this;
@@ -17,6 +17,12 @@ class _ToplineService {
17
17
  }
18
18
  on(eventName, cb) {
19
19
  switch (eventName) {
20
+ case ToplineEventName.Login:
21
+ this.#innerSrvs.on(eventName, cb);
22
+ break;
23
+ case ToplineEventName.Signup:
24
+ this.#innerSrvs.on(eventName, cb);
25
+ break;
20
26
  case ToplineEventName.Logout:
21
27
  this.#innerSrvs.on(eventName, cb);
22
28
  break;
@@ -4,7 +4,7 @@ import { getApiBaseUrl } from '../env/index.js';
4
4
  import request from '../request/index.js';
5
5
  import { logError } from '../logger/index.js';
6
6
  import type { ToplineUser } from '../../types/data.js';
7
- import { type LogoutListener, type UserChangeListener, type SyncNotificationListener, type InnerListenerCallback, ToplineEventName, InnerToplineEventName } from './types.js';
7
+ import { type LoginListener, type SignupListener, type LogoutListener, type UserChangeListener, type SyncNotificationListener, type InnerListenerCallback, ToplineEventName, InnerToplineEventName } from './types.js';
8
8
  export type Deps = {
9
9
  getRefreshToken: typeof getRefreshToken;
10
10
  setGrantToken: typeof setGrantToken;
@@ -21,13 +21,18 @@ export declare class InnerService {
21
21
  /** Get grant token */
22
22
  grantToken(): string | null;
23
23
  /** Register an event listener */
24
+ on(eventName: ToplineEventName.Login, cb: LoginListener): void;
25
+ on(eventName: ToplineEventName.Signup, cb: SignupListener): void;
24
26
  on(eventName: ToplineEventName.Logout, cb: LogoutListener): void;
25
27
  on(eventName: ToplineEventName.UserChange, cb: UserChangeListener): void;
26
28
  on(eventName: ToplineEventName.SyncNotification, cb: SyncNotificationListener): void;
27
29
  /** Emit an outer event */
30
+ emit(eventName: ToplineEventName.Login, payload: ToplineUser): void;
31
+ emit(eventName: ToplineEventName.Signup, payload: ToplineUser): void;
28
32
  emit(eventName: ToplineEventName.Logout): void;
29
33
  emit(eventName: ToplineEventName.UserChange, payload: ToplineUser): void;
30
34
  emit(eventName: ToplineEventName.SyncNotification, payload: string): void;
35
+ emit(eventName: ToplineEventName, payload?: ToplineUser | string): void;
31
36
  /** Upgrade grant token with refresh token */
32
37
  upgradeGrantToken(): Promise<string | null>;
33
38
  /**
@@ -38,6 +38,18 @@ export class InnerService {
38
38
  }
39
39
  on(eventName, cb) {
40
40
  switch (eventName) {
41
+ case ToplineEventName.Login:
42
+ this.#listeners.add({
43
+ eventName,
44
+ cb: cb
45
+ });
46
+ break;
47
+ case ToplineEventName.Signup:
48
+ this.#listeners.add({
49
+ eventName,
50
+ cb: cb
51
+ });
52
+ break;
41
53
  case ToplineEventName.Logout:
42
54
  this.#listeners.add({
43
55
  eventName,
@@ -67,6 +79,12 @@ export class InnerService {
67
79
  this.#listeners.forEach(listener => {
68
80
  if (eventName === listener.eventName) {
69
81
  switch (listener.eventName) {
82
+ case ToplineEventName.Login:
83
+ listener.cb.call(this, payload);
84
+ break;
85
+ case ToplineEventName.Signup:
86
+ listener.cb.call(this, payload);
87
+ break;
70
88
  case ToplineEventName.Logout:
71
89
  listener.cb.call(this);
72
90
  break;
@@ -5,6 +5,10 @@ import type { ToplineUser } from '../../types/data.js';
5
5
  * @public
6
6
  */
7
7
  export declare enum ToplineEventName {
8
+ /** User has been logged in */
9
+ Login = "login",
10
+ /** User has been signed up */
11
+ Signup = "signup",
8
12
  /** User has been logged out */
9
13
  Logout = "logout",
10
14
  /** User data changed */
@@ -12,10 +16,18 @@ export declare enum ToplineEventName {
12
16
  /** A sync notification has been received */
13
17
  SyncNotification = "syncNotification"
14
18
  }
19
+ export type LoginListener = (user: ToplineUser) => unknown;
20
+ export type SignupListener = (user: ToplineUser) => unknown;
15
21
  export type LogoutListener = () => unknown;
16
22
  export type UserChangeListener = (user: ToplineUser) => unknown;
17
23
  export type SyncNotificationListener = (syncId: string) => unknown;
18
24
  export type ToplineEventListener = {
25
+ eventName: ToplineEventName.Login;
26
+ cb: LoginListener;
27
+ } | {
28
+ eventName: ToplineEventName.Signup;
29
+ cb: SignupListener;
30
+ } | {
19
31
  eventName: ToplineEventName.Logout;
20
32
  cb: LogoutListener;
21
33
  } | {
@@ -5,6 +5,10 @@
5
5
  */
6
6
  export var ToplineEventName;
7
7
  (function (ToplineEventName) {
8
+ /** User has been logged in */
9
+ ToplineEventName["Login"] = "login";
10
+ /** User has been signed up */
11
+ ToplineEventName["Signup"] = "signup";
8
12
  /** User has been logged out */
9
13
  ToplineEventName["Logout"] = "logout";
10
14
  /** User data changed */
@@ -1,7 +1,3 @@
1
- import stampit from 'stampit';
2
- import { getApiBaseUrl, getRequestCredentialsMode } from '../../../../modules/env/index.js';
3
- import request from '../../../../modules/request/index.js';
4
- import processSuccessfulResponse from '../../../../shared/procedures/process-successful-response/index.js';
5
1
  import type { ToplineUser } from '../../../../types/data.js';
6
2
  export type ReturnValue = {
7
3
  user: ToplineUser | null;
@@ -14,14 +10,4 @@ export type ReturnValue = {
14
10
  * - on network error or if backend responds with 5xx - "network";
15
11
  * - on login failure - "incorrect-credentials".
16
12
  */
17
- declare function performLogin(this: This, email: string, password: string): Promise<ReturnValue>;
18
- export type This = {
19
- getApiBaseUrl: typeof getApiBaseUrl;
20
- getRequestCredentialsMode: typeof getRequestCredentialsMode;
21
- request: typeof request;
22
- processSuccessfulResponse: typeof processSuccessfulResponse;
23
- performLogin: typeof performLogin;
24
- };
25
- export declare const PerformLogin: stampit.Stamp<This>;
26
- declare const _default: (email: string, password: string) => Promise<ReturnValue>;
27
- export default _default;
13
+ export default function performLogin(email: string, password: string): Promise<ReturnValue>;
@@ -1,7 +1,7 @@
1
- import stampit from 'stampit';
2
1
  import { getApiBaseUrl, getRequestCredentialsMode } from '../../../../modules/env/index.js';
3
2
  import request from '../../../../modules/request/index.js';
4
- import processSuccessfulResponse from '../../../../shared/procedures/process-successful-response/index.js';
3
+ import processResponse from '../../../../shared/procedures/process-response.js';
4
+ import { ToplineEventName } from '../../../../modules/topline-service/index.js';
5
5
  /**
6
6
  * Perform logging-in
7
7
  *
@@ -9,8 +9,8 @@ import processSuccessfulResponse from '../../../../shared/procedures/process-suc
9
9
  * - on network error or if backend responds with 5xx - "network";
10
10
  * - on login failure - "incorrect-credentials".
11
11
  */
12
- async function performLogin(email, password) {
13
- const url = `${this.getApiBaseUrl()}/public/login-with-credentials`;
12
+ export default async function performLogin(email, password) {
13
+ const url = `${getApiBaseUrl()}/public/login-with-credentials`;
14
14
  const options = {
15
15
  method: 'POST',
16
16
  headers: {
@@ -20,11 +20,11 @@ async function performLogin(email, password) {
20
20
  email,
21
21
  password
22
22
  }),
23
- credentials: this.getRequestCredentialsMode(),
23
+ credentials: getRequestCredentialsMode(),
24
24
  cache: 'no-store',
25
25
  redirect: 'error'
26
26
  };
27
- const response = await this.request(url, options, {
27
+ const response = await request(url, options, {
28
28
  maxRetries: 1
29
29
  });
30
30
  if (!response) {
@@ -34,7 +34,7 @@ async function performLogin(email, password) {
34
34
  };
35
35
  }
36
36
  if (response.status === 200) {
37
- return await this.processSuccessfulResponse(response, url);
37
+ return await processResponse(response, url, ToplineEventName.Login);
38
38
  }
39
39
  if (response.status === 401) {
40
40
  return {
@@ -48,13 +48,4 @@ async function performLogin(email, password) {
48
48
  user: null,
49
49
  error: 'network'
50
50
  };
51
- }
52
- export const PerformLogin = stampit().props({
53
- getApiBaseUrl,
54
- getRequestCredentialsMode,
55
- request,
56
- processSuccessfulResponse
57
- }).methods({
58
- performLogin
59
- });
60
- export default performLogin.bind(PerformLogin());
51
+ }
@@ -1,7 +1,3 @@
1
- import stampit from 'stampit';
2
- import { getApiBaseUrl, getRequestCredentialsMode } from '../../../../modules/env/index.js';
3
- import request from '../../../../modules/request/index.js';
4
- import processSuccessfulResponse from '../../../../shared/procedures/process-successful-response/index.js';
5
1
  import type { ToplineUser } from '../../../../types/data.js';
6
2
  export type ReturnValue = {
7
3
  user: ToplineUser | null;
@@ -14,14 +10,4 @@ export type ReturnValue = {
14
10
  * - on network error or if backend responds with 5xx - "network";
15
11
  * - on 403 Forbidden response - "no-claim".
16
12
  */
17
- declare function savePassword(this: This, email: string, password: string, secretCode: string): Promise<ReturnValue>;
18
- export type This = {
19
- getApiBaseUrl: typeof getApiBaseUrl;
20
- getRequestCredentialsMode: typeof getRequestCredentialsMode;
21
- request: typeof request;
22
- processSuccessfulResponse: typeof processSuccessfulResponse;
23
- savePassword: typeof savePassword;
24
- };
25
- export declare const SavePassword: stampit.Stamp<This>;
26
- declare const _default: (email: string, password: string, secretCode: string) => Promise<ReturnValue>;
27
- export default _default;
13
+ export default function savePassword(email: string, password: string, secretCode: string): Promise<ReturnValue>;
@@ -1,7 +1,7 @@
1
- import stampit from 'stampit';
2
1
  import { getApiBaseUrl, getRequestCredentialsMode } from '../../../../modules/env/index.js';
3
2
  import request from '../../../../modules/request/index.js';
4
- import processSuccessfulResponse from '../../../../shared/procedures/process-successful-response/index.js';
3
+ import processResponse from '../../../../shared/procedures/process-response.js';
4
+ import { ToplineEventName } from '../../../../modules/topline-service/index.js';
5
5
  /**
6
6
  * Save new password
7
7
  *
@@ -9,8 +9,8 @@ import processSuccessfulResponse from '../../../../shared/procedures/process-suc
9
9
  * - on network error or if backend responds with 5xx - "network";
10
10
  * - on 403 Forbidden response - "no-claim".
11
11
  */
12
- async function savePassword(email, password, secretCode) {
13
- const url = `${this.getApiBaseUrl()}/public/create-new-password`;
12
+ export default async function savePassword(email, password, secretCode) {
13
+ const url = `${getApiBaseUrl()}/public/create-new-password`;
14
14
  const options = {
15
15
  method: 'POST',
16
16
  headers: {
@@ -21,11 +21,11 @@ async function savePassword(email, password, secretCode) {
21
21
  password,
22
22
  secretCode
23
23
  }),
24
- credentials: this.getRequestCredentialsMode(),
24
+ credentials: getRequestCredentialsMode(),
25
25
  cache: 'no-store',
26
26
  redirect: 'error'
27
27
  };
28
- const response = await this.request(url, options, {
28
+ const response = await request(url, options, {
29
29
  expectedStatusCodes: [200, 403]
30
30
  });
31
31
  if (!response) {
@@ -35,7 +35,7 @@ async function savePassword(email, password, secretCode) {
35
35
  };
36
36
  }
37
37
  if (response.status === 200) {
38
- return await this.processSuccessfulResponse(response, url);
38
+ return await processResponse(response, url, ToplineEventName.Login);
39
39
  }
40
40
  if (response.status === 403) {
41
41
  return {
@@ -49,13 +49,4 @@ async function savePassword(email, password, secretCode) {
49
49
  user: null,
50
50
  error: 'network'
51
51
  };
52
- }
53
- export const SavePassword = stampit().props({
54
- getApiBaseUrl,
55
- getRequestCredentialsMode,
56
- request,
57
- processSuccessfulResponse
58
- }).methods({
59
- savePassword
60
- });
61
- export default savePassword.bind(SavePassword());
52
+ }
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import 'react';
2
3
  import { Button } from '@peassoft/mnr-web-ui-kit/button/index.js';
3
4
  export default function PasswordChangeConfirmation(props) {
4
5
  const {
@@ -1,4 +1,4 @@
1
- import { useState, useCallback } from 'react';
1
+ import React, { useState, useCallback } from 'react';
2
2
  export default function useStateWithValidationReset(initialState, validationSetFn, validationResetValue) {
3
3
  const [value, setValue] = useState(initialState);
4
4
  const handleChange = useCallback(newVal => {
@@ -6,7 +6,7 @@ export type InnerToplineContext = {
6
6
  forceBlankHomeLink: boolean;
7
7
  user: ToplineUser | null;
8
8
  handleUserChange: (user: ToplineUser | null) => unknown;
9
- onReady: (toplineService: ToplineService, user: ToplineUser | null) => unknown;
9
+ onReady: (toplineService: ToplineService, user: ToplineUser | null, isUserKnown: boolean) => unknown;
10
10
  onError: (err: Error) => unknown;
11
11
  };
12
12
  declare const _default: React.Context<InnerToplineContext>;
@@ -29,12 +29,14 @@ export default function LoggedOutUserMenu(props) {
29
29
  label: "Войти" + '...',
30
30
  itemRef: menuItemRefs[0],
31
31
  tabIndex: currItemIdx === 0 ? 0 : -1,
32
+ testId: 'login_item',
32
33
  onKeyDown: handleKeyDown.bind(null, 'login'),
33
34
  onClick: handleSelect.bind(null, 'login')
34
35
  }), _jsx(UserMenuItem, {
35
36
  label: "Создать аккаунт" + '...',
36
37
  itemRef: menuItemRefs[1],
37
38
  tabIndex: currItemIdx === 1 ? 0 : -1,
39
+ testId: 'signup_item',
38
40
  onKeyDown: handleKeyDown.bind(null, 'signup'),
39
41
  onClick: handleSelect.bind(null, 'signup')
40
42
  })]
@@ -29,12 +29,14 @@ export default function LoggedInUserMenu(props) {
29
29
  label: "Мой профиль" + '...',
30
30
  itemRef: menuItemRefs[0],
31
31
  tabIndex: currItemIdx === 0 ? 0 : -1,
32
+ testId: 'profile_item',
32
33
  onKeyDown: handleKeyDown.bind(null, 'profile'),
33
34
  onClick: handleSelect.bind(null, 'profile')
34
35
  }), _jsx(UserMenuItem, {
35
36
  label: "Выйти" + '',
36
37
  itemRef: menuItemRefs[1],
37
38
  tabIndex: currItemIdx === 1 ? 0 : -1,
39
+ testId: 'logout_item',
38
40
  onKeyDown: handleKeyDown.bind(null, 'logout'),
39
41
  onClick: handleSelect.bind(null, 'logout')
40
42
  })]
@@ -11,7 +11,7 @@ import { PasswordRecovery } from '../../../password-recovery/index.js';
11
11
  import { Profile } from '../../../profile/index.js';
12
12
  import ToplineContext from '../../context.js';
13
13
  import { globalRefs } from '../../../../modules/focus-marshal/index.js';
14
- import { initDb, getAllData } from '../../../../modules/local-db/index.js';
14
+ import { initDb, getAllData, getIsUserKnown } from '../../../../modules/local-db/index.js';
15
15
  import { logError } from '../../../../modules/logger/index.js';
16
16
  import { setGrantToken, setRefreshToken } from '../../../../modules/tokens/index.js';
17
17
  import { toplineService, innerToplineService, ToplineEventName, InnerToplineEventName } from '../../../../modules/topline-service/index.js';
@@ -27,8 +27,10 @@ export default function Shell() {
27
27
  const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
28
28
  const [modalWindowActive, setModalWindowOpen] = useState(null);
29
29
  const handleRenderingError = useCallback(e => {
30
- logError(e);
31
- onError(e);
30
+ if (e instanceof Error) {
31
+ logError(e);
32
+ onError(e);
33
+ }
32
34
  }, [onError]);
33
35
  const handleClickOnUserAvatar = useCallback(isOpen => setIsUserMenuOpen(isOpen), []);
34
36
  const closeUserMenu = useCallback(() => {
@@ -68,6 +70,8 @@ export default function Shell() {
68
70
  const handleMoveToLogin = useCallback(() => setModalWindowOpen('login'), []);
69
71
  useEffect(() => {
70
72
  async function initData() {
73
+ innerToplineService.on(ToplineEventName.Login, handleUserChange);
74
+ innerToplineService.on(ToplineEventName.Signup, handleUserChange);
71
75
  innerToplineService.on(ToplineEventName.UserChange, handleUserChange);
72
76
  innerToplineService.on(ToplineEventName.Logout, () => handleUserChange(null));
73
77
  try {
@@ -76,7 +80,7 @@ export default function Shell() {
76
80
  if (e instanceof Error) {
77
81
  logError(e);
78
82
  }
79
- onReady(toplineService, null);
83
+ onReady(toplineService, null, true);
80
84
  return;
81
85
  }
82
86
  const {
@@ -87,7 +91,9 @@ export default function Shell() {
87
91
  handleUserChange(user);
88
92
  setGrantToken(grantToken);
89
93
  setRefreshToken(refreshToken);
90
- onReady(toplineService, user);
94
+ const isUserKnownResult = await getIsUserKnown();
95
+ const isUserKnown = isUserKnownResult.ok ? isUserKnownResult.value : true;
96
+ onReady(toplineService, user, isUserKnown);
91
97
  if (user) {
92
98
  await refreshUser(user);
93
99
  openWebsocket();
@@ -4,6 +4,7 @@ type Props = {
4
4
  itemRef: React.RefObject<HTMLDivElement | null>;
5
5
  tabIndex: number;
6
6
  onKeyDown: (e: React.KeyboardEvent) => unknown;
7
+ testId?: string;
7
8
  onClick: () => unknown;
8
9
  };
9
10
  export default function UserMenuItem(props: Props): JSX.Element;