namirasoft-site-react 1.5.53 → 1.5.55

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 (82) hide show
  1. package/dist/Color.js +1 -1
  2. package/dist/Color.js.map +1 -1
  3. package/dist/LinkOperation.d.ts +1 -0
  4. package/dist/LinkOperation.js +15 -0
  5. package/dist/LinkOperation.js.map +1 -1
  6. package/dist/Validator.js +3 -3
  7. package/dist/Validator.js.map +1 -1
  8. package/dist/components/NSBoxBaseCombo.d.ts +1 -0
  9. package/dist/components/NSBoxBaseCombo.js +24 -21
  10. package/dist/components/NSBoxBaseCombo.js.map +1 -1
  11. package/dist/components/NSBoxBooleans.js +1 -1
  12. package/dist/components/NSBoxBooleans.js.map +1 -1
  13. package/dist/components/NSBoxDouble.js +2 -2
  14. package/dist/components/NSBoxDouble.js.map +1 -1
  15. package/dist/components/NSBoxDynamics.js +1 -1
  16. package/dist/components/NSBoxDynamics.js.map +1 -1
  17. package/dist/components/NSBoxEntity.js +1 -1
  18. package/dist/components/NSBoxFilePath.js +1 -1
  19. package/dist/components/NSBoxFilePath.js.map +1 -1
  20. package/dist/components/NSBoxIPV4.js +1 -1
  21. package/dist/components/NSBoxIPV4.js.map +1 -1
  22. package/dist/components/NSBoxIPV6.js +1 -1
  23. package/dist/components/NSBoxIPV6.js.map +1 -1
  24. package/dist/components/NSBoxPhone.js +3 -1
  25. package/dist/components/NSBoxPhone.js.map +1 -1
  26. package/dist/components/NSBoxSchemaBase.js +2 -2
  27. package/dist/components/NSBoxSchemaBase.js.map +1 -1
  28. package/dist/components/NSBoxURL.js +2 -1
  29. package/dist/components/NSBoxURL.js.map +1 -1
  30. package/dist/components/NSChartDoughnut.js +2 -0
  31. package/dist/components/NSChartDoughnut.js.map +1 -1
  32. package/dist/components/NSChartPie.js +2 -0
  33. package/dist/components/NSChartPie.js.map +1 -1
  34. package/dist/components/NSFilterBox.js +2 -2
  35. package/dist/components/NSFilterBox.js.map +1 -1
  36. package/dist/components/NSHeader.js +7 -9
  37. package/dist/components/NSHeader.js.map +1 -1
  38. package/dist/components/NSID.js +1 -1
  39. package/dist/components/NSID.js.map +1 -1
  40. package/dist/components/NSInfo.js +2 -1
  41. package/dist/components/NSInfo.js.map +1 -1
  42. package/dist/components/NSLink.js +1 -1
  43. package/dist/components/NSLink.js.map +1 -1
  44. package/dist/components/NSListGrouped.js +1 -1
  45. package/dist/components/NSListGrouped.js.map +1 -1
  46. package/dist/components/NSMarkdown.js +2 -1
  47. package/dist/components/NSMarkdown.js.map +1 -1
  48. package/dist/components/NSProductSearch.js +2 -2
  49. package/dist/components/NSProductSearch.js.map +1 -1
  50. package/dist/components/NSTable.js +9 -9
  51. package/dist/components/NSTable.js.map +1 -1
  52. package/dist/formatter/EmailFormatter.js +1 -1
  53. package/dist/routing/NSNotifier.js +7 -2
  54. package/dist/routing/NSNotifier.js.map +1 -1
  55. package/package.json +5 -5
  56. package/src/Color.tsx +1 -1
  57. package/src/LinkOperation.ts +18 -0
  58. package/src/Validator.ts +3 -3
  59. package/src/components/NSBoxBaseCombo.tsx +22 -19
  60. package/src/components/NSBoxBooleans.tsx +1 -1
  61. package/src/components/NSBoxDouble.tsx +2 -2
  62. package/src/components/NSBoxDynamics.tsx +1 -0
  63. package/src/components/NSBoxEntity.tsx +1 -1
  64. package/src/components/NSBoxFilePath.tsx +1 -1
  65. package/src/components/NSBoxIPV4.tsx +1 -1
  66. package/src/components/NSBoxIPV6.tsx +1 -1
  67. package/src/components/NSBoxPhone.tsx +3 -1
  68. package/src/components/NSBoxSchemaBase.tsx +2 -2
  69. package/src/components/NSBoxURL.tsx +2 -1
  70. package/src/components/NSChartDoughnut.tsx +2 -0
  71. package/src/components/NSChartPie.tsx +2 -0
  72. package/src/components/NSFilterBox.tsx +2 -2
  73. package/src/components/NSHeader.tsx +2 -4
  74. package/src/components/NSID.tsx +1 -1
  75. package/src/components/NSInfo.tsx +2 -1
  76. package/src/components/NSLink.tsx +1 -0
  77. package/src/components/NSListGrouped.tsx +2 -2
  78. package/src/components/NSMarkdown.tsx +2 -1
  79. package/src/components/NSProductSearch.tsx +2 -2
  80. package/src/components/NSTable.tsx +4 -4
  81. package/src/formatter/EmailFormatter.tsx +1 -1
  82. package/src/routing/NSNotifier.ts +8 -2
