@peassoft/mnr-web-topline 0.1.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 (255) hide show
  1. package/README.md +44 -0
  2. package/dist/css/index.css +192 -0
  3. package/dist/en/hooks/use-topline/index.d.ts +11 -0
  4. package/dist/en/hooks/use-topline/index.js +14 -0
  5. package/dist/en/index.d.ts +8 -0
  6. package/dist/en/index.js +5 -0
  7. package/dist/en/modules/env/index.d.ts +12 -0
  8. package/dist/en/modules/env/index.js +27 -0
  9. package/dist/en/modules/focus-marshal/index.d.ts +6 -0
  10. package/dist/en/modules/focus-marshal/index.js +6 -0
  11. package/dist/en/modules/keyboard-navigation/key-codes.d.ts +18 -0
  12. package/dist/en/modules/keyboard-navigation/key-codes.js +18 -0
  13. package/dist/en/modules/keyboard-navigation/vertical-menu.d.ts +14 -0
  14. package/dist/en/modules/keyboard-navigation/vertical-menu.js +45 -0
  15. package/dist/en/modules/local-db/actions/delete-all-data/index.d.ts +4 -0
  16. package/dist/en/modules/local-db/actions/delete-all-data/index.js +21 -0
  17. package/dist/en/modules/local-db/actions/get-all-data/index.d.ts +11 -0
  18. package/dist/en/modules/local-db/actions/get-all-data/index.js +51 -0
  19. package/dist/en/modules/local-db/actions/update-grant-token/index.d.ts +4 -0
  20. package/dist/en/modules/local-db/actions/update-grant-token/index.js +26 -0
  21. package/dist/en/modules/local-db/actions/update-refresh-token/index.d.ts +4 -0
  22. package/dist/en/modules/local-db/actions/update-refresh-token/index.js +26 -0
  23. package/dist/en/modules/local-db/actions/update-user/index.d.ts +5 -0
  24. package/dist/en/modules/local-db/actions/update-user/index.js +26 -0
  25. package/dist/en/modules/local-db/create-request-error.d.ts +5 -0
  26. package/dist/en/modules/local-db/create-request-error.js +9 -0
  27. package/dist/en/modules/local-db/index.d.ts +6 -0
  28. package/dist/en/modules/local-db/index.js +6 -0
  29. package/dist/en/modules/local-db/init-db.d.ts +17 -0
  30. package/dist/en/modules/local-db/init-db.js +52 -0
  31. package/dist/en/modules/logger/index.d.ts +1 -0
  32. package/dist/en/modules/logger/index.js +3 -0
  33. package/dist/en/modules/request/index.d.ts +20 -0
  34. package/dist/en/modules/request/index.js +78 -0
  35. package/dist/en/modules/request/normalize-request-opts.d.ts +5 -0
  36. package/dist/en/modules/request/normalize-request-opts.js +11 -0
  37. package/dist/en/modules/request/should-retry.d.ts +6 -0
  38. package/dist/en/modules/request/should-retry.js +16 -0
  39. package/dist/en/modules/request/types.d.ts +20 -0
  40. package/dist/en/modules/request/types.js +1 -0
  41. package/dist/en/modules/tokens/index.d.ts +4 -0
  42. package/dist/en/modules/tokens/index.js +14 -0
  43. package/dist/en/modules/topline-service/index.d.ts +24 -0
  44. package/dist/en/modules/topline-service/index.js +46 -0
  45. package/dist/en/modules/topline-service/inner-service.d.ts +45 -0
  46. package/dist/en/modules/topline-service/inner-service.js +219 -0
  47. package/dist/en/modules/topline-service/types.d.ts +32 -0
  48. package/dist/en/modules/topline-service/types.js +19 -0
  49. package/dist/en/modules/validators/email.d.ts +4 -0
  50. package/dist/en/modules/validators/email.js +7 -0
  51. package/dist/en/modules/validators/password-recovery-code.d.ts +4 -0
  52. package/dist/en/modules/validators/password-recovery-code.js +6 -0
  53. package/dist/en/modules/validators/password.d.ts +4 -0
  54. package/dist/en/modules/validators/password.js +6 -0
  55. package/dist/en/modules/websocket/index.d.ts +4 -0
  56. package/dist/en/modules/websocket/index.js +92 -0
  57. package/dist/en/parts/login/actions/perform-login/index.d.ts +27 -0
  58. package/dist/en/parts/login/actions/perform-login/index.js +60 -0
  59. package/dist/en/parts/login/index.d.ts +1 -0
  60. package/dist/en/parts/login/index.js +1 -0
  61. package/dist/en/parts/login/ui/login/index.d.ts +8 -0
  62. package/dist/en/parts/login/ui/login/index.js +138 -0
  63. package/dist/en/parts/logout/actions/perform-logout/index.d.ts +23 -0
  64. package/dist/en/parts/logout/actions/perform-logout/index.js +54 -0
  65. package/dist/en/parts/logout/actions/perform-logout/make-second-attempt.d.ts +1 -0
  66. package/dist/en/parts/logout/actions/perform-logout/make-second-attempt.js +3 -0
  67. package/dist/en/parts/logout/index.d.ts +1 -0
  68. package/dist/en/parts/logout/index.js +1 -0
  69. package/dist/en/parts/password-recovery/actions/create-claim/index.d.ts +22 -0
  70. package/dist/en/parts/password-recovery/actions/create-claim/index.js +41 -0
  71. package/dist/en/parts/password-recovery/actions/save-password/index.d.ts +27 -0
  72. package/dist/en/parts/password-recovery/actions/save-password/index.js +61 -0
  73. package/dist/en/parts/password-recovery/index.d.ts +1 -0
  74. package/dist/en/parts/password-recovery/index.js +1 -0
  75. package/dist/en/parts/password-recovery/ui/password-recovery/index.d.ts +6 -0
  76. package/dist/en/parts/password-recovery/ui/password-recovery/index.js +33 -0
  77. package/dist/en/parts/password-recovery/ui/step-one/index.d.ts +7 -0
  78. package/dist/en/parts/password-recovery/ui/step-one/index.js +82 -0
  79. package/dist/en/parts/password-recovery/ui/step-two/index.d.ts +7 -0
  80. package/dist/en/parts/password-recovery/ui/step-two/index.js +134 -0
  81. package/dist/en/parts/shell/actions/refresh-user/has-user-been-changed.d.ts +5 -0
  82. package/dist/en/parts/shell/actions/refresh-user/has-user-been-changed.js +6 -0
  83. package/dist/en/parts/shell/actions/refresh-user/index.d.ts +28 -0
  84. package/dist/en/parts/shell/actions/refresh-user/index.js +79 -0
  85. package/dist/en/parts/shell/actions/refresh-user/make-second-attempt.d.ts +2 -0
  86. package/dist/en/parts/shell/actions/refresh-user/make-second-attempt.js +3 -0
  87. package/dist/en/parts/shell/context.d.ts +12 -0
  88. package/dist/en/parts/shell/context.js +8 -0
  89. package/dist/en/parts/shell/index.d.ts +2 -0
  90. package/dist/en/parts/shell/index.js +2 -0
  91. package/dist/en/parts/shell/ui/logged-out-user-menu/index.d.ts +8 -0
  92. package/dist/en/parts/shell/ui/logged-out-user-menu/index.js +42 -0
  93. package/dist/en/parts/shell/ui/loggeg-in-user-menu/index.d.ts +8 -0
  94. package/dist/en/parts/shell/ui/loggeg-in-user-menu/index.js +42 -0
  95. package/dist/en/parts/shell/ui/logo/index.d.ts +1 -0
  96. package/dist/en/parts/shell/ui/logo/index.js +8 -0
  97. package/dist/en/parts/shell/ui/logo/logo-full.d.ts +2 -0
  98. package/dist/en/parts/shell/ui/logo/logo-full.js +26 -0
  99. package/dist/en/parts/shell/ui/logo/logo-short.d.ts +2 -0
  100. package/dist/en/parts/shell/ui/logo/logo-short.js +26 -0
  101. package/dist/en/parts/shell/ui/shell/index.d.ts +2 -0
  102. package/dist/en/parts/shell/ui/shell/index.js +187 -0
  103. package/dist/en/parts/shell/ui/user-avatar/index.d.ts +7 -0
  104. package/dist/en/parts/shell/ui/user-avatar/index.js +48 -0
  105. package/dist/en/parts/shell/ui/user-menu/index.d.ts +8 -0
  106. package/dist/en/parts/shell/ui/user-menu/index.js +37 -0
  107. package/dist/en/parts/shell/ui/user-menu-item/index.d.ts +10 -0
  108. package/dist/en/parts/shell/ui/user-menu-item/index.js +19 -0
  109. package/dist/en/parts/signup/actions/perform-signup/index.d.ts +33 -0
  110. package/dist/en/parts/signup/actions/perform-signup/index.js +58 -0
  111. package/dist/en/parts/signup/index.d.ts +1 -0
  112. package/dist/en/parts/signup/index.js +1 -0
  113. package/dist/en/parts/signup/ui/signup/index.d.ts +8 -0
  114. package/dist/en/parts/signup/ui/signup/index.js +163 -0
  115. package/dist/en/shared/components/alternative/index.d.ts +7 -0
  116. package/dist/en/shared/components/alternative/index.js +3 -0
  117. package/dist/en/shared/components/modal/index.d.ts +8 -0
  118. package/dist/en/shared/components/modal/index.js +32 -0
  119. package/dist/en/shared/procedures/process-successful-response/index.d.ts +30 -0
  120. package/dist/en/shared/procedures/process-successful-response/index.js +66 -0
  121. package/dist/en/topline.d.ts +24 -0
  122. package/dist/en/topline.js +33 -0
  123. package/dist/en/types/app.d.ts +1 -0
  124. package/dist/en/types/app.js +1 -0
  125. package/dist/en/types/data.d.ts +10 -0
  126. package/dist/en/types/data.js +4 -0
  127. package/dist/en/types/helpers.d.ts +2 -0
  128. package/dist/en/types/helpers.js +3 -0
  129. package/dist/ru/hooks/use-topline/index.d.ts +11 -0
  130. package/dist/ru/hooks/use-topline/index.js +14 -0
  131. package/dist/ru/index.d.ts +8 -0
  132. package/dist/ru/index.js +5 -0
  133. package/dist/ru/modules/env/index.d.ts +12 -0
  134. package/dist/ru/modules/env/index.js +27 -0
  135. package/dist/ru/modules/focus-marshal/index.d.ts +6 -0
  136. package/dist/ru/modules/focus-marshal/index.js +6 -0
  137. package/dist/ru/modules/keyboard-navigation/key-codes.d.ts +18 -0
  138. package/dist/ru/modules/keyboard-navigation/key-codes.js +18 -0
  139. package/dist/ru/modules/keyboard-navigation/vertical-menu.d.ts +14 -0
  140. package/dist/ru/modules/keyboard-navigation/vertical-menu.js +45 -0
  141. package/dist/ru/modules/local-db/actions/delete-all-data/index.d.ts +4 -0
  142. package/dist/ru/modules/local-db/actions/delete-all-data/index.js +21 -0
  143. package/dist/ru/modules/local-db/actions/get-all-data/index.d.ts +11 -0
  144. package/dist/ru/modules/local-db/actions/get-all-data/index.js +51 -0
  145. package/dist/ru/modules/local-db/actions/update-grant-token/index.d.ts +4 -0
  146. package/dist/ru/modules/local-db/actions/update-grant-token/index.js +26 -0
  147. package/dist/ru/modules/local-db/actions/update-refresh-token/index.d.ts +4 -0
  148. package/dist/ru/modules/local-db/actions/update-refresh-token/index.js +26 -0
  149. package/dist/ru/modules/local-db/actions/update-user/index.d.ts +5 -0
  150. package/dist/ru/modules/local-db/actions/update-user/index.js +26 -0
  151. package/dist/ru/modules/local-db/create-request-error.d.ts +5 -0
  152. package/dist/ru/modules/local-db/create-request-error.js +9 -0
  153. package/dist/ru/modules/local-db/index.d.ts +6 -0
  154. package/dist/ru/modules/local-db/index.js +6 -0
  155. package/dist/ru/modules/local-db/init-db.d.ts +17 -0
  156. package/dist/ru/modules/local-db/init-db.js +52 -0
  157. package/dist/ru/modules/logger/index.d.ts +1 -0
  158. package/dist/ru/modules/logger/index.js +3 -0
  159. package/dist/ru/modules/request/index.d.ts +20 -0
  160. package/dist/ru/modules/request/index.js +78 -0
  161. package/dist/ru/modules/request/normalize-request-opts.d.ts +5 -0
  162. package/dist/ru/modules/request/normalize-request-opts.js +11 -0
  163. package/dist/ru/modules/request/should-retry.d.ts +6 -0
  164. package/dist/ru/modules/request/should-retry.js +16 -0
  165. package/dist/ru/modules/request/types.d.ts +20 -0
  166. package/dist/ru/modules/request/types.js +1 -0
  167. package/dist/ru/modules/tokens/index.d.ts +4 -0
  168. package/dist/ru/modules/tokens/index.js +14 -0
  169. package/dist/ru/modules/topline-service/index.d.ts +24 -0
  170. package/dist/ru/modules/topline-service/index.js +46 -0
  171. package/dist/ru/modules/topline-service/inner-service.d.ts +45 -0
  172. package/dist/ru/modules/topline-service/inner-service.js +219 -0
  173. package/dist/ru/modules/topline-service/types.d.ts +32 -0
  174. package/dist/ru/modules/topline-service/types.js +19 -0
  175. package/dist/ru/modules/validators/email.d.ts +4 -0
  176. package/dist/ru/modules/validators/email.js +7 -0
  177. package/dist/ru/modules/validators/password-recovery-code.d.ts +4 -0
  178. package/dist/ru/modules/validators/password-recovery-code.js +6 -0
  179. package/dist/ru/modules/validators/password.d.ts +4 -0
  180. package/dist/ru/modules/validators/password.js +6 -0
  181. package/dist/ru/modules/websocket/index.d.ts +4 -0
  182. package/dist/ru/modules/websocket/index.js +92 -0
  183. package/dist/ru/parts/login/actions/perform-login/index.d.ts +27 -0
  184. package/dist/ru/parts/login/actions/perform-login/index.js +60 -0
  185. package/dist/ru/parts/login/index.d.ts +1 -0
  186. package/dist/ru/parts/login/index.js +1 -0
  187. package/dist/ru/parts/login/ui/login/index.d.ts +8 -0
  188. package/dist/ru/parts/login/ui/login/index.js +138 -0
  189. package/dist/ru/parts/logout/actions/perform-logout/index.d.ts +23 -0
  190. package/dist/ru/parts/logout/actions/perform-logout/index.js +54 -0
  191. package/dist/ru/parts/logout/actions/perform-logout/make-second-attempt.d.ts +1 -0
  192. package/dist/ru/parts/logout/actions/perform-logout/make-second-attempt.js +3 -0
  193. package/dist/ru/parts/logout/index.d.ts +1 -0
  194. package/dist/ru/parts/logout/index.js +1 -0
  195. package/dist/ru/parts/password-recovery/actions/create-claim/index.d.ts +22 -0
  196. package/dist/ru/parts/password-recovery/actions/create-claim/index.js +41 -0
  197. package/dist/ru/parts/password-recovery/actions/save-password/index.d.ts +27 -0
  198. package/dist/ru/parts/password-recovery/actions/save-password/index.js +61 -0
  199. package/dist/ru/parts/password-recovery/index.d.ts +1 -0
  200. package/dist/ru/parts/password-recovery/index.js +1 -0
  201. package/dist/ru/parts/password-recovery/ui/password-recovery/index.d.ts +6 -0
  202. package/dist/ru/parts/password-recovery/ui/password-recovery/index.js +33 -0
  203. package/dist/ru/parts/password-recovery/ui/step-one/index.d.ts +7 -0
  204. package/dist/ru/parts/password-recovery/ui/step-one/index.js +82 -0
  205. package/dist/ru/parts/password-recovery/ui/step-two/index.d.ts +7 -0
  206. package/dist/ru/parts/password-recovery/ui/step-two/index.js +134 -0
  207. package/dist/ru/parts/shell/actions/refresh-user/has-user-been-changed.d.ts +5 -0
  208. package/dist/ru/parts/shell/actions/refresh-user/has-user-been-changed.js +6 -0
  209. package/dist/ru/parts/shell/actions/refresh-user/index.d.ts +28 -0
  210. package/dist/ru/parts/shell/actions/refresh-user/index.js +79 -0
  211. package/dist/ru/parts/shell/actions/refresh-user/make-second-attempt.d.ts +2 -0
  212. package/dist/ru/parts/shell/actions/refresh-user/make-second-attempt.js +3 -0
  213. package/dist/ru/parts/shell/context.d.ts +12 -0
  214. package/dist/ru/parts/shell/context.js +8 -0
  215. package/dist/ru/parts/shell/index.d.ts +2 -0
  216. package/dist/ru/parts/shell/index.js +2 -0
  217. package/dist/ru/parts/shell/ui/logged-out-user-menu/index.d.ts +8 -0
  218. package/dist/ru/parts/shell/ui/logged-out-user-menu/index.js +42 -0
  219. package/dist/ru/parts/shell/ui/loggeg-in-user-menu/index.d.ts +8 -0
  220. package/dist/ru/parts/shell/ui/loggeg-in-user-menu/index.js +42 -0
  221. package/dist/ru/parts/shell/ui/logo/index.d.ts +1 -0
  222. package/dist/ru/parts/shell/ui/logo/index.js +8 -0
  223. package/dist/ru/parts/shell/ui/logo/logo-full.d.ts +2 -0
  224. package/dist/ru/parts/shell/ui/logo/logo-full.js +26 -0
  225. package/dist/ru/parts/shell/ui/logo/logo-short.d.ts +2 -0
  226. package/dist/ru/parts/shell/ui/logo/logo-short.js +26 -0
  227. package/dist/ru/parts/shell/ui/shell/index.d.ts +2 -0
  228. package/dist/ru/parts/shell/ui/shell/index.js +187 -0
  229. package/dist/ru/parts/shell/ui/user-avatar/index.d.ts +7 -0
  230. package/dist/ru/parts/shell/ui/user-avatar/index.js +48 -0
  231. package/dist/ru/parts/shell/ui/user-menu/index.d.ts +8 -0
  232. package/dist/ru/parts/shell/ui/user-menu/index.js +37 -0
  233. package/dist/ru/parts/shell/ui/user-menu-item/index.d.ts +10 -0
  234. package/dist/ru/parts/shell/ui/user-menu-item/index.js +19 -0
  235. package/dist/ru/parts/signup/actions/perform-signup/index.d.ts +33 -0
  236. package/dist/ru/parts/signup/actions/perform-signup/index.js +58 -0
  237. package/dist/ru/parts/signup/index.d.ts +1 -0
  238. package/dist/ru/parts/signup/index.js +1 -0
  239. package/dist/ru/parts/signup/ui/signup/index.d.ts +8 -0
  240. package/dist/ru/parts/signup/ui/signup/index.js +163 -0
  241. package/dist/ru/shared/components/alternative/index.d.ts +7 -0
  242. package/dist/ru/shared/components/alternative/index.js +3 -0
  243. package/dist/ru/shared/components/modal/index.d.ts +8 -0
  244. package/dist/ru/shared/components/modal/index.js +32 -0
  245. package/dist/ru/shared/procedures/process-successful-response/index.d.ts +30 -0
  246. package/dist/ru/shared/procedures/process-successful-response/index.js +66 -0
  247. package/dist/ru/topline.d.ts +24 -0
  248. package/dist/ru/topline.js +33 -0
  249. package/dist/ru/types/app.d.ts +1 -0
  250. package/dist/ru/types/app.js +1 -0
  251. package/dist/ru/types/data.d.ts +10 -0
  252. package/dist/ru/types/data.js +4 -0
  253. package/dist/ru/types/helpers.d.ts +2 -0
  254. package/dist/ru/types/helpers.js +3 -0
  255. package/package.json +75 -0
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Validate secret code for password recovery
3
+ */
4
+ export default function validatePasswordRecoveryCode(secretCode) {
5
+ return secretCode !== '';
6
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Validate password
3
+ */
4
+ export default function validatePassword(password: string): boolean;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Validate password
3
+ */
4
+ export default function validatePassword(password) {
5
+ return password !== '';
6
+ }
@@ -0,0 +1,4 @@
1
+ /** Open websocket */
2
+ export declare function openWebsocket(): void;
3
+ /** Close websocket */
4
+ export declare function closeWebsocket(): void;
@@ -0,0 +1,92 @@
1
+ import WebError from '@memnrev/web-error';
2
+ import { getWebsocketUrl } from '../env/index.js';
3
+ import { getGrantToken } from '../tokens/index.js';
4
+ import { logError } from '../logger/index.js';
5
+ import { innerToplineService, ToplineEventName } from '../topline-service/index.js';
6
+ import { isObject } from '../../types/helpers.js';
7
+ let activeSocket = null;
8
+ let currConnectionRetries = 0;
9
+ const MAX_RECONNECTION_DELAY_MS = 30000;
10
+ const closeCodes = {
11
+ // We have closed the connection by ourselves
12
+ INITIATED_BY_OURSELVES: 1000,
13
+ // Connection is closed by server
14
+ INITIATED_BY_SERVER: 1001,
15
+ // No status code is actually present in a Close control frame
16
+ WITHOUT_STATUS_CODE: 1005,
17
+ // Connection was closed abnormally, e.g., without sending or receiving a Close control frame.
18
+ // This includes the case of connection handshake failure.
19
+ NETWORK_PROBLEM: 1006,
20
+ // Grant token is not verified/expired
21
+ BY_SERVER_INVALID_GRANT_TOKEN: 4401
22
+ };
23
+ /** Handle incoming message from websocket */
24
+ function handleSocketMessage(e) {
25
+ if (e.data === 'logout') {
26
+ innerToplineService.processLogout();
27
+ closeWebsocket();
28
+ } else {
29
+ const message = JSON.parse(e.data);
30
+ if (isObject(message) && 'syncId' in message && typeof message.syncId === 'string') {
31
+ innerToplineService.emit(ToplineEventName.SyncNotification, message.syncId);
32
+ }
33
+ }
34
+ }
35
+ /** Open websocket */
36
+ export function openWebsocket() {
37
+ closeWebsocket();
38
+ const wsUrl = getWebsocketUrl();
39
+ const socket = new window.WebSocket(wsUrl);
40
+ socket.addEventListener('open', handleSocketOpen);
41
+ socket.addEventListener('close', e => void handleSocketClose(e));
42
+ socket.addEventListener('message', handleSocketMessage);
43
+ activeSocket = socket;
44
+ currConnectionRetries = 0;
45
+ }
46
+ /** Close websocket */
47
+ export function closeWebsocket() {
48
+ if (activeSocket) {
49
+ activeSocket.close(closeCodes.INITIATED_BY_OURSELVES);
50
+ }
51
+ }
52
+ /** Handle for websocket "open" event */
53
+ function handleSocketOpen() {
54
+ this.send(JSON.stringify({
55
+ type: 'connection',
56
+ data: {
57
+ grantToken: getGrantToken()
58
+ }
59
+ }));
60
+ }
61
+ /** Handle websocket "close" event */
62
+ async function handleSocketClose(e) {
63
+ activeSocket = null;
64
+ switch (e.code) {
65
+ case closeCodes.INITIATED_BY_OURSELVES:
66
+ break;
67
+ case closeCodes.INITIATED_BY_SERVER:
68
+ case closeCodes.WITHOUT_STATUS_CODE:
69
+ case closeCodes.NETWORK_PROBLEM:
70
+ reconnect();
71
+ break;
72
+ case closeCodes.BY_SERVER_INVALID_GRANT_TOKEN:
73
+ if (await innerToplineService.upgradeGrantToken()) {
74
+ reconnect();
75
+ }
76
+ break;
77
+ default:
78
+ // Unexpected closing code
79
+ logError(new WebError({
80
+ name: 'UnexpectedWsClosingCode'
81
+ }, `websocket was closed with unexpected code ${e.code}`));
82
+ reconnect();
83
+ }
84
+ }
85
+ /** Make re-connection try */
86
+ function reconnect() {
87
+ let delay = 2 ** ++currConnectionRetries * 2000;
88
+ if (delay > MAX_RECONNECTION_DELAY_MS) {
89
+ delay = MAX_RECONNECTION_DELAY_MS;
90
+ }
91
+ setTimeout(openWebsocket, delay);
92
+ }
@@ -0,0 +1,27 @@
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
+ import type { ToplineUser } from '../../../../types/data.js';
6
+ export type ReturnValue = {
7
+ user: ToplineUser | null;
8
+ error: 'network' | 'incorrect-credentials' | null;
9
+ };
10
+ /**
11
+ * Perform logging-in
12
+ *
13
+ * Return `null` if login succeeds; otherwise:
14
+ * - on network error or if backend responds with 5xx - "network";
15
+ * - on login failure - "incorrect-credentials".
16
+ */
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;
@@ -0,0 +1,60 @@
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
+ /**
6
+ * Perform logging-in
7
+ *
8
+ * Return `null` if login succeeds; otherwise:
9
+ * - on network error or if backend responds with 5xx - "network";
10
+ * - on login failure - "incorrect-credentials".
11
+ */
12
+ async function performLogin(email, password) {
13
+ const url = `${this.getApiBaseUrl()}/public/login-with-credentials`;
14
+ const options = {
15
+ method: 'POST',
16
+ headers: {
17
+ 'Content-Type': 'application/json; charset=utf-8'
18
+ },
19
+ body: JSON.stringify({
20
+ email,
21
+ password
22
+ }),
23
+ credentials: this.getRequestCredentialsMode(),
24
+ cache: 'no-store',
25
+ redirect: 'error'
26
+ };
27
+ const response = await this.request(url, options, {
28
+ maxRetries: 1
29
+ });
30
+ if (!response) {
31
+ return {
32
+ user: null,
33
+ error: 'network'
34
+ };
35
+ }
36
+ if (response.status === 200) {
37
+ return await this.processSuccessfulResponse(response, url);
38
+ }
39
+ if (response.status === 401) {
40
+ return {
41
+ user: null,
42
+ error: 'incorrect-credentials'
43
+ };
44
+ }
45
+ // This code is actually unreachable as `request` returns `null` in case of unexpected
46
+ // status code. The code is added to preserve formal function API.
47
+ return {
48
+ user: null,
49
+ error: 'network'
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());
@@ -0,0 +1 @@
1
+ export { default as Login } from './ui/login/index.js';
@@ -0,0 +1 @@
1
+ export { default as Login } from './ui/login/index.js';
@@ -0,0 +1,8 @@
1
+ import { type JSX } from 'react';
2
+ type Props = {
3
+ onClose: () => unknown;
4
+ onMoveToPasswordRecovery: () => unknown;
5
+ onMoveToSignUp: () => unknown;
6
+ };
7
+ export default function Login(props: Props): JSX.Element;
8
+ export {};
@@ -0,0 +1,138 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useContext, useState, useCallback, useEffect, createRef } from 'react';
3
+ import Modal from '../../../../shared/components/modal/index.js';
4
+ import Alternative from '../../../../shared/components/alternative/index.js';
5
+ import { InputField } from '@peassoft/mnr-web-ui-kit/input-field/index.js';
6
+ import { Button } from '@peassoft/mnr-web-ui-kit/button/index.js';
7
+ import { ErrorMessage } from '@peassoft/mnr-web-ui-kit/error-message/index.js';
8
+ import { ToplineContext } from '../../../shell/index.js';
9
+ import { globalRefs } from '../../../../modules/focus-marshal/index.js';
10
+ import validateEmail from '../../../../modules/validators/email.js';
11
+ import validatePassword from '../../../../modules/validators/password.js';
12
+ import performLogin from '../../actions/perform-login/index.js';
13
+ export default function Login(props) {
14
+ const {
15
+ onClose,
16
+ onMoveToPasswordRecovery,
17
+ onMoveToSignUp
18
+ } = props;
19
+ const lastElementRef = createRef();
20
+ const [email, setEmail] = useState('');
21
+ const [isEmailValid, setIsEmailValid] = useState(true);
22
+ const [password, setPassword] = useState('');
23
+ const [isPasswordValid, setIsPasswordValid] = useState(true);
24
+ const [isMakingRequest, setIsMakingRequest] = useState(false);
25
+ const [errorMessage, setErrorMessage] = useState('');
26
+ const {
27
+ handleUserChange
28
+ } = useContext(ToplineContext);
29
+ const handleEmailChange = useCallback(newValue => setEmail(newValue.trim()), []);
30
+ const handlePasswordChange = useCallback(newValue => setPassword(newValue.trim()), []);
31
+ const handleEmailBlur = useCallback(() => setIsEmailValid(validateEmail(email)), [email]);
32
+ const handlePasswordBlur = useCallback(() => setIsPasswordValid(validatePassword(password)), [password]);
33
+ const handleLogInBtnClick = useCallback(async () => {
34
+ let hasFormValidationFailed = false;
35
+ if (!validateEmail(email)) {
36
+ setIsEmailValid(false);
37
+ hasFormValidationFailed = true;
38
+ }
39
+ if (!validatePassword(password)) {
40
+ setIsPasswordValid(false);
41
+ hasFormValidationFailed = true;
42
+ }
43
+ if (hasFormValidationFailed) return;
44
+ setIsMakingRequest(true);
45
+ const {
46
+ user,
47
+ error
48
+ } = await performLogin(email, password);
49
+ if (user && !error) {
50
+ onClose();
51
+ handleUserChange(user);
52
+ return;
53
+ }
54
+ setIsMakingRequest(false);
55
+ switch (error) {
56
+ case 'network':
57
+ setErrorMessage("Сервер недоступен. Попробуйте повторить позже.");
58
+ break;
59
+ case 'incorrect-credentials':
60
+ setErrorMessage("Неправильное имя пользователя и/или пароль.");
61
+ break;
62
+ default:
63
+ throw new Error('Unknown error of a login request');
64
+ }
65
+ }, [email, password, onClose, handleUserChange]);
66
+ const handleTabOnLastElement = useCallback(() => globalRefs.modalFirstItem.current?.focus(), []);
67
+ const handleShiftTabOnFirstElement = useCallback(() => lastElementRef.current?.focus(), [lastElementRef]);
68
+ useEffect(() => globalRefs.modalFirstItem.current?.focus(), []);
69
+ return _jsxs(Modal, {
70
+ title: "Войти в аккаунт",
71
+ onClose: onClose,
72
+ children: [_jsxs("form", {
73
+ children: [_jsx(InputField, {
74
+ ref: globalRefs.modalFirstItem,
75
+ type: 'email',
76
+ autocompleteAttribute: 'username',
77
+ label: "Email. Обязательное поле",
78
+ errorMessage: isEmailValid ? '' : "Введите корректный адрес email",
79
+ value: email,
80
+ onChange: handleEmailChange,
81
+ onBlur: handleEmailBlur,
82
+ onShiftTab: handleShiftTabOnFirstElement
83
+ }), _jsx(InputField, {
84
+ type: 'password',
85
+ autocompleteAttribute: 'current-password',
86
+ label: "Пароль. Обязательное поле",
87
+ errorMessage: isPasswordValid ? '' : "Пароль не может быть пустым",
88
+ value: password,
89
+ onChange: handlePasswordChange,
90
+ onBlur: handlePasswordBlur
91
+ }), _jsx(Alternative, {
92
+ condition: () => Boolean(errorMessage),
93
+ true: _jsx(ErrorMessage, {
94
+ variant: 'standalone',
95
+ children: errorMessage
96
+ }),
97
+ false: null
98
+ }), _jsxs("div", {
99
+ className: 'topline_login_btnsCont',
100
+ children: [_jsx(Button, {
101
+ label: "Войти",
102
+ stretched: true,
103
+ isInProgress: isMakingRequest,
104
+ onClick: handleLogInBtnClick
105
+ }), _jsx(Button, {
106
+ label: "Отменить",
107
+ variant: 'secondary',
108
+ stretched: true,
109
+ onClick: onClose
110
+ })]
111
+ })]
112
+ }), _jsxs("div", {
113
+ className: 'topline_login_extraBlock',
114
+ children: [_jsx("p", {
115
+ className: 'topline_login_extraBlockLabel',
116
+ children: "Забыли пароль?"
117
+ }), _jsx(Button, {
118
+ label: "Восстановить пароль",
119
+ variant: 'secondary',
120
+ size: 'small',
121
+ onClick: onMoveToPasswordRecovery
122
+ })]
123
+ }), _jsxs("div", {
124
+ className: 'topline_login_extraBlock',
125
+ children: [_jsx("p", {
126
+ className: 'topline_login_extraBlockLabel',
127
+ children: "Нужен аккаунт?"
128
+ }), _jsx(Button, {
129
+ ref: lastElementRef,
130
+ label: "Создай его сейчас!",
131
+ variant: 'secondary',
132
+ size: 'small',
133
+ onClick: onMoveToSignUp,
134
+ onTab: handleTabOnLastElement
135
+ })]
136
+ })]
137
+ });
138
+ }
@@ -0,0 +1,23 @@
1
+ import stampit from 'stampit';
2
+ import { closeWebsocket } from '../../../../modules/websocket/index.js';
3
+ import { getGrantToken } from '../../../../modules/tokens/index.js';
4
+ import { type InnerService } from '../../../../modules/topline-service/index.js';
5
+ import { getApiBaseUrl } from '../../../../modules/env/index.js';
6
+ import request from '../../../../modules/request/index.js';
7
+ import makeSecondAttempt from './make-second-attempt.js';
8
+ export type This = {
9
+ closeWebsocket: typeof closeWebsocket;
10
+ getGrantToken: typeof getGrantToken;
11
+ innerToplineService: Pick<InnerService, 'processLogout' | 'upgradeGrantToken'>;
12
+ getApiBaseUrl: typeof getApiBaseUrl;
13
+ request: typeof request;
14
+ makeSecondAttempt: typeof makeSecondAttempt;
15
+ performLogout: typeof performLogout;
16
+ };
17
+ export declare const PerformLogout: stampit.Stamp<This>;
18
+ declare const self: () => Promise<void>;
19
+ export default self;
20
+ /**
21
+ * Make logout request to api
22
+ */
23
+ declare function performLogout(this: This): Promise<void>;
@@ -0,0 +1,54 @@
1
+ import stampit from 'stampit';
2
+ import { closeWebsocket } from '../../../../modules/websocket/index.js';
3
+ import { getGrantToken } from '../../../../modules/tokens/index.js';
4
+ import { innerToplineService } from '../../../../modules/topline-service/index.js';
5
+ import { getApiBaseUrl } from '../../../../modules/env/index.js';
6
+ import request from '../../../../modules/request/index.js';
7
+ import makeSecondAttempt from './make-second-attempt.js';
8
+ export const PerformLogout = stampit().props({
9
+ closeWebsocket,
10
+ getGrantToken,
11
+ innerToplineService,
12
+ getApiBaseUrl,
13
+ request,
14
+ makeSecondAttempt
15
+ }).methods({
16
+ performLogout
17
+ });
18
+ const self = performLogout.bind(PerformLogout());
19
+ export default self;
20
+ /**
21
+ * Make logout request to api
22
+ */
23
+ async function performLogout() {
24
+ this.closeWebsocket();
25
+ const grantToken = this.getGrantToken();
26
+ if (!grantToken) {
27
+ this.innerToplineService.processLogout();
28
+ return;
29
+ }
30
+ const url = `${this.getApiBaseUrl()}/private/log-out`;
31
+ const options = {
32
+ method: 'POST',
33
+ headers: {
34
+ Authorization: `Bearer ${grantToken}`
35
+ },
36
+ cache: 'no-store',
37
+ redirect: 'error'
38
+ };
39
+ const response = await this.request(url, options, {
40
+ maxRetries: 1
41
+ });
42
+ if (!response || response.status !== 401) {
43
+ this.innerToplineService.processLogout();
44
+ return;
45
+ }
46
+ if (response.status === 401) {
47
+ // innerToplineService.upgradeGrantToken() makes all necessary clean-up in case
48
+ // the upgrade fails
49
+ const grantToken = await this.innerToplineService.upgradeGrantToken();
50
+ if (grantToken) {
51
+ await this.makeSecondAttempt(self);
52
+ }
53
+ }
54
+ }
@@ -0,0 +1 @@
1
+ export default function makeSecondAttempt(self: () => Promise<void>): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export default async function makeSecondAttempt(self) {
2
+ await self();
3
+ }
@@ -0,0 +1 @@
1
+ export { default as performLogout } from './actions/perform-logout/index.js';
@@ -0,0 +1 @@
1
+ export { default as performLogout } from './actions/perform-logout/index.js';
@@ -0,0 +1,22 @@
1
+ import stampit from 'stampit';
2
+ import { getApiBaseUrl, getRequestCredentialsMode } from '../../../../modules/env/index.js';
3
+ import request from '../../../../modules/request/index.js';
4
+ export type ReturnValue = {
5
+ error: 'network' | null;
6
+ };
7
+ /**
8
+ * Create password recovery claim
9
+ *
10
+ * Returns `null` if claim creation succeeds; otherwise:
11
+ * - on network error or if backend responds with 5xx - "network".
12
+ */
13
+ declare function createClaim(this: This, email: string): Promise<ReturnValue>;
14
+ export type This = {
15
+ getApiBaseUrl: typeof getApiBaseUrl;
16
+ getRequestCredentialsMode: typeof getRequestCredentialsMode;
17
+ request: typeof request;
18
+ createClaim: typeof createClaim;
19
+ };
20
+ export declare const CreateClaim: stampit.Stamp<This>;
21
+ declare const _default: (email: string) => Promise<ReturnValue>;
22
+ export default _default;
@@ -0,0 +1,41 @@
1
+ import stampit from 'stampit';
2
+ import { getApiBaseUrl, getRequestCredentialsMode } from '../../../../modules/env/index.js';
3
+ import request from '../../../../modules/request/index.js';
4
+ /**
5
+ * Create password recovery claim
6
+ *
7
+ * Returns `null` if claim creation succeeds; otherwise:
8
+ * - on network error or if backend responds with 5xx - "network".
9
+ */
10
+ async function createClaim(email) {
11
+ const url = `${this.getApiBaseUrl()}/public/create-password-recovery-claim`;
12
+ const options = {
13
+ method: 'POST',
14
+ headers: {
15
+ 'Content-Type': 'application/json; charset=utf-8'
16
+ },
17
+ body: JSON.stringify({
18
+ email
19
+ }),
20
+ credentials: this.getRequestCredentialsMode(),
21
+ cache: 'no-store',
22
+ redirect: 'error'
23
+ };
24
+ const response = await this.request(url, options);
25
+ if (!response) {
26
+ return {
27
+ error: 'network'
28
+ };
29
+ }
30
+ return {
31
+ error: null
32
+ };
33
+ }
34
+ export const CreateClaim = stampit().props({
35
+ getApiBaseUrl,
36
+ getRequestCredentialsMode,
37
+ request
38
+ }).methods({
39
+ createClaim
40
+ });
41
+ export default createClaim.bind(CreateClaim());
@@ -0,0 +1,27 @@
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
+ import type { ToplineUser } from '../../../../types/data.js';
6
+ export type ReturnValue = {
7
+ user: ToplineUser | null;
8
+ error: 'network' | 'no-claim' | null;
9
+ };
10
+ /**
11
+ * Save new password
12
+ *
13
+ * Returns `null` if sign-up succeeds; otherwise:
14
+ * - on network error or if backend responds with 5xx - "network";
15
+ * - on 403 Forbidden response - "no-claim".
16
+ */
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;
@@ -0,0 +1,61 @@
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
+ /**
6
+ * Save new password
7
+ *
8
+ * Returns `null` if sign-up succeeds; otherwise:
9
+ * - on network error or if backend responds with 5xx - "network";
10
+ * - on 403 Forbidden response - "no-claim".
11
+ */
12
+ async function savePassword(email, password, secretCode) {
13
+ const url = `${this.getApiBaseUrl()}/public/create-new-password`;
14
+ const options = {
15
+ method: 'POST',
16
+ headers: {
17
+ 'Content-Type': 'application/json; charset=utf-8'
18
+ },
19
+ body: JSON.stringify({
20
+ email,
21
+ password,
22
+ secretCode
23
+ }),
24
+ credentials: this.getRequestCredentialsMode(),
25
+ cache: 'no-store',
26
+ redirect: 'error'
27
+ };
28
+ const response = await this.request(url, options, {
29
+ expectedStatusCodes: [200, 403]
30
+ });
31
+ if (!response) {
32
+ return {
33
+ user: null,
34
+ error: 'network'
35
+ };
36
+ }
37
+ if (response.status === 200) {
38
+ return await this.processSuccessfulResponse(response, url);
39
+ }
40
+ if (response.status === 403) {
41
+ return {
42
+ user: null,
43
+ error: 'no-claim'
44
+ };
45
+ }
46
+ // This code is actually unreachable as `request` returns `null` in case of unexpected
47
+ // status code. The code is added to preserve formal function API.
48
+ return {
49
+ user: null,
50
+ error: 'network'
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());
@@ -0,0 +1 @@
1
+ export { default as PasswordRecovery } from './ui/password-recovery/index.js';
@@ -0,0 +1 @@
1
+ export { default as PasswordRecovery } from './ui/password-recovery/index.js';
@@ -0,0 +1,6 @@
1
+ import { type JSX } from 'react';
2
+ type Props = {
3
+ onClose: () => unknown;
4
+ };
5
+ export default function PasswordRecovery(props: Props): JSX.Element;
6
+ export {};
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState, useCallback } from 'react';
3
+ import Modal from '../../../../shared/components/modal/index.js';
4
+ import Alternative from '../../../../shared/components/alternative/index.js';
5
+ import StepOne from '../step-one/index.js';
6
+ import StepTwo from '../step-two/index.js';
7
+ export default function PasswordRecovery(props) {
8
+ const {
9
+ onClose
10
+ } = props;
11
+ const [step, setStep] = useState(1);
12
+ const [email, setEmail] = useState('');
13
+ const condition = useCallback(() => step === 1, [step]);
14
+ const onNext = useCallback(email => {
15
+ setEmail(email);
16
+ setStep(2);
17
+ }, []);
18
+ return _jsx(Modal, {
19
+ title: "Восстановление пароля",
20
+ onClose: onClose,
21
+ children: _jsx(Alternative, {
22
+ condition: condition,
23
+ true: _jsx(StepOne, {
24
+ onNext: onNext,
25
+ onClose: onClose
26
+ }),
27
+ false: _jsx(StepTwo, {
28
+ email: email,
29
+ onClose: onClose
30
+ })
31
+ })
32
+ });
33
+ }
@@ -0,0 +1,7 @@
1
+ import { type JSX } from 'react';
2
+ type Props = {
3
+ onNext: (email: string) => unknown;
4
+ onClose: () => unknown;
5
+ };
6
+ export default function StepOne(props: Props): JSX.Element;
7
+ export {};