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.
- package/dist/Color.js +1 -1
- package/dist/Color.js.map +1 -1
- package/dist/LinkOperation.d.ts +1 -0
- package/dist/LinkOperation.js +15 -0
- package/dist/LinkOperation.js.map +1 -1
- package/dist/Validator.js +3 -3
- package/dist/Validator.js.map +1 -1
- package/dist/components/NSBoxBaseCombo.d.ts +1 -0
- package/dist/components/NSBoxBaseCombo.js +24 -21
- package/dist/components/NSBoxBaseCombo.js.map +1 -1
- package/dist/components/NSBoxBooleans.js +1 -1
- package/dist/components/NSBoxBooleans.js.map +1 -1
- package/dist/components/NSBoxDouble.js +2 -2
- package/dist/components/NSBoxDouble.js.map +1 -1
- package/dist/components/NSBoxDynamics.js +1 -1
- package/dist/components/NSBoxDynamics.js.map +1 -1
- package/dist/components/NSBoxEntity.js +1 -1
- package/dist/components/NSBoxFilePath.js +1 -1
- package/dist/components/NSBoxFilePath.js.map +1 -1
- package/dist/components/NSBoxIPV4.js +1 -1
- package/dist/components/NSBoxIPV4.js.map +1 -1
- package/dist/components/NSBoxIPV6.js +1 -1
- package/dist/components/NSBoxIPV6.js.map +1 -1
- package/dist/components/NSBoxPhone.js +3 -1
- package/dist/components/NSBoxPhone.js.map +1 -1
- package/dist/components/NSBoxSchemaBase.js +2 -2
- package/dist/components/NSBoxSchemaBase.js.map +1 -1
- package/dist/components/NSBoxURL.js +2 -1
- package/dist/components/NSBoxURL.js.map +1 -1
- package/dist/components/NSChartDoughnut.js +2 -0
- package/dist/components/NSChartDoughnut.js.map +1 -1
- package/dist/components/NSChartPie.js +2 -0
- package/dist/components/NSChartPie.js.map +1 -1
- package/dist/components/NSFilterBox.js +2 -2
- package/dist/components/NSFilterBox.js.map +1 -1
- package/dist/components/NSHeader.js +7 -9
- package/dist/components/NSHeader.js.map +1 -1
- package/dist/components/NSID.js +1 -1
- package/dist/components/NSID.js.map +1 -1
- package/dist/components/NSInfo.js +2 -1
- package/dist/components/NSInfo.js.map +1 -1
- package/dist/components/NSLink.js +1 -1
- package/dist/components/NSLink.js.map +1 -1
- package/dist/components/NSListGrouped.js +1 -1
- package/dist/components/NSListGrouped.js.map +1 -1
- package/dist/components/NSMarkdown.js +2 -1
- package/dist/components/NSMarkdown.js.map +1 -1
- package/dist/components/NSProductSearch.js +2 -2
- package/dist/components/NSProductSearch.js.map +1 -1
- package/dist/components/NSTable.js +9 -9
- package/dist/components/NSTable.js.map +1 -1
- package/dist/formatter/EmailFormatter.js +1 -1
- package/dist/routing/NSNotifier.js +7 -2
- package/dist/routing/NSNotifier.js.map +1 -1
- package/package.json +5 -5
- package/src/Color.tsx +1 -1
- package/src/LinkOperation.ts +18 -0
- package/src/Validator.ts +3 -3
- package/src/components/NSBoxBaseCombo.tsx +22 -19
- package/src/components/NSBoxBooleans.tsx +1 -1
- package/src/components/NSBoxDouble.tsx +2 -2
- package/src/components/NSBoxDynamics.tsx +1 -0
- package/src/components/NSBoxEntity.tsx +1 -1
- package/src/components/NSBoxFilePath.tsx +1 -1
- package/src/components/NSBoxIPV4.tsx +1 -1
- package/src/components/NSBoxIPV6.tsx +1 -1
- package/src/components/NSBoxPhone.tsx +3 -1
- package/src/components/NSBoxSchemaBase.tsx +2 -2
- package/src/components/NSBoxURL.tsx +2 -1
- package/src/components/NSChartDoughnut.tsx +2 -0
- package/src/components/NSChartPie.tsx +2 -0
- package/src/components/NSFilterBox.tsx +2 -2
- package/src/components/NSHeader.tsx +2 -4
- package/src/components/NSID.tsx +1 -1
- package/src/components/NSInfo.tsx +2 -1
- package/src/components/NSLink.tsx +1 -0
- package/src/components/NSListGrouped.tsx +2 -2
- package/src/components/NSMarkdown.tsx +2 -1
- package/src/components/NSProductSearch.tsx +2 -2
- package/src/components/NSTable.tsx +4 -4
- package/src/formatter/EmailFormatter.tsx +1 -1
- 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
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (this.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)}
|
|
@@ -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 {
|
|
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
|
|
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.
|
|
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: `
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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) =>
|
package/src/components/NSID.tsx
CHANGED
|
@@ -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
|
-
|
|
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
|
|
589
|
-
selectedRows
|
|
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
|
|
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: "
|
|
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
|
-
|
|
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;
|