@@ -7,6 +7,7 @@ import React, { createRef } from "react";
7
7
  import { IBaseComponentProps } from "../props/IBaseComponentProps";
8
8
  import { IValidationProps } from "../props/IValidationProps";
9
9
  import { Validator } from "../Validator";
10
+ import { LinkOperation } from "../LinkOperation";
10
11
  import { INSBox } from "./INSBox";
11
12
  import Styles from "./NSBoxBaseCombo.module.css";
12
13
  import { INSBoxBaseLayoutProps, NSBoxBaseLayout } from "./NSBoxBaseLayout";
@@ -62,6 +63,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
62
63
  private autofillName = `ns-combo-${Math.random().toString(36).slice(2)}-${Date.now().toString(36)}`;
63
64
  private set_value: ({ value: string, callback?: () => void }) | null = null;
64
65
  private set_values: ({ values: string[], callback?: () => void }) | null = null;
66
+ private default_value_applied: boolean = false;
65
67
  private service: SetTimeouService;
66
68
  constructor(props: NSBoxBaseComboProps<Data, NSBoxBaseCombo<Data>>)
67
69
  {
@@ -164,6 +166,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
164
166
  return;
165
167
  }
166
168
  }
169
+ this.set_value = null;
167
170
  this.setDataOne(data, callback);
168
171
  }
169
172
  getValueAll(checkError: boolean = true): string[]
@@ -182,6 +185,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
182
185
  this.set_values = { values, callback };
183
186
  return;
184
187
  }
188
+ this.set_values = null;
185
189
  this.setDataAll(data_list, callback);
186
190
  }
187
191
  getDataOne(checkError: boolean = true): Data | null
@@ -284,6 +288,9 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
284
288
  {
285
289
  let rows = [...items.rows, ...(this.state.items ?? [])];
286
290
  this.setRows(this.state.page_has_more, rows);
291
+ }).catch((error) =>
292
+ {
293
+ console.error("NSBoxBaseCombo.loadID: getItems failed", error);
287
294
  });
288
295
  }
289
296
  public getRows(): Data[]
@@ -321,21 +328,17 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
321
328
  });
