namirasoft-account-react 1.4.19 → 1.4.21

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 (76) hide show
  1. package/.env.template +10 -10
  2. package/config-overrides.js +72 -72
  3. package/dist/IEntityInfo.d.ts +11 -11
  4. package/dist/Messages.js.map +1 -1
  5. package/dist/NSARouterMaker.d.ts +0 -1
  6. package/dist/NSARouterMaker.js.map +1 -1
  7. package/dist/Router.d.ts +0 -1
  8. package/dist/components/NSAAccessListDialog.js.map +1 -1
  9. package/dist/components/NSAAccessListDialog.module.css +87 -0
  10. package/dist/components/NSABoxOTP.js.map +1 -1
  11. package/dist/components/NSABoxOTP.module.css +11 -0
  12. package/dist/components/NSAMessageListDialog.js.map +1 -1
  13. package/dist/components/NSAMessageListDialog.module.css +98 -0
  14. package/dist/components/NSAProductListDialog.js.map +1 -1
  15. package/dist/components/NSAProductListDialog.module.css +45 -0
  16. package/dist/components/NSAWorkspaceListDialog.js.map +1 -1
  17. package/dist/components/NSAWorkspaceListDialog.module.css +43 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/layouts/Actions.d.ts +2 -1
  20. package/dist/layouts/Actions.js +38 -17
  21. package/dist/layouts/Actions.js.map +1 -1
  22. package/dist/layouts/NSALayout.d.ts +2 -1
  23. package/dist/layouts/NSALayout.js +58 -37
  24. package/dist/layouts/NSALayout.js.map +1 -1
  25. package/dist/layouts/NSASectionEdit.d.ts +0 -1
  26. package/dist/layouts/NSASectionEdit.js +12 -8
  27. package/dist/layouts/NSASectionEdit.js.map +1 -1
  28. package/dist/layouts/NSASectionList.js +6 -4
  29. package/dist/layouts/NSASectionList.js.map +1 -1
  30. package/dist/layouts/NSASectionTabs.d.ts +0 -1
  31. package/dist/layouts/NSASectionTabs.js +4 -7
  32. package/dist/layouts/NSASectionTabs.js.map +1 -1
  33. package/dist/layouts/NSASectionView.js +4 -3
  34. package/dist/layouts/NSASectionView.js.map +1 -1
  35. package/dist/pages/NSAHomePage.module.css +23 -0
  36. package/dist/pages/NSALoginPage.module.css +20 -0
  37. package/dist/pages/NSAVerificationPage.module.css +23 -0
  38. package/package.json +70 -70
  39. package/public/index.html +21 -21
  40. package/src/App.css +31 -31
  41. package/src/App.tsx +18 -18
  42. package/src/IEntityInfo.ts +31 -31
  43. package/src/INSARouterMaker.ts +7 -7
  44. package/src/INSARouterProps.ts +17 -17
  45. package/src/INSARouterState.ts +5 -5
  46. package/src/Info.ts +20 -20
  47. package/src/Message.ts +6 -6
  48. package/src/Messages.ts +33 -33
  49. package/src/NSARouterMaker.tsx +142 -142
  50. package/src/Router.tsx +39 -39
  51. package/src/components/NSAAccessListDialog.module.css +86 -86
  52. package/src/components/NSAAccessListDialog.tsx +160 -160
  53. package/src/components/NSABoxOTP.module.css +10 -10
  54. package/src/components/NSABoxOTP.tsx +63 -63
  55. package/src/components/NSAMessageListDialog.module.css +97 -97
  56. package/src/components/NSAMessageListDialog.tsx +116 -116
  57. package/src/components/NSAProductListDialog.module.css +44 -44
  58. package/src/components/NSAProductListDialog.tsx +100 -100
  59. package/src/components/NSAWorkspaceListDialog.module.css +42 -42
  60. package/src/components/NSAWorkspaceListDialog.tsx +73 -73
  61. package/src/index.tsx +24 -24
  62. package/src/layouts/Actions.ts +147 -119
  63. package/src/layouts/Menus.ts +15 -15
  64. package/src/layouts/NSALayout.tsx +417 -387
  65. package/src/layouts/NSASectionEdit.tsx +144 -140
  66. package/src/layouts/NSASectionList.tsx +161 -158
  67. package/src/layouts/NSASectionTabs.tsx +152 -156
  68. package/src/layouts/NSASectionView.tsx +61 -60
  69. package/src/main.ts +19 -19
  70. package/src/pages/NSAHomePage.module.css +22 -22
  71. package/src/pages/NSAHomePage.tsx +27 -27
  72. package/src/pages/NSALoginPage.module.css +19 -19
  73. package/src/pages/NSALoginPage.tsx +65 -65
  74. package/src/pages/NSAVerificationPage.module.css +22 -22
  75. package/src/pages/NSAVerificationPage.tsx +59 -59
  76. package/tsconfig.json +43 -43