322
329
  this.setState({ items: rows, items_list, items_dict, loading: false, page_has_more }, () =>
323
330
  {
324
- let callback: (() => void) | undefined = undefined;
325
- if (this.set_value?.callback)
326
- {
327
- callback = () =>
328
- {
329
- let cb = this.set_value?.callback;
330
- this.set_value = null;
331
- cb?.();
332
- };
333
- }
334
- if (this.set_value)
335
- this.setValue(this.set_value.value, callback);
336
- else if (this.set_values)
337
- this.setValueAll(this.set_values.values, callback);
338
- else if (this.props.defaultValue)
331
+ let set_value = this.set_value;
332
+ let set_values = this.set_values;
333
+ let apply_default = !this.default_value_applied;
334
+ this.set_value = null;
335
+ this.set_values = null;
336
+ this.default_value_applied = true;
337
+ if (set_value)
338
+ this.setValue(set_value.value, set_value.callback);
339
+ else if (set_values)
340
+ this.setValueAll(set_values.values, set_values.callback);
341
+ else if (apply_default && this.props.defaultValue)
339
342
  this.setValue(this.props.defaultValue);
340
343
  this.props.onLoaded?.(this);
341
344
  });
@@ -384,7 +387,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
384
387
  {
385
388
  let res = this.props.onList?.();
386
389
  if (res)
387
- window.open(res, '_blank');
390
+ LinkOperation.openBlank(res);
388
391
  }
389
392
  });
390
393
  if (this.props.onNew)
@@ -395,7 +398,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
395
398
  {
396
399
  let res = this.props.onNew?.();
397
400
  if (res)
398
- window.open(res, '_blank');
401
+ LinkOperation.openBlank(res);
399
402
  }
400
403
  });
401
404
  if (this.props.onView)
@@ -411,7 +414,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
411
414
  {
412
415
  let res = this.props.onView?.(id);
413
416
  if (res)
414
- window.open(res, '_blank');
417
+ LinkOperation.openBlank(res);
415
418
  }
416
419
  }
417
420
  });
@@ -454,7 +457,7 @@ export class NSBoxBaseCombo<Data> extends React.Component<NSBoxBaseComboProps<Da
454
457
  <Select
455
458
  id={this.props.id}
456
459
  mode={this.props.multiple ? "multiple" : undefined}
457
- className={[Styles.ns_box_base_combo_select, this.props.input?.classList].join(" ")}
460
+ className={[Styles.ns_box_base_combo_select, this.props.input?.classList?.join(" ")].join(" ")}
458
461
  placeholder={this.props.placeholder ?? "Please select one"}
459
462
  defaultValue={this.props.defaultValue}
460
463
  value={this.props.multiple ? (this.state.data_list.map(v => this.props.getValue(v))) : (this.state.data ? this.props.getValue(this.state.data) : null)}
@@ -96,7 +96,7 @@ export class NSBoxBooleans extends React.Component<NSBoxBooleansProps, NSboxBool
96
96
  if (checked)
97
97
  {
98
98
  if (!values.includes(value))
99
- values.push(value);
99
+ values = [...values, value];
100
100
  }
101
101
  else
102
102
  values = values.filter(item => item !== value);
@@ -11,7 +11,7 @@ import { INSBoxBaseLayoutProps, NSBoxBaseLayout } from "./NSBoxBaseLayout";
11
11
  import { NamingConvention } from "namirasoft-core";
12
12
  import { IValidationPrecisionProps } from "../props/IValidationPrecisionProps";
13
13
  import { INSBox } from "./INSBox";
14
- import { IntegerFormatter } from "../formatter/IntegerFormatter";
14
+ import { FloatFormatter } from "../formatter/FloatFormatter";
15
15
 
16
16
  export interface NSBoxDoubleProps extends IBaseComponentProps, IValidationProps, IValidationNumberProps, IValidationPrecisionProps, INSBoxBaseLayoutProps<NSBoxDouble, number>
17
17
  {
@@ -84,7 +84,7 @@ export class NSBoxDouble extends React.Component<NSBoxDoubleProps, NSBoxDoubleSt
84
84
  ref={this.NSBoxBaseLayout_Main}
85
85
  {...this.props}
86
86
  menu={menu}
87
- getValue={() => new IntegerFormatter().format(this.getValue(false))}
87
+ getValue={() => new FloatFormatter().format(this.getValue(false))}
88
88
  >
89
89
  <input
90
90
  id={this.props.input?.id}
@@ -55,6 +55,7 @@ export class NSBoxDynamics extends React.Component<NSBoxDynamicsProps, NSBoxDyna
55
55
  {
56
56
  (this.props.variables ?? []).map((variable, index) =>
57
57
  <NSBoxDynamic
58
+ key={variable.name}
58
59
  ref={this.NSBoxDynamic_Refs[variable.name]}
59
60
  {...this.props}
60
61
  name={`${this.props.name}_${index}`}
@@ -118,7 +118,7 @@ export class NSBoxEntity<Data> extends React.Component<NSBoxEntityProps<Data>> i
118
118
  {
119
119
  let onNew: (() => string | void) | undefined = this.props.onNew;
120
120
  let onList: (() => string | void) | undefined = this.props.onList;
121
- let onView: ((id: string) => string | void) | undefined = this.props.onList;
121
+ let onView: ((id: string) => string | void) | undefined = this.props.onView;
122
122
  if (this.props.table)
123
123
  {
124
124
  if (!onNew)
@@ -89,7 +89,7 @@ export class NSBoxFilePath extends React.Component<NSBoxFilePathProps, NSBoxFile
89
89
  // onChange={e => this.setValue(e.target.value)}
90
90
  // onClick={() => { this.props.onClicked?.(this); }}
91
91
  style={{
92
- background: `FilePath("https://static.namirasoft.com/image/concept/type/file-path.png") white no-repeat scroll center right 4px`,
92
+ background: `url("https://static.namirasoft.com/image/concept/type/file-path.png") white no-repeat scroll center right 4px`,
93
93
  backgroundSize: "24px",
94
94
  ...this.props.input?.style,
95
95
  lineHeight: "48px",
@@ -95,7 +95,7 @@ export class NSBoxIPV4 extends React.Component<NSBoxIPV4Props, NSBoxIPV4State> i
95
95
  minLength={7}
96
96
  maxLength={15}
97
97
  size={15}
98
- pattern={IPV4Schema.REGEX + ""}
98
+ pattern={IPV4Schema.REGEX.source}
99
99
  style={{
100
100
  background: `url("https://static.namirasoft.com/image/concept/type/ipv4%266.png") white no-repeat scroll center right 4px`,
101
101
  backgroundSize: "24px",
@@ -92,7 +92,7 @@ export class NSBoxIPV6 extends React.Component<NSBoxIPV6Props, NSBoxIPV6State> i
92
92
  value={this.state.value ?? ""}
93
93
  onChange={e => this.setValue(e.target.value)}
94
94
  onClick={() => { this.props.onClicked?.(this); }}
95
- pattern={IPV6Schema.REGEX + ""}
95
+ pattern={IPV6Schema.REGEX.source}
96
96
  style={{
97
97
  background: `url("https://static.namirasoft.com/image/concept/type/ipv4%266.png") white no-repeat scroll center right 4px`,
98
98
  backgroundSize: "24px",
@@ -56,7 +56,9 @@ export class NSBoxPhone extends React.Component<NSBoxPhoneProps, NSBoxPhoneState
56
56
  return NSBoxBaseLayout.checkGetValue(this, checkError, () =>
57
57
  {
58
58
  let value = this.state.value?.trim();
59
- if (!value?.startsWith('+'))
59
+ if (!value)
60
+ return null;
61
+ if (!value.startsWith('+'))
60
62
  value = '+' + value;
61
63
  return value;
62
64
  });
@@ -110,7 +110,7 @@ export class NSBoxSchemaBase extends React.Component<NSBoxSchemaBaseProps, NSBox
110
110
  let invlid_list = this.NSBoxString_InalidList.current?.getValue(checkError)?.split(",") ?? [];
111
111
  let place_holder = this.NSBoxString_PlaceHolder.current?.getValue(checkError) ?? undefined;
112
112
  let enum_object: { [name: string]: string; } = {};
113
- invlid_list.forEach((v) => enum_object[v] = v);
113
+ valid_list.forEach((v) => enum_object[v] = v);
114
114
 
115
115
  let ans = null;
116
116
  if (type)
@@ -298,7 +298,7 @@ export class NSBoxSchemaBase extends React.Component<NSBoxSchemaBaseProps, NSBox
298
298
  min_length = schema.min_length;
299
299
  max_length = schema.max_length;
300
300
  if (schema.regex)
301
- regex = schema.regex + "";
301
+ regex = schema.regex.source;
302
302
  break;
303
303
  }
304
304
  case VariableType.Date:
@@ -10,6 +10,7 @@ import { safeMenuMenuItem } from "./NSMenuButton";
10
10
  import { INSBoxBaseLayoutProps, NSBoxBaseLayout } from "./NSBoxBaseLayout";
11
11
  import { INSBox } from "./INSBox";
12
12
  import { NamingConvention } from "namirasoft-core";
13
+ import { LinkOperation } from "../LinkOperation";
13
14
 
14
15
  export interface NSBoxURLProps extends IBaseComponentProps, IValidationProps, IValidationStringProps, INSBoxBaseLayoutProps<NSBoxURL, string>
15
16
  {
@@ -78,7 +79,7 @@ export class NSBoxURL extends React.Component<NSBoxURLProps, NSBoxURLState> impl
78
79
  icon: "https://static.namirasoft.com/image/concept/type/url.png",
79
80
  onClick: () =>
80
81
  {
81
- window.open(this.state.value ?? "", "_blank");
82
+ LinkOperation.openBlank(this.state.value ?? "");
82
83
  },
83
84
  })
84
85
  });
@@ -84,6 +84,8 @@ export function NSChartDoughnut(props: NSChartDoughnutProps)
84
84
  const { ctx, chartArea: { width, height } } = chart;
85
85
  const meta = chart.getDatasetMeta(0);
86
86
  const arc = meta.data[0] as unknown as ArcElementType;
87
+ if (!arc)
88
+ return;
87
89
  ctx.save();
88
90
  const fontSize = Math.max(12, arc.innerRadius / 3);
89
91
  ctx.font = `${fontSize}px sans-serif`;
@@ -78,6 +78,8 @@ export function NSChartPie(props: NSChartPieProps)
78
78
  const { ctx, chartArea: { width, height } } = chart;
79
79
  const meta = chart.getDatasetMeta(0);
80
80
  const arc = meta.data[0] as unknown as ArcElementType;
81
+ if (!arc)
82
+ return;
81
83
 
82
84
  ctx.save();
83
85
  const fontSize = Math.max(12, arc.innerRadius / 3);
@@ -172,7 +172,7 @@ export class NSFilterBox extends Component<NSFilterBoxProps, NSFilterBoxState>
172
172
  this.state.selected.column.column.getValues(search).then(values =>
173
173
  {
174
174
  this.setSelectedValues(values);
175
- });
175
+ }).catch(() => { });
176
176
  }
177
177
  else if (this.props.getValues)
178
178
  {
@@ -243,7 +243,7 @@ export class NSFilterBox extends Component<NSFilterBoxProps, NSFilterBoxState>
243
243
  }
244
244
  private onSelected_Value(not: boolean, values: string[])
245
245
  {
246
- let filterItems = this.state.filterItems;
246
+ let filterItems = [...this.state.filterItems];
247
247
  if (this.state.selected.column && this.state.selected.operator)
248
248
  {
249
249
  let table = new BaseMetaTable(null, this.state.selected.column.table.name, this.state.selected.column.table.text);
@@ -126,9 +126,7 @@ export class NSHeader extends Component<NSHeaderProps, NSHeaderState>
126
126
  }
127
127
  override render()
128
128
  {
129
- let nav: IBaseComponentProps | undefined = this.props.nav;
130
- if (!nav)
131
- nav = { style: {} };
129
+ let nav: IBaseComponentProps = { ...this.props.nav, style: { ...this.props.nav?.style } };
132
130
  if (!nav.style)
133
131
  nav.style = {};
134
132
  if (!nav.style?.backgroundColor)
@@ -220,7 +218,7 @@ export class NSHeader extends Component<NSHeaderProps, NSHeaderState>
220
218
  }
221
219
  {
222
220
  this.props.right?.link &&
223
- <a href={this.props.right?.link?.href} target={this.props.right?.link?.target} className={Styles.ns_navbar_title}>{this.props.right?.link?.children}</a>
221
+ <a href={this.props.right?.link?.href} target={this.props.right?.link?.target} rel="noreferrer" className={Styles.ns_navbar_title}>{this.props.right?.link?.children}</a>
224
222
  }
225
223
  {
226
224
  this.props.right.icons.map((icon, index) =>
@@ -141,7 +141,7 @@ export class NSID extends React.Component<NSIDProps, NSIDState>
141
141
  cache.get().then(text =>
142
142
  {
143
143
  this.setState({ text });
144
- });
144
+ }).catch(() => { });
145
145
  }
146
146
 
147
147
  override render()
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { NSDialog } from './NSDialog';
3
+ import { LinkOperation } from '../LinkOperation';
3
4
 
4
5
  export interface NSInfoProps
5
6
  {
@@ -25,7 +26,7 @@ export class NSInfo extends React.Component<NSInfoProps, NSInfoState>
25
26
  else if (this.props.text)
26
27
  this.setState(prev => { return { ...prev, show_info: true } });
27
28
  else if (this.props.link)
28
- window.open(this.props.link, "_blank");
29
+ LinkOperation.openBlank(this.props.link);
29
30
  }
30
31
  override render()
31
32
  {
@@ -15,6 +15,7 @@ export function NSLink(props: NSLinkProps)
15
15
  className={`${props.children ? Styles.ns_link : Styles.ns_link_absolute} ${props.classList?.join(" ") ?? ""}`}
16
16
  href={props.href}
17
17
  target={props?.target ?? "_self"}
18
+ rel={props?.target === "_blank" ? "noreferrer" : undefined}
18
19
  style={props.style}
19
20
  >
20
21
  {props.children}
@@ -172,8 +172,8 @@ export class NSListGrouped<Data> extends Component<NSListGroupedProps<Data>, NSL
172
172
  <NSLoading title='Loading group items ...' />
173
173
  }
174
174
  {
175
- group.items?.map((item) => (
176
- <li key={`NSListGrouped_li_key_${index}`} onClick={() => this.props.onClick(group, item)}>
175
+ group.items?.map((item, item_index) => (
176
+ <li key={`NSListGrouped_li_key_${index}_${item_index}`} onClick={() => this.props.onClick(group, item)}>
177
177
  <div className={Styles.ns_group_item}>
178
178
  <span>{item.text && <span>{item.text}</span>}</span>
179
179
  <span style={item.text_bold ? { fontWeight: 'bold' } : {}}>
@@ -1,5 +1,6 @@
1
1
  import { Component, ReactNode } from "react";
2
2
  import Styles from "./NSMarkdown.module.css";
3
+ import { LinkOperation } from "../LinkOperation";
3
4
 
4
5
  export interface NSMarkdownProps
5
6
  {
@@ -174,7 +175,7 @@ export class NSMarkdown extends Component<NSMarkdownProps>
174
175
  nodes.push(
175
176
  <a
176
177
  key={this.nextKey()}
177
- href={url}
178
+ href={LinkOperation.isSafeURL(url) ? url : undefined}
178
179
  target="_blank"
179
180
  rel="noopener noreferrer"
180
181
  className={Styles.ns_md_link}
@@ -70,7 +70,7 @@ export class NSProductSearch extends React.Component<NSProductSearchProps, NSPro
70
70
  }
71
71
  let render_domain = (domain: DomainRow) =>
72
72
  {
73
- return <a href={domain.url} className={Styles.ns_product_search_item_domain}>
73
+ return <a key={domain.id} href={domain.url} className={Styles.ns_product_search_item_domain}>
74
74
  <div>
75
75
  <img
76
76
  src={domain.logo ?? ""}
@@ -147,7 +147,7 @@ export class NSProductSearch extends React.Component<NSProductSearchProps, NSPro
147
147
  {
148
148
  this.state.links.map(link =>
149
149
  (
150
- <a href={link.url} className={Styles.ns_product_search_item_link}>
150
+ <a key={link.id} href={link.url} className={Styles.ns_product_search_item_link}>
151
151
  <div>
152
152
  <img
153
153
  src={link.logo ?? ""}
@@ -585,8 +585,8 @@ export class NSTable<RowType> extends Component<NSTableProps<RowType>, NSTableSt
585
585
  {
586
586
  if (ctrlKey)
587
587
  {
588
- selectedIDs.push(rowID);
589
- selectedRows.push(row.value);
588
+ selectedIDs = [...selectedIDs, rowID];
589
+ selectedRows = [...selectedRows, row.value];
590
590
  }
591
591
  else
592
592
  {
@@ -1164,7 +1164,7 @@ export class NSTable<RowType> extends Component<NSTableProps<RowType>, NSTableSt
1164
1164
  }
1165
1165
  current_page={this.NSPagination.current?.getCurrentPage() ?? 1}
1166
1166
  current_size={this.NSPagination.current?.getPageSize() ?? 0}
1167
- max_page={this.state.totalItems}
1167
+ max_page={(this.NSPagination.current?.getPageSize() ?? 0) > 0 ? Math.max(1, Math.ceil(this.state.totalItems / (this.NSPagination.current?.getPageSize() ?? 1))) : 1}
1168
1168
  getItems={async (page, size, selected) =>
1169
1169
  {
1170
1170
  if (selected)
@@ -1370,7 +1370,7 @@ export class NSTable<RowType> extends Component<NSTableProps<RowType>, NSTableSt
1370
1370
  {
1371
1371
  this.getColumns(true).map(column =>
1372
1372
  <th
1373
- key={column.name}
1373
+ key={this.getColumnKey(column)}
1374
1374
  scope="col"
1375
1375
  onMouseDown={(e) =>
1376
1376
  {
@@ -16,7 +16,7 @@ export class EmailFormatter extends BaseColumnFormatter
16
16
  return this.formatter.format({
17
17
  text: value,
18
18
  href: `mailto:${value}`,
19
- image: { url: "https://static.namirasoft.com/image/concept/type/email.png", alt: "phone" }
19
+ image: { url: "https://static.namirasoft.com/image/concept/type/email.png", alt: "email" }
20
20
  }, column, row, printable);
21
21
  }
22
22
  override compare(a: any, b: any): number
@@ -33,7 +33,13 @@ export class NSNotifier
33
33
  let ans: NSBarNotificationProps[] = [];
34
34
  let value = this.storage.get("ns-notifications", "");
35
35
  if (value)
36
- ans = JSON.parse(value);
36
+ try
37
+ {
38
+ ans = JSON.parse(value);
39
+ } catch (error)
40
+ {
41
+ ans = [];
42
+ }
37
43
  let now = new Date();
38
44
  ans = ans.filter(x =>
39
45
  {
@@ -106,7 +112,7 @@ export class NSNotifier
106
112
  text = error.message;
107
113
  if (axios.isAxiosError(error))
108
114
  if (error.response?.data)
109
- text = error.response.data;
115
+ text = typeof error.response.data === "string" ? error.response.data : JSON.stringify(error.response.data);
110
116
  }
111
117
  else
112
118
  text = error;