@@ -1,388 +1,418 @@
1
- import { forwardRef, ReactNode, useEffect, useImperativeHandle, useRef, useState } from 'react';
2
- import { useParams } from 'react-router-dom';
3
- import { EnvService, CacheService, IStorageLocal, NamingConvention } from 'namirasoft-core';
4
- import { NSLayout, IHeaderProps, IBaseComponentProps, IHeaderIconProps, INSBarActionProps, INSBarHeroBannerProps, INSBarNotificationProps, INSBarTitleProps, NSDeleteDialog } from 'namirasoft-site-react';
5
- import { NamirasoftMessageServer } from 'namirasoft-message';
6
- import { NSASectionEdit, NSASectionEditProps, NSASectionEditRef, onApply as NSASectionEdit_onApply } from './NSASectionEdit';
7
- import { NSASectionView, NSASectionViewProps, NSASectionViewRef } from './NSASectionView';
8
- import { NSASectionList, NSASectionListProps } from './NSASectionList';
9
- import { Actions } from './Actions';
10
- import { INSARouterProps } from '../INSARouterProps';
11
- import { IEntityInfo } from '../IEntityInfo';
12
- import { NSAProductListDialog } from '../components/NSAProductListDialog';
13
- import { NSAWorkspaceListDialog } from '../components/NSAWorkspaceListDialog';
14
- import { NSAAccessListDialog } from '../components/NSAAccessListDialog';
15
- import { NSAMessageListDialog } from '../components/NSAMessageListDialog';
16
-
17
- export interface NSALayoutProps<EntityType extends { id: string }, EntityTypeInput = EntityType> extends IBaseComponentProps, INSARouterProps
18
- {
19
- scope: string;
20
- logo: string;
21
- background?: string;
22
- header?: IHeaderProps;
23
- notifications: INSBarNotificationProps[];
24
- action?: INSBarActionProps;
25
- banner?: INSBarHeroBannerProps;
26
- title?: INSBarTitleProps;
27
- pages?: {
28
- entity: IEntityInfo<EntityType, EntityTypeInput>;
29
- ui?: {
30
- action?: {
31
- menus: {
32
- new?: boolean,
33
- view?: boolean,
34
- viewHistory?: boolean,
35
- copy?: boolean,
36
- edit?: boolean,
37
- delete?: boolean,
38
- apply?: boolean,
39
- }
40
- }
41
- }
42
- list?: NSASectionListProps<EntityType>;
43
- edit?: NSASectionEditProps<EntityType, EntityTypeInput>;
44
- view?: NSASectionViewProps<EntityType>;
45
- }
46
- children: ReactNode;
47
- }
48
-
49
- interface NSALayoutState
50
- {
51
- refresher: number;
52
- message_count: number;
53
- showDeleteDialog: boolean;
54
- showMessageListDialog: boolean;
55
- showAccessListDialog: boolean;
56
- showProductListDialog: boolean;
57
- showWorkspaceListDialog: boolean;
58
- }
59
-
60
- export interface NSALayoutRef<EntityType extends { id: string }, EntityTypeInput = EntityType>
61
- {
62
- list: NSASectionList<EntityType, EntityTypeInput> | null;
63
- edit: NSASectionEditRef | null;
64
- view: NSASectionViewRef | null;
65
- }
66
-
67
- export const NSALayout = forwardRef<any, any>(<EntityType extends { id: string }, EntityTypeInput = EntityType>(
68
- props: Omit<NSALayoutProps<EntityType, EntityTypeInput>, "ref">,
69
- ref: React.Ref<NSALayoutRef<EntityType, EntityTypeInput>>
70
- ) =>
71
- {
72
- const NSASectionList_Ref = useRef<NSASectionList<EntityType, EntityTypeInput>>(null);
73
- const NSASectionEdit_Ref = useRef<NSASectionEditRef>(null);
74
- const NSASectionView_Ref = useRef<NSASectionViewRef>(null);
75
-
76
- const [state, setState] = useState<NSALayoutState>({
77
- refresher: 0,
78
- message_count: 0,
79
- showDeleteDialog: false,
80
- showMessageListDialog: false,
81
- showAccessListDialog: false,
82
- showProductListDialog: false,
83
- showWorkspaceListDialog: false
84
- });
85
-
86
- const hideDeleteDialog = () => { setState(prevState => ({ ...prevState, showDeleteDialog: false })); };
87
- const showDeleteDialog = () => { setState(prevState => ({ ...prevState, showDeleteDialog: true })); };
88
-
89
- let icons: IHeaderIconProps[] = [];
90
- let isLoggedIn = props.account.token_manager.exists();
91
- let REACT_APP_BASE_URL_ACCOUNT_CONSOLE = new EnvService("REACT_APP_BASE_URL_ACCOUNT_CONSOLE").getString();
92
-
93
- if (isLoggedIn)
94
- icons.push({
95
- src: "https://static.namirasoft.com/image/concept/logout/white.svg", alt: "Logout", onClicked: () =>
96
- {
97
- window.location.href = REACT_APP_BASE_URL_ACCOUNT_CONSOLE + "/logout";
98
- },
99
- tooltip: "Logout"
100
- });
101
-
102
- // message
103
- let STORAGE_KEY = "ns-messsage-count";
104
- let storage = new IStorageLocal();
105
- let reloadMessageCount: (force: boolean) => void;
106
- let cache_message: CacheService<number> = new CacheService<number>(STORAGE_KEY, 15, storage, async () =>
107
- {
108
- let REACT_APP_BASE_URL_MESSAGE = new EnvService("REACT_APP_BASE_URL_MESSAGE", true).getString();
109
- let server = new NamirasoftMessageServer(REACT_APP_BASE_URL_MESSAGE, props.account.token_manager, console.error);
110
- let res = await server.message.GetNewCount();
111
- return res.count;
112
- }, () => { reloadMessageCount(false); });
113
- reloadMessageCount = (force: boolean) =>
114
- {
115
- if (force)
116
- cache_message.del();
117
- cache_message.get().then(count =>
118
- {
119
- setState(prevState => ({ ...prevState, message_count: count }));
120
- });
121
- }
122
- useEffect(() =>
123
- {
124
- if (isLoggedIn)
125
- reloadMessageCount(false);
126
- // eslint-disable-next-line react-hooks/exhaustive-deps
127
- }, []);
128
- if (isLoggedIn)
129
- {
130
- icons.push({
131
- src: "https://static.namirasoft.com/image/namirasoft/message/logo/base.png", alt: "Message", onClicked: () =>
132
- {
133
- setState(prevState => ({ ...prevState, showMessageListDialog: true }));
134
- },
135
- children: <>
136
- {
137
- (
138
- state.showMessageListDialog &&
139
- <NSAMessageListDialog {...props}
140
- onClose={() => { setState(prevState => ({ ...prevState, showMessageListDialog: false })); }}
141
- onSeenAll={() =>
142
- {
143
- if (reloadMessageCount)
144
- reloadMessageCount(true);
145
- }}
146
- onCountReceived={count =>
147
- {
148
- cache_message.set(count);
149
- setState(prevState => ({ ...prevState, message_count: count }));
150
- }}
151
- />
152
- )
153
- }
154
- </>,
155
- count: state.message_count,
156
- tooltip: "Message"
157
- });
158
- }
159
- if (isLoggedIn)
160
- icons.push({
161
- src: "https://static.namirasoft.com/image/namirasoft/access/logo/base.png", alt: "Access", onClicked: () =>
162
- {
163
- setState(prevState => ({ ...prevState, showAccessListDialog: true }));
164
- },
165
- children: <>
166
- {
167
- (state.showAccessListDialog) && <NSAAccessListDialog {...props} onClose={() =>
168
- {
169
- setState(prevState => ({ ...prevState, showAccessListDialog: false }));
170
- }} />
171
- }
172
-
173
- </>,
174
- tooltip: "Accsess"
175
- });
176
- if (isLoggedIn)
177
- icons.push({
178
- src: "https://static.namirasoft.com/image/namirasoft/workspace/logo/base.png", alt: "Workspace", onClicked: () =>
179
- {
180
- setState(prevState => ({ ...prevState, showWorkspaceListDialog: true }));
181
- },
182
- children: <>
183
- {
184
- (state.showWorkspaceListDialog) && <NSAWorkspaceListDialog {...props} onClose={() =>
185
- {
186
- debugger
187
- setState(prevState => ({ ...prevState, showWorkspaceListDialog: false }));
188
- }} />
189
- }
190
- </>,
191
- tooltip: "Workspace List"
192
- });
193
- icons.push({
194
- src: "https://static.namirasoft.com/image/concept/product-list/white.svg", alt: "Product", onClicked: () =>
195
- {
196
- setState(prevState => ({ ...prevState, showProductListDialog: true }));
197
- },
198
- children: <>
199
- {
200
- (state.showProductListDialog) && <NSAProductListDialog {...props} onClose={() =>
201
- {
202
- setState(prevState => ({ ...prevState, showProductListDialog: false }));
203
- }} >
204
- <></>
205
- </NSAProductListDialog>
206
- }
207
- </>,
208
- tooltip: "Product List"
209
- });
210
-
211
- let name = "";
212
- if (props.pages)
213
- name = NamingConvention.lower_case_underscore.convert(props.pages.entity.name, NamingConvention.Pascal_Case_Space);
214
-
215
- let user_name = props.account.token_manager.getUserData(user => [user.first_name, user.last_name].filter(n => n).join(" "), "");
216
-
217
- let { id } = useParams();
218
-
219
- let getIDs: (() => string[]) | null = null;
220
- if (props.pages?.list)
221
- getIDs = () => { return NSASectionList_Ref.current?.getSelectedIDs() ?? []; };
222
- if (props.pages?.edit)
223
- getIDs = () => [id].filter(id => id) as string[];
224
- if (props.pages?.view)
225
- getIDs = () => [id].filter(id => id) as string[];
226
-
227
- let action: INSBarActionProps | undefined = props.action;
228
- if (!action)
229
- action = { title: "", description: "", menus: {} };
230
-
231
- if (getIDs)
232
- if (props.pages?.entity.client.getMenus)
233
- {
234
- let menus = props.pages?.entity.client.getMenus(getIDs);
235
- for (let key of Object.keys(menus))
236
- {
237
- if (!action.menus[key])
238
- action.menus[key] = [];
239
- action.menus[key].push(...menus[key]);
240
- }
241
- }
242
-
243
- let name_apply = "Apply";
244
- let name_actions = "Actions";
245
- action.menus[name_apply] = [];
246
- action.menus[name_actions] = [];
247
-
248
- if (props.pages?.edit)
249
- {
250
- if (!action.title)
251
- action.title = (props.pages.edit.isEdit ? "Edit" : "New") + " " + name;
252
-
253
- // Menu
254
- if (props.pages.edit.ui.action?.menus.apply ?? true)
255
- action.menus[name_apply].push(Actions.apply(() =>
256
- {
257
- if (props.pages?.edit)
258
- NSASectionEdit_onApply(props.pages?.edit, props.pages.entity, id);
259
- }));
260
- }
261
- else if (props.pages)
262
- if (props.pages.ui?.action?.menus.new ?? true)
263
- action.menus[name_apply].push(Actions.new(props, props.pages.entity));
264
-
265
- if (getIDs)
266
- if (props.pages)
267
- {
268
- if (props.pages.ui?.action?.menus.view ?? true)
269
- action.menus[name_actions].push(Actions.view(props, props.pages.entity, getIDs));
270
- if (props.pages.ui?.action?.menus.viewHistory ?? true)
271
- action.menus[name_actions].push(Actions.viewHistory(getIDs));
272
- if (props.pages.ui?.action?.menus.copy ?? true)
273
- action.menus[name_actions].push(Actions.copy(props, props.pages.entity, getIDs));
274
- if (props.pages.ui?.action?.menus.edit ?? true)
275
- action.menus[name_actions].push(Actions.edit(props, props.pages.entity, getIDs));
276
- if (props.pages.ui?.action?.menus.delete ?? true)
277
- action.menus[name_actions].push(Actions.delete(getIDs, showDeleteDialog));
278
- }
279
-
280
- let action_name = "";
281
- let content;
282
- if (props.pages?.list)
283
- {
284
- action_name = "List";
285
- content = <NSASectionList<EntityType, EntityTypeInput> ref={NSASectionList_Ref} {...props} {...props.pages.list} entity={props.pages.entity} />
286
- }
287
- else if (props.pages?.edit)
288
- {
289
- if (props.pages.edit.isEdit)
290
- action_name = "Edit";
291
- else
292
- action_name = "New";
293
- content = <NSASectionEdit ref={NSASectionEdit_Ref} {...props} {...props.pages.edit} entity={props.pages.entity} >{props.children}</NSASectionEdit>;
294
- }
295
- else if (props.pages?.view)
296
- {
297
- action_name = "View";
298
- content = <NSASectionView ref={NSASectionView_Ref}
299
- {...props}
300
- {...props.pages.view}
301
- entity={props.pages.entity}
302
- />;
303
- }
304
- else
305
- content = props.children;
306
-
307
- let fullname = "";
308
- if (props.pages?.entity.name)
309
- {
310
- let Name_Pascal_Space = NamingConvention.lower_case_underscore.convert(props.pages.entity.name, NamingConvention.Pascal_Case_Space);
311
- fullname = action_name + " " + Name_Pascal_Space;
312
- }
313
- let action_title = action?.title ?? "";
314
- if (!action_title)
315
- action_title = fullname;
316
-
317
- useImperativeHandle(ref, () => ({
318
- list: NSASectionList_Ref.current,
319
- edit: NSASectionEdit_Ref.current,
320
- view: NSASectionView_Ref.current,
321
- }));
322
- return (
323
- <NSLayout
324
- {...props}
325
- header={{
326
- title: (user_name + " " + (props.header?.title ?? "")).trim(),
327
- icons: [...icons, ...(props.header?.icons ?? [])],
328
- logo_title: props.header?.logo_title
329
- }}
330
- action={{
331
- title: action_title,
332
- description: action?.description,
333
- menus: action.menus
334
- }}
335
- isLoggedIn={props.account.token_manager.exists}
336
- >
337
- <div className="container-fluid">
338
- {
339
- state.showDeleteDialog &&
340
- <NSDeleteDialog
341
- title={"Delete Confirmation"}
342
- description={`Are you sure you want to delete ${name}?`}
343
- onClose={hideDeleteDialog}
344
- onNo={hideDeleteDialog}
345
- onYes={async () =>
346
- {
347
- try
348
- {
349
- if (props.pages)
350
- if (getIDs)
351
- {
352
- let ids = getIDs();
353
- if (ids.length === 0)
354
- throw new Error("Nothing was found to delete.");
355
- if (ids.length === 1)
356
- {
357
- await props.pages.entity.server.delete(ids[0]);
358
- props.notifier.onSuccess(`${name} was deleted successfully.`);
359
- hideDeleteDialog();
360
-
361
- if (props.pages?.list)
362
- {
363
- let table = NSASectionList_Ref.current?.NSTable_Main.current;
364
- if (table)
365
- table.reload(null, null);
366
- }
367
- else if (props.pages?.edit)
368
- props.url.redirect(props.pages.entity.client.getListURL(), {});
369
- else if (props.pages?.view)
370
- props.url.redirect(props.pages.entity.client.getListURL(), {});
371
- }
372
- else
373
- // todo support multiple ids deletion
374
- throw new Error("Multiple deletion is not supported yet.");
375
- }
376
- } catch (error: any)
377
- {
378
- props.notifier.onError(error);
379
- }
380
- }}
381
- >
382
- <></>
383
- </NSDeleteDialog>}
384
- {content}
385
- </div>
386
- </NSLayout>
387
- );
1
+ import { forwardRef, ReactNode, useEffect, useImperativeHandle, useRef, useState } from 'react';
2
+ import { useParams } from 'react-router-dom';
3
+ import { EnvService, CacheService, IStorageLocal, NamingConvention } from 'namirasoft-core';
4
+ import { NSLayout, IHeaderProps, IBaseComponentProps, IHeaderIconProps, INSBarActionProps, INSBarHeroBannerProps, INSBarNotificationProps, INSBarTitleProps, NSDeleteDialog } from 'namirasoft-site-react';
5
+ import { NamirasoftMessageServer } from 'namirasoft-message';
6
+ import { NSASectionEdit, NSASectionEditProps, NSASectionEditRef, onApply as NSASectionEdit_onApply } from './NSASectionEdit';
7
+ import { NSASectionView, NSASectionViewProps, NSASectionViewRef } from './NSASectionView';
8
+ import { NSASectionList, NSASectionListProps } from './NSASectionList';
9
+ import { Actions } from './Actions';
10
+ import { INSARouterProps } from '../INSARouterProps';
11
+ import { IEntityInfo } from '../IEntityInfo';
12
+ import { NSAProductListDialog } from '../components/NSAProductListDialog';
13
+ import { NSAWorkspaceListDialog } from '../components/NSAWorkspaceListDialog';
14
+ import { NSAAccessListDialog } from '../components/NSAAccessListDialog';
15
+ import { NSAMessageListDialog } from '../components/NSAMessageListDialog';
16
+
17
+ export interface NSALayoutProps<EntityType extends { id: string }, EntityTypeInput = EntityType> extends IBaseComponentProps, INSARouterProps
18
+ {
19
+ scope: string;
20
+ logo: string;
21
+ background?: string;
22
+ header?: IHeaderProps;
23
+ notifications: INSBarNotificationProps[];
24
+ action?: INSBarActionProps;
25
+ banner?: INSBarHeroBannerProps;
26
+ title?: INSBarTitleProps;
27
+ pages?: {
28
+ entity: IEntityInfo<EntityType, EntityTypeInput>;
29
+ ui?: {
30
+ action?: {
31
+ menus: {
32
+ _new?: boolean,
33
+ list?: boolean,
34
+ view?: boolean,
35
+ viewHistory?: boolean,
36
+ copy?: boolean,
37
+ edit?: boolean,
38
+ delete?: boolean,
39
+ apply?: boolean,
40
+ }
41
+ }
42
+ }
43
+ list?: NSASectionListProps<EntityType>;
44
+ edit?: NSASectionEditProps<EntityType, EntityTypeInput>;
45
+ view?: NSASectionViewProps<EntityType>;
46
+ }
47
+ children: ReactNode;
48
+ }
49
+
50
+ interface NSALayoutState
51
+ {
52
+ refresher: number;
53
+ message_count: number;
54
+ showDeleteDialog: boolean;
55
+ showMessageListDialog: boolean;
56
+ showAccessListDialog: boolean;
57
+ showProductListDialog: boolean;
58
+ showWorkspaceListDialog: boolean;
59
+ }
60
+
61
+ export interface NSALayoutRef<EntityType extends { id: string }, EntityTypeInput = EntityType>
62
+ {
63
+ list: NSASectionList<EntityType, EntityTypeInput> | null;
64
+ edit: NSASectionEditRef | null;
65
+ view: NSASectionViewRef | null;
66
+ }
67
+
68
+ export const NSALayout = forwardRef<any, any>(<EntityType extends { id: string }, EntityTypeInput = EntityType>(
69
+ props: Omit<NSALayoutProps<EntityType, EntityTypeInput>, "ref">,
70
+ ref: React.Ref<NSALayoutRef<EntityType, EntityTypeInput>>
71
+ ) =>
72
+ {
73
+ const NSASectionList_Ref = useRef<NSASectionList<EntityType, EntityTypeInput>>(null);
74
+ const NSASectionEdit_Ref = useRef<NSASectionEditRef>(null);
75
+ const NSASectionView_Ref = useRef<NSASectionViewRef>(null);
76
+
77
+ const [state, setState] = useState<NSALayoutState>({
78
+ refresher: 0,
79
+ message_count: 0,
80
+ showDeleteDialog: false,
81
+ showMessageListDialog: false,
82
+ showAccessListDialog: false,
83
+ showProductListDialog: false,
84
+ showWorkspaceListDialog: false
85
+ });
86
+
87
+ const hideDeleteDialog = () => { setState(prevState => ({ ...prevState, showDeleteDialog: false })); };
88
+ const showDeleteDialog = () => { setState(prevState => ({ ...prevState, showDeleteDialog: true })); };
89
+
90
+ let icons: IHeaderIconProps[] = [];
91
+ let isLoggedIn = props.account.token_manager.exists();
92
+ let REACT_APP_BASE_URL_ACCOUNT_CONSOLE = new EnvService("REACT_APP_BASE_URL_ACCOUNT_CONSOLE").getString();
93
+
94
+ if (isLoggedIn)
95
+ icons.push({
96
+ src: "https://static.namirasoft.com/image/concept/logout/white.svg", alt: "Logout", onClicked: () =>
97
+ {
98
+ window.location.href = REACT_APP_BASE_URL_ACCOUNT_CONSOLE + "/logout";
99
+ },
100
+ tooltip: "Logout"
101
+ });
102
+
103
+ // message
104
+ let STORAGE_KEY = "ns-messsage-count";
105
+ let storage = new IStorageLocal();
106
+ let reloadMessageCount: (force: boolean) => void;
107
+ let cache_message: CacheService<number> = new CacheService<number>(STORAGE_KEY, 15, storage, async () =>
108
+ {
109
+ let REACT_APP_BASE_URL_MESSAGE = new EnvService("REACT_APP_BASE_URL_MESSAGE", true).getString();
110
+ let server = new NamirasoftMessageServer(REACT_APP_BASE_URL_MESSAGE, props.account.token_manager, console.error);
111
+ let res = await server.message.GetNewCount();
112
+ return res.count;
113
+ }, () => { reloadMessageCount(false); });
114
+ reloadMessageCount = (force: boolean) =>
115
+ {
116
+ if (force)
117
+ cache_message.del();
118
+ cache_message.get().then(count =>
119
+ {
120
+ setState(prevState => ({ ...prevState, message_count: count }));
121
+ });
122
+ }
123
+ useEffect(() =>
124
+ {
125
+ if (isLoggedIn)
126
+ reloadMessageCount(false);
127
+ // eslint-disable-next-line react-hooks/exhaustive-deps
128
+ }, []);
129
+ if (isLoggedIn)
130
+ {
131
+ icons.push({
132
+ src: "https://static.namirasoft.com/image/namirasoft/message/logo/base.png", alt: "Message", onClicked: () =>
133
+ {
134
+ setState(prevState => ({ ...prevState, showMessageListDialog: true }));
135
+ },
136
+ children: <>
137
+ {
138
+ (
139
+ state.showMessageListDialog &&
140
+ <NSAMessageListDialog {...props}
141
+ onClose={() => { setState(prevState => ({ ...prevState, showMessageListDialog: false })); }}
142
+ onSeenAll={() =>
143
+ {
144
+ if (reloadMessageCount)
145
+ reloadMessageCount(true);
146
+ }}
147
+ onCountReceived={count =>
148
+ {
149
+ cache_message.set(count);
150
+ setState(prevState => ({ ...prevState, message_count: count }));
151
+ }}
152
+ />
153
+ )
154
+ }
155
+ </>,
156
+ count: state.message_count,
157
+ tooltip: "Message"
158
+ });
159
+ }
160
+ if (isLoggedIn)
161
+ icons.push({
162
+ src: "https://static.namirasoft.com/image/namirasoft/access/logo/base.png", alt: "Access", onClicked: () =>
163
+ {
164
+ setState(prevState => ({ ...prevState, showAccessListDialog: true }));
165
+ },
166
+ children: <>
167
+ {
168
+ (state.showAccessListDialog) && <NSAAccessListDialog {...props} onClose={() =>
169
+ {
170
+ setState(prevState => ({ ...prevState, showAccessListDialog: false }));
171
+ }} />
172
+ }
173
+
174
+ </>,
175
+ tooltip: "Accsess"
176
+ });
177
+ if (isLoggedIn)
178
+ icons.push({
179
+ src: "https://static.namirasoft.com/image/namirasoft/workspace/logo/base.png", alt: "Workspace", onClicked: () =>
180
+ {
181
+ setState(prevState => ({ ...prevState, showWorkspaceListDialog: true }));
182
+ },
183
+ children: <>
184
+ {
185
+ (state.showWorkspaceListDialog) && <NSAWorkspaceListDialog {...props} onClose={() =>
186
+ {
187
+ debugger
188
+ setState(prevState => ({ ...prevState, showWorkspaceListDialog: false }));
189
+ }} />
190
+ }
191
+ </>,
192
+ tooltip: "Workspace List"
193
+ });
194
+ icons.push({
195
+ src: "https://static.namirasoft.com/image/concept/product-list/white.svg", alt: "Product", onClicked: () =>
196
+ {
197
+ setState(prevState => ({ ...prevState, showProductListDialog: true }));
198
+ },
199
+ children: <>
200
+ {
201
+ (state.showProductListDialog) && <NSAProductListDialog {...props} onClose={() =>
202
+ {
203
+ setState(prevState => ({ ...prevState, showProductListDialog: false }));
204
+ }} >
205
+ <></>
206
+ </NSAProductListDialog>
207
+ }
208
+ </>,
209
+ tooltip: "Product List"
210
+ });
211
+
212
+ let name = "";
213
+ if (props.pages)
214
+ name = NamingConvention.lower_case_underscore.convert(props.pages.entity.name, NamingConvention.Pascal_Case_Space);
215
+
216
+ let user_name = props.account.token_manager.getUserData(user => [user.first_name, user.last_name].filter(n => n).join(" "), "");
217
+
218
+ let { id } = useParams();
219
+
220
+ let getIDs: (() => string[]) | null = null;
221
+ if (props.pages?.list)
222
+ getIDs = () => { return NSASectionList_Ref.current?.getSelectedIDs() ?? []; };
223
+ if (props.pages?.edit)
224
+ getIDs = () => [id].filter(id => id) as string[];
225
+ if (props.pages?.view)
226
+ getIDs = () => [id].filter(id => id) as string[];
227
+
228
+ let action: INSBarActionProps | undefined = props.action;
229
+ if (!action)
230
+ action = { title: "", description: "", menus: {} };
231
+
232
+ if (getIDs)
233
+ if (props.pages?.entity.client.getMenus)
234
+ {
235
+ let menus = props.pages?.entity.client.getMenus(getIDs);
236
+ for (let key of Object.keys(menus))
237
+ {
238
+ if (!action.menus[key])
239
+ action.menus[key] = [];
240
+ action.menus[key].push(...menus[key]);
241
+ }
242
+ }
243
+
244
+ let name_apply = "Apply";
245
+ let name_actions = "Actions";
246
+ action.menus[name_apply] = [];
247
+ action.menus[name_actions] = [];
248
+
249
+ if (props.pages?.edit)
250
+ {
251
+ if (!action.title)
252
+ action.title = (props.pages.edit.isEdit ? "Edit" : "New") + " " + name;
253
+
254
+ // Menu
255
+ if (props.pages.edit.ui.action?.menus.apply ?? true)
256
+ action.menus[name_apply].push(Actions.apply(() =>
257
+ {
258
+ if (props.pages?.edit)
259
+ NSASectionEdit_onApply(props.pages?.edit, props.pages.entity, id);
260
+ }));
261
+ }
262
+ else if (props.pages)
263
+ {
264
+ if (props.pages.entity.client.getNewURL)
265
+ if (props.pages.entity.server.create)
266
+ if (props.pages.ui?.action?.menus._new ?? true)
267
+ action.menus[name_apply].push(Actions._new(props, props.pages.entity));
268
+ }
269
+
270
+ if (getIDs)
271
+ if (props.pages)
272
+ {
273
+ if (props.pages.entity.client.getListURL)
274
+ if (props.pages.entity.server.list)
275
+ if (props.pages.ui?.action?.menus.list ?? true)
276
+ action.menus[name_actions].push(Actions.list(props, props.pages.entity));
277
+
278
+ if (props.pages.entity.client.getViewURL)
279
+ if (props.pages.entity.server.get)
280
+ if (props.pages.ui?.action?.menus.view ?? true)
281
+ action.menus[name_actions].push(Actions.view(props, props.pages.entity, getIDs));
282
+
283
+ if (props.pages.ui?.action?.menus.viewHistory ?? true)
284
+ action.menus[name_actions].push(Actions.viewHistory(getIDs));
285
+
286
+ if (props.pages.entity.client.getCopyURL)
287
+ if (props.pages.entity.server.create)
288
+ if (props.pages.ui?.action?.menus.copy ?? true)
289
+ action.menus[name_actions].push(Actions.copy(props, props.pages.entity, getIDs));
290
+
291
+ if (props.pages.entity.client.getEditURL)
292
+ if (props.pages.entity.server.update)
293
+ if (props.pages.ui?.action?.menus.edit ?? true)
294
+ action.menus[name_actions].push(Actions.edit(props, props.pages.entity, getIDs));
295
+
296
+ if (props.pages.entity.server.delete)
297
+ if (props.pages.ui?.action?.menus.delete ?? true)
298
+ action.menus[name_actions].push(Actions.delete(getIDs, showDeleteDialog));
299
+ }
300
+
301
+ let action_name = "";
302
+ let content;
303
+ if (props.pages?.list)
304
+ {
305
+ action_name = "List";
306
+ content = <NSASectionList<EntityType, EntityTypeInput> ref={NSASectionList_Ref} {...props} {...props.pages.list} entity={props.pages.entity} />
307
+ }
308
+ else if (props.pages?.edit)
309
+ {
310
+ if (props.pages.edit.isEdit)
311
+ action_name = "Edit";
312
+ else
313
+ action_name = "New";
314
+ content = <NSASectionEdit ref={NSASectionEdit_Ref} {...props} {...props.pages.edit} entity={props.pages.entity} >{props.children}</NSASectionEdit>;
315
+ }
316
+ else if (props.pages?.view)
317
+ {
318
+ action_name = "View";
319
+ content = <NSASectionView ref={NSASectionView_Ref}
320
+ {...props}
321
+ {...props.pages.view}
322
+ entity={props.pages.entity}
323
+ />;
324
+ }
325
+ else
326
+ content = props.children;
327
+
328
+ let fullname = "";
329
+ if (props.pages?.entity.name)
330
+ {
331
+ let Name_Pascal_Space = NamingConvention.lower_case_underscore.convert(props.pages.entity.name, NamingConvention.Pascal_Case_Space);
332
+ fullname = action_name + " " + Name_Pascal_Space;
333
+ }
334
+ let action_title = action?.title ?? "";
335
+ if (!action_title)
336
+ action_title = fullname;
337
+
338
+ useImperativeHandle(ref, () => ({
339
+ list: NSASectionList_Ref.current,
340
+ edit: NSASectionEdit_Ref.current,
341
+ view: NSASectionView_Ref.current,
342
+ }));
343
+ return (
344
+ <NSLayout
345
+ {...props}
346
+ header={{
347
+ title: (user_name + " " + (props.header?.title ?? "")).trim(),
348
+ icons: [...icons, ...(props.header?.icons ?? [])],
349
+ logo_title: props.header?.logo_title
350
+ }}
351
+ action={{
352
+ title: action_title,
353
+ description: action?.description,
354
+ menus: action.menus
355
+ }}
356
+ isLoggedIn={props.account.token_manager.exists}
357
+ >
358
+ <div className="container-fluid">
359
+ {
360
+ state.showDeleteDialog &&
361
+ <NSDeleteDialog
362
+ title={"Delete Confirmation"}
363
+ description={`Are you sure you want to delete ${name}?`}
364
+ onClose={hideDeleteDialog}
365
+ onNo={hideDeleteDialog}
366
+ onYes={async () =>
367
+ {
368
+ try
369
+ {
370
+ if (props.pages)
371
+ if (getIDs)
372
+ {
373
+ let ids = getIDs();
374
+ if (ids.length === 0)
375
+ throw new Error("Nothing was found to delete.");
376
+ if (props.pages.entity.server.delete)
377
+ if (ids.length === 1)
378
+ {
379
+ await props.pages.entity.server.delete(ids[0]);
380
+ props.notifier.onSuccess(`${name} was deleted successfully.`);
381
+ hideDeleteDialog();
382
+
383
+ if (props.pages?.list)
384
+ {
385
+ let table = NSASectionList_Ref.current?.NSTable_Main.current;
386
+ if (table)
387
+ table.reload(null, null);
388
+ }
389
+ else if (props.pages?.edit)
390
+ {
391
+ if (props.pages.entity.client.getListURL)
392
+ props.url.redirect(props.pages.entity.client.getListURL(), {});
393
+ else if (props.pages.entity.client.getViewURL)
394
+ props.url.redirect(props.pages.entity.client.getViewURL(ids[0]), {});
395
+ }
396
+ else if (props.pages?.view)
397
+ {
398
+ if (props.pages.entity.client.getListURL)
399
+ props.url.redirect(props.pages.entity.client.getListURL(), {});
400
+ }
401
+ }
402
+ else
403
+ // todo support multiple ids deletion
404
+ throw new Error("Multiple deletion is not supported yet.");
405
+ }
406
+ } catch (error: any)
407
+ {
408
+ props.notifier.onError(error);
409
+ }
410
+ }}
411
+ >
412
+ <></>
413
+ </NSDeleteDialog>}
414
+ {content}
415
+ </div>
416
+ </NSLayout>
417
+ );
388
418
  });