@abpjs/tenant-management 2.1.0 → 2.4.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.
- package/dist/hooks/useTenantManagement.d.ts +8 -0
- package/dist/index.d.ts +16 -4
- package/dist/index.js +159 -18
- package/dist/index.mjs +159 -18
- package/dist/models/index.d.ts +12 -2
- package/dist/services/tenant-management.service.d.ts +6 -1
- package/package.json +4 -4
|
@@ -69,6 +69,14 @@ export interface UseTenantManagementReturn {
|
|
|
69
69
|
setSortOrder: (order: SortOrder) => void;
|
|
70
70
|
/** Handle shared database checkbox change @since 1.1.0 */
|
|
71
71
|
onSharedDatabaseChange: (value: boolean) => void;
|
|
72
|
+
/** Whether the features modal is visible @since 2.2.0 */
|
|
73
|
+
visibleFeatures: boolean;
|
|
74
|
+
/** Provider key for the features modal (tenant ID) @since 2.2.0 */
|
|
75
|
+
featuresProviderKey: string;
|
|
76
|
+
/** Callback when features modal visibility changes @since 2.2.0 */
|
|
77
|
+
onVisibleFeaturesChange: (value: boolean) => void;
|
|
78
|
+
/** Open the features modal for a tenant @since 2.2.0 */
|
|
79
|
+
openFeaturesModal: (providerKey: string) => void;
|
|
72
80
|
/** Reset all state */
|
|
73
81
|
reset: () => void;
|
|
74
82
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @abpjs/tenant-management
|
|
3
3
|
* ABP Framework Tenant Management module for React
|
|
4
|
-
* Translated from @abp/ng.tenant-management v2.
|
|
4
|
+
* Translated from @abp/ng.tenant-management v2.4.0
|
|
5
|
+
*
|
|
6
|
+
* Changes in v2.4.0:
|
|
7
|
+
* - Added apiName property to TenantManagementService (defaults to 'default')
|
|
8
|
+
* - Added adminEmailAddress and adminPassword fields to AddRequest interface
|
|
9
|
+
* - UpdateRequest no longer extends AddRequest (now only has id and name)
|
|
10
|
+
*
|
|
11
|
+
* Changes in v2.2.0:
|
|
12
|
+
* - Added openFeaturesModal(providerKey: string) to useTenantManagement hook
|
|
13
|
+
* - Added visibleFeatures state to useTenantManagement hook
|
|
14
|
+
* - Added featuresProviderKey state to useTenantManagement hook
|
|
15
|
+
* - Added onVisibleFeaturesChange callback to useTenantManagement hook
|
|
16
|
+
* - Dependency updates to @abp/ng.theme.shared v2.2.0, @abp/ng.feature-management v2.2.0
|
|
17
|
+
*
|
|
18
|
+
* Changes in v2.1.0:
|
|
19
|
+
* - Version bump only (dependency updates to @abp/ng.theme.shared v2.1.0, @abp/ng.feature-management v2.1.0)
|
|
5
20
|
*
|
|
6
21
|
* Changes in v2.0.0:
|
|
7
22
|
* - Removed TENANT_MANAGEMENT_ROUTES constant (deprecated in v0.9.0)
|
|
@@ -15,9 +30,6 @@
|
|
|
15
30
|
* - Added TenantsComponentOutputs interface
|
|
16
31
|
* - Updated onSearch signature: (value: any) -> (value: string)
|
|
17
32
|
* - Updated onPageChange signature: (data: any) -> (page: number)
|
|
18
|
-
*
|
|
19
|
-
* Changes in v2.1.0:
|
|
20
|
-
* - Version bump only (dependency updates to @abp/ng.theme.shared v2.1.0, @abp/ng.feature-management v2.1.0)
|
|
21
33
|
*/
|
|
22
34
|
export * from './models';
|
|
23
35
|
export * from './services';
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
33
33
|
// src/services/tenant-management.service.ts
|
|
34
34
|
var TenantManagementService = class {
|
|
35
35
|
constructor(rest) {
|
|
36
|
+
/**
|
|
37
|
+
* The API name used for REST requests.
|
|
38
|
+
* @since 2.4.0
|
|
39
|
+
*/
|
|
40
|
+
this.apiName = "default";
|
|
36
41
|
this.rest = rest;
|
|
37
42
|
}
|
|
38
43
|
/**
|
|
@@ -308,6 +313,8 @@ function useTenantManagement() {
|
|
|
308
313
|
const [useSharedDatabase, setUseSharedDatabase] = (0, import_react.useState)(true);
|
|
309
314
|
const [sortKey, setSortKey] = (0, import_react.useState)("name");
|
|
310
315
|
const [sortOrder, setSortOrder] = (0, import_react.useState)("");
|
|
316
|
+
const [visibleFeatures, setVisibleFeatures] = (0, import_react.useState)(false);
|
|
317
|
+
const [featuresProviderKey, setFeaturesProviderKey] = (0, import_react.useState)("");
|
|
311
318
|
const fetchTenants = (0, import_react.useCallback)(async (params) => {
|
|
312
319
|
setIsLoading(true);
|
|
313
320
|
setError(null);
|
|
@@ -462,6 +469,16 @@ function useTenantManagement() {
|
|
|
462
469
|
setDefaultConnectionString("");
|
|
463
470
|
}
|
|
464
471
|
}, []);
|
|
472
|
+
const onVisibleFeaturesChange = (0, import_react.useCallback)((value) => {
|
|
473
|
+
setVisibleFeatures(value);
|
|
474
|
+
if (!value) {
|
|
475
|
+
setFeaturesProviderKey("");
|
|
476
|
+
}
|
|
477
|
+
}, []);
|
|
478
|
+
const openFeaturesModal = (0, import_react.useCallback)((providerKey) => {
|
|
479
|
+
setFeaturesProviderKey(providerKey);
|
|
480
|
+
setVisibleFeatures(true);
|
|
481
|
+
}, []);
|
|
465
482
|
const isDisabledSaveButton = (0, import_react.useMemo)(() => {
|
|
466
483
|
return !useSharedDatabase && !defaultConnectionString.trim();
|
|
467
484
|
}, [useSharedDatabase, defaultConnectionString]);
|
|
@@ -473,6 +490,8 @@ function useTenantManagement() {
|
|
|
473
490
|
setError(null);
|
|
474
491
|
setDefaultConnectionString("");
|
|
475
492
|
setUseSharedDatabase(true);
|
|
493
|
+
setVisibleFeatures(false);
|
|
494
|
+
setFeaturesProviderKey("");
|
|
476
495
|
}, []);
|
|
477
496
|
return {
|
|
478
497
|
tenants,
|
|
@@ -485,6 +504,8 @@ function useTenantManagement() {
|
|
|
485
504
|
sortKey,
|
|
486
505
|
sortOrder,
|
|
487
506
|
isDisabledSaveButton,
|
|
507
|
+
visibleFeatures,
|
|
508
|
+
featuresProviderKey,
|
|
488
509
|
fetchTenants,
|
|
489
510
|
fetchTenantById,
|
|
490
511
|
createTenant,
|
|
@@ -499,6 +520,8 @@ function useTenantManagement() {
|
|
|
499
520
|
setSortKey,
|
|
500
521
|
setSortOrder,
|
|
501
522
|
onSharedDatabaseChange,
|
|
523
|
+
onVisibleFeaturesChange,
|
|
524
|
+
openFeaturesModal,
|
|
502
525
|
reset
|
|
503
526
|
};
|
|
504
527
|
}
|
|
@@ -557,6 +580,10 @@ function TenantManagementModal({
|
|
|
557
580
|
const [currentView, setCurrentView] = (0, import_react2.useState)(initialView);
|
|
558
581
|
const [tenantName, setTenantName] = (0, import_react2.useState)("");
|
|
559
582
|
const [tenantNameError, setTenantNameError] = (0, import_react2.useState)(null);
|
|
583
|
+
const [adminEmail, setAdminEmail] = (0, import_react2.useState)("");
|
|
584
|
+
const [adminEmailError, setAdminEmailError] = (0, import_react2.useState)(null);
|
|
585
|
+
const [adminPassword, setAdminPassword] = (0, import_react2.useState)("");
|
|
586
|
+
const [adminPasswordError, setAdminPasswordError] = (0, import_react2.useState)(null);
|
|
560
587
|
const [localConnectionString, setLocalConnectionString] = (0, import_react2.useState)("");
|
|
561
588
|
const [localUseSharedDatabase, setLocalUseSharedDatabase] = (0, import_react2.useState)(true);
|
|
562
589
|
const isEditing = !!tenantId;
|
|
@@ -580,6 +607,10 @@ function TenantManagementModal({
|
|
|
580
607
|
reset();
|
|
581
608
|
setTenantName("");
|
|
582
609
|
setTenantNameError(null);
|
|
610
|
+
setAdminEmail("");
|
|
611
|
+
setAdminEmailError(null);
|
|
612
|
+
setAdminPassword("");
|
|
613
|
+
setAdminPasswordError(null);
|
|
583
614
|
setLocalConnectionString("");
|
|
584
615
|
setLocalUseSharedDatabase(true);
|
|
585
616
|
}
|
|
@@ -610,6 +641,39 @@ function TenantManagementModal({
|
|
|
610
641
|
},
|
|
611
642
|
[t]
|
|
612
643
|
);
|
|
644
|
+
const validateAdminEmail = (0, import_react2.useCallback)(
|
|
645
|
+
(email) => {
|
|
646
|
+
if (!email || email.trim().length === 0) {
|
|
647
|
+
setAdminEmailError(t("AbpValidation::ThisFieldIsRequired"));
|
|
648
|
+
return false;
|
|
649
|
+
}
|
|
650
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
651
|
+
if (!emailRegex.test(email)) {
|
|
652
|
+
setAdminEmailError(t("AbpValidation::ThisFieldIsNotAValidEmailAddress"));
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
setAdminEmailError(null);
|
|
656
|
+
return true;
|
|
657
|
+
},
|
|
658
|
+
[t]
|
|
659
|
+
);
|
|
660
|
+
const validateAdminPassword = (0, import_react2.useCallback)(
|
|
661
|
+
(password) => {
|
|
662
|
+
if (!password || password.length === 0) {
|
|
663
|
+
setAdminPasswordError(t("AbpValidation::ThisFieldIsRequired"));
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
if (password.length < 6) {
|
|
667
|
+
setAdminPasswordError(
|
|
668
|
+
t("AbpValidation::ThisFieldMustBeAStringWithAMinimumLengthOf{0}", "6")
|
|
669
|
+
);
|
|
670
|
+
return false;
|
|
671
|
+
}
|
|
672
|
+
setAdminPasswordError(null);
|
|
673
|
+
return true;
|
|
674
|
+
},
|
|
675
|
+
[t]
|
|
676
|
+
);
|
|
613
677
|
const handleTenantSubmit = (0, import_react2.useCallback)(async () => {
|
|
614
678
|
if (!validateTenantName(tenantName)) {
|
|
615
679
|
return;
|
|
@@ -618,7 +682,16 @@ function TenantManagementModal({
|
|
|
618
682
|
if (isEditing && tenantId) {
|
|
619
683
|
result = await updateTenant({ id: tenantId, name: tenantName.trim() });
|
|
620
684
|
} else {
|
|
621
|
-
|
|
685
|
+
const emailValid = validateAdminEmail(adminEmail);
|
|
686
|
+
const passwordValid = validateAdminPassword(adminPassword);
|
|
687
|
+
if (!emailValid || !passwordValid) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
result = await createTenant({
|
|
691
|
+
name: tenantName.trim(),
|
|
692
|
+
adminEmailAddress: adminEmail.trim(),
|
|
693
|
+
adminPassword
|
|
694
|
+
});
|
|
622
695
|
}
|
|
623
696
|
if (result.success) {
|
|
624
697
|
onSave?.();
|
|
@@ -626,9 +699,13 @@ function TenantManagementModal({
|
|
|
626
699
|
}
|
|
627
700
|
}, [
|
|
628
701
|
tenantName,
|
|
702
|
+
adminEmail,
|
|
703
|
+
adminPassword,
|
|
629
704
|
isEditing,
|
|
630
705
|
tenantId,
|
|
631
706
|
validateTenantName,
|
|
707
|
+
validateAdminEmail,
|
|
708
|
+
validateAdminPassword,
|
|
632
709
|
createTenant,
|
|
633
710
|
updateTenant,
|
|
634
711
|
onSave,
|
|
@@ -668,6 +745,26 @@ function TenantManagementModal({
|
|
|
668
745
|
},
|
|
669
746
|
[tenantNameError, validateTenantName]
|
|
670
747
|
);
|
|
748
|
+
const handleAdminEmailChange = (0, import_react2.useCallback)(
|
|
749
|
+
(e) => {
|
|
750
|
+
const value = e.target.value;
|
|
751
|
+
setAdminEmail(value);
|
|
752
|
+
if (adminEmailError) {
|
|
753
|
+
validateAdminEmail(value);
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
[adminEmailError, validateAdminEmail]
|
|
757
|
+
);
|
|
758
|
+
const handleAdminPasswordChange = (0, import_react2.useCallback)(
|
|
759
|
+
(e) => {
|
|
760
|
+
const value = e.target.value;
|
|
761
|
+
setAdminPassword(value);
|
|
762
|
+
if (adminPasswordError) {
|
|
763
|
+
validateAdminPassword(value);
|
|
764
|
+
}
|
|
765
|
+
},
|
|
766
|
+
[adminPasswordError, validateAdminPassword]
|
|
767
|
+
);
|
|
671
768
|
const handleUseSharedDatabaseChange = (0, import_react2.useCallback)(() => {
|
|
672
769
|
setLocalUseSharedDatabase((prev) => {
|
|
673
770
|
const newValue = !prev;
|
|
@@ -680,26 +777,70 @@ function TenantManagementModal({
|
|
|
680
777
|
const handleConnectionStringChange = (0, import_react2.useCallback)((e) => {
|
|
681
778
|
setLocalConnectionString(e.target.value);
|
|
682
779
|
}, []);
|
|
683
|
-
const renderTenantForm = () => /* @__PURE__ */ (0, import_jsx_runtime.
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
780
|
+
const renderTenantForm = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.VStack, { gap: 4, align: "stretch", children: [
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
782
|
+
import_theme_shared.FormField,
|
|
783
|
+
{
|
|
784
|
+
label: t("AbpTenantManagement::TenantName"),
|
|
785
|
+
htmlFor: "tenant-name",
|
|
786
|
+
invalid: !!tenantNameError,
|
|
787
|
+
errorText: tenantNameError || void 0,
|
|
788
|
+
required: true,
|
|
789
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
790
|
+
import_react3.Input,
|
|
791
|
+
{
|
|
792
|
+
id: "tenant-name",
|
|
793
|
+
value: tenantName,
|
|
794
|
+
onChange: handleTenantNameChange,
|
|
795
|
+
placeholder: t("AbpTenantManagement::TenantName"),
|
|
796
|
+
maxLength: 256
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
}
|
|
800
|
+
),
|
|
801
|
+
!isEditing && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
803
|
+
import_theme_shared.FormField,
|
|
804
|
+
{
|
|
805
|
+
label: t("AbpTenantManagement::DisplayName:AdminEmailAddress"),
|
|
806
|
+
htmlFor: "admin-email",
|
|
807
|
+
invalid: !!adminEmailError,
|
|
808
|
+
errorText: adminEmailError || void 0,
|
|
809
|
+
required: true,
|
|
810
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
811
|
+
import_react3.Input,
|
|
812
|
+
{
|
|
813
|
+
id: "admin-email",
|
|
814
|
+
type: "email",
|
|
815
|
+
value: adminEmail,
|
|
816
|
+
onChange: handleAdminEmailChange,
|
|
817
|
+
placeholder: t("AbpTenantManagement::DisplayName:AdminEmailAddress")
|
|
818
|
+
}
|
|
819
|
+
)
|
|
820
|
+
}
|
|
821
|
+
),
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
823
|
+
import_theme_shared.FormField,
|
|
693
824
|
{
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
825
|
+
label: t("AbpTenantManagement::DisplayName:AdminPassword"),
|
|
826
|
+
htmlFor: "admin-password",
|
|
827
|
+
invalid: !!adminPasswordError,
|
|
828
|
+
errorText: adminPasswordError || void 0,
|
|
829
|
+
required: true,
|
|
830
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
831
|
+
import_react3.Input,
|
|
832
|
+
{
|
|
833
|
+
id: "admin-password",
|
|
834
|
+
type: "password",
|
|
835
|
+
value: adminPassword,
|
|
836
|
+
onChange: handleAdminPasswordChange,
|
|
837
|
+
placeholder: t("AbpTenantManagement::DisplayName:AdminPassword")
|
|
838
|
+
}
|
|
839
|
+
)
|
|
699
840
|
}
|
|
700
841
|
)
|
|
701
|
-
}
|
|
702
|
-
|
|
842
|
+
] })
|
|
843
|
+
] });
|
|
703
844
|
const renderConnectionStringForm = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react3.VStack, { gap: 4, align: "stretch", children: [
|
|
704
845
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
705
846
|
import_theme_shared.Checkbox,
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// src/services/tenant-management.service.ts
|
|
2
2
|
var TenantManagementService = class {
|
|
3
3
|
constructor(rest) {
|
|
4
|
+
/**
|
|
5
|
+
* The API name used for REST requests.
|
|
6
|
+
* @since 2.4.0
|
|
7
|
+
*/
|
|
8
|
+
this.apiName = "default";
|
|
4
9
|
this.rest = rest;
|
|
5
10
|
}
|
|
6
11
|
/**
|
|
@@ -276,6 +281,8 @@ function useTenantManagement() {
|
|
|
276
281
|
const [useSharedDatabase, setUseSharedDatabase] = useState(true);
|
|
277
282
|
const [sortKey, setSortKey] = useState("name");
|
|
278
283
|
const [sortOrder, setSortOrder] = useState("");
|
|
284
|
+
const [visibleFeatures, setVisibleFeatures] = useState(false);
|
|
285
|
+
const [featuresProviderKey, setFeaturesProviderKey] = useState("");
|
|
279
286
|
const fetchTenants = useCallback(async (params) => {
|
|
280
287
|
setIsLoading(true);
|
|
281
288
|
setError(null);
|
|
@@ -430,6 +437,16 @@ function useTenantManagement() {
|
|
|
430
437
|
setDefaultConnectionString("");
|
|
431
438
|
}
|
|
432
439
|
}, []);
|
|
440
|
+
const onVisibleFeaturesChange = useCallback((value) => {
|
|
441
|
+
setVisibleFeatures(value);
|
|
442
|
+
if (!value) {
|
|
443
|
+
setFeaturesProviderKey("");
|
|
444
|
+
}
|
|
445
|
+
}, []);
|
|
446
|
+
const openFeaturesModal = useCallback((providerKey) => {
|
|
447
|
+
setFeaturesProviderKey(providerKey);
|
|
448
|
+
setVisibleFeatures(true);
|
|
449
|
+
}, []);
|
|
433
450
|
const isDisabledSaveButton = useMemo(() => {
|
|
434
451
|
return !useSharedDatabase && !defaultConnectionString.trim();
|
|
435
452
|
}, [useSharedDatabase, defaultConnectionString]);
|
|
@@ -441,6 +458,8 @@ function useTenantManagement() {
|
|
|
441
458
|
setError(null);
|
|
442
459
|
setDefaultConnectionString("");
|
|
443
460
|
setUseSharedDatabase(true);
|
|
461
|
+
setVisibleFeatures(false);
|
|
462
|
+
setFeaturesProviderKey("");
|
|
444
463
|
}, []);
|
|
445
464
|
return {
|
|
446
465
|
tenants,
|
|
@@ -453,6 +472,8 @@ function useTenantManagement() {
|
|
|
453
472
|
sortKey,
|
|
454
473
|
sortOrder,
|
|
455
474
|
isDisabledSaveButton,
|
|
475
|
+
visibleFeatures,
|
|
476
|
+
featuresProviderKey,
|
|
456
477
|
fetchTenants,
|
|
457
478
|
fetchTenantById,
|
|
458
479
|
createTenant,
|
|
@@ -467,6 +488,8 @@ function useTenantManagement() {
|
|
|
467
488
|
setSortKey,
|
|
468
489
|
setSortOrder,
|
|
469
490
|
onSharedDatabaseChange,
|
|
491
|
+
onVisibleFeaturesChange,
|
|
492
|
+
openFeaturesModal,
|
|
470
493
|
reset
|
|
471
494
|
};
|
|
472
495
|
}
|
|
@@ -531,6 +554,10 @@ function TenantManagementModal({
|
|
|
531
554
|
const [currentView, setCurrentView] = useState2(initialView);
|
|
532
555
|
const [tenantName, setTenantName] = useState2("");
|
|
533
556
|
const [tenantNameError, setTenantNameError] = useState2(null);
|
|
557
|
+
const [adminEmail, setAdminEmail] = useState2("");
|
|
558
|
+
const [adminEmailError, setAdminEmailError] = useState2(null);
|
|
559
|
+
const [adminPassword, setAdminPassword] = useState2("");
|
|
560
|
+
const [adminPasswordError, setAdminPasswordError] = useState2(null);
|
|
534
561
|
const [localConnectionString, setLocalConnectionString] = useState2("");
|
|
535
562
|
const [localUseSharedDatabase, setLocalUseSharedDatabase] = useState2(true);
|
|
536
563
|
const isEditing = !!tenantId;
|
|
@@ -554,6 +581,10 @@ function TenantManagementModal({
|
|
|
554
581
|
reset();
|
|
555
582
|
setTenantName("");
|
|
556
583
|
setTenantNameError(null);
|
|
584
|
+
setAdminEmail("");
|
|
585
|
+
setAdminEmailError(null);
|
|
586
|
+
setAdminPassword("");
|
|
587
|
+
setAdminPasswordError(null);
|
|
557
588
|
setLocalConnectionString("");
|
|
558
589
|
setLocalUseSharedDatabase(true);
|
|
559
590
|
}
|
|
@@ -584,6 +615,39 @@ function TenantManagementModal({
|
|
|
584
615
|
},
|
|
585
616
|
[t]
|
|
586
617
|
);
|
|
618
|
+
const validateAdminEmail = useCallback2(
|
|
619
|
+
(email) => {
|
|
620
|
+
if (!email || email.trim().length === 0) {
|
|
621
|
+
setAdminEmailError(t("AbpValidation::ThisFieldIsRequired"));
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
625
|
+
if (!emailRegex.test(email)) {
|
|
626
|
+
setAdminEmailError(t("AbpValidation::ThisFieldIsNotAValidEmailAddress"));
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
setAdminEmailError(null);
|
|
630
|
+
return true;
|
|
631
|
+
},
|
|
632
|
+
[t]
|
|
633
|
+
);
|
|
634
|
+
const validateAdminPassword = useCallback2(
|
|
635
|
+
(password) => {
|
|
636
|
+
if (!password || password.length === 0) {
|
|
637
|
+
setAdminPasswordError(t("AbpValidation::ThisFieldIsRequired"));
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
if (password.length < 6) {
|
|
641
|
+
setAdminPasswordError(
|
|
642
|
+
t("AbpValidation::ThisFieldMustBeAStringWithAMinimumLengthOf{0}", "6")
|
|
643
|
+
);
|
|
644
|
+
return false;
|
|
645
|
+
}
|
|
646
|
+
setAdminPasswordError(null);
|
|
647
|
+
return true;
|
|
648
|
+
},
|
|
649
|
+
[t]
|
|
650
|
+
);
|
|
587
651
|
const handleTenantSubmit = useCallback2(async () => {
|
|
588
652
|
if (!validateTenantName(tenantName)) {
|
|
589
653
|
return;
|
|
@@ -592,7 +656,16 @@ function TenantManagementModal({
|
|
|
592
656
|
if (isEditing && tenantId) {
|
|
593
657
|
result = await updateTenant({ id: tenantId, name: tenantName.trim() });
|
|
594
658
|
} else {
|
|
595
|
-
|
|
659
|
+
const emailValid = validateAdminEmail(adminEmail);
|
|
660
|
+
const passwordValid = validateAdminPassword(adminPassword);
|
|
661
|
+
if (!emailValid || !passwordValid) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
result = await createTenant({
|
|
665
|
+
name: tenantName.trim(),
|
|
666
|
+
adminEmailAddress: adminEmail.trim(),
|
|
667
|
+
adminPassword
|
|
668
|
+
});
|
|
596
669
|
}
|
|
597
670
|
if (result.success) {
|
|
598
671
|
onSave?.();
|
|
@@ -600,9 +673,13 @@ function TenantManagementModal({
|
|
|
600
673
|
}
|
|
601
674
|
}, [
|
|
602
675
|
tenantName,
|
|
676
|
+
adminEmail,
|
|
677
|
+
adminPassword,
|
|
603
678
|
isEditing,
|
|
604
679
|
tenantId,
|
|
605
680
|
validateTenantName,
|
|
681
|
+
validateAdminEmail,
|
|
682
|
+
validateAdminPassword,
|
|
606
683
|
createTenant,
|
|
607
684
|
updateTenant,
|
|
608
685
|
onSave,
|
|
@@ -642,6 +719,26 @@ function TenantManagementModal({
|
|
|
642
719
|
},
|
|
643
720
|
[tenantNameError, validateTenantName]
|
|
644
721
|
);
|
|
722
|
+
const handleAdminEmailChange = useCallback2(
|
|
723
|
+
(e) => {
|
|
724
|
+
const value = e.target.value;
|
|
725
|
+
setAdminEmail(value);
|
|
726
|
+
if (adminEmailError) {
|
|
727
|
+
validateAdminEmail(value);
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
[adminEmailError, validateAdminEmail]
|
|
731
|
+
);
|
|
732
|
+
const handleAdminPasswordChange = useCallback2(
|
|
733
|
+
(e) => {
|
|
734
|
+
const value = e.target.value;
|
|
735
|
+
setAdminPassword(value);
|
|
736
|
+
if (adminPasswordError) {
|
|
737
|
+
validateAdminPassword(value);
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
[adminPasswordError, validateAdminPassword]
|
|
741
|
+
);
|
|
645
742
|
const handleUseSharedDatabaseChange = useCallback2(() => {
|
|
646
743
|
setLocalUseSharedDatabase((prev) => {
|
|
647
744
|
const newValue = !prev;
|
|
@@ -654,26 +751,70 @@ function TenantManagementModal({
|
|
|
654
751
|
const handleConnectionStringChange = useCallback2((e) => {
|
|
655
752
|
setLocalConnectionString(e.target.value);
|
|
656
753
|
}, []);
|
|
657
|
-
const renderTenantForm = () => /* @__PURE__ */
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
754
|
+
const renderTenantForm = () => /* @__PURE__ */ jsxs(VStack, { gap: 4, align: "stretch", children: [
|
|
755
|
+
/* @__PURE__ */ jsx(
|
|
756
|
+
FormField,
|
|
757
|
+
{
|
|
758
|
+
label: t("AbpTenantManagement::TenantName"),
|
|
759
|
+
htmlFor: "tenant-name",
|
|
760
|
+
invalid: !!tenantNameError,
|
|
761
|
+
errorText: tenantNameError || void 0,
|
|
762
|
+
required: true,
|
|
763
|
+
children: /* @__PURE__ */ jsx(
|
|
764
|
+
Input,
|
|
765
|
+
{
|
|
766
|
+
id: "tenant-name",
|
|
767
|
+
value: tenantName,
|
|
768
|
+
onChange: handleTenantNameChange,
|
|
769
|
+
placeholder: t("AbpTenantManagement::TenantName"),
|
|
770
|
+
maxLength: 256
|
|
771
|
+
}
|
|
772
|
+
)
|
|
773
|
+
}
|
|
774
|
+
),
|
|
775
|
+
!isEditing && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
776
|
+
/* @__PURE__ */ jsx(
|
|
777
|
+
FormField,
|
|
778
|
+
{
|
|
779
|
+
label: t("AbpTenantManagement::DisplayName:AdminEmailAddress"),
|
|
780
|
+
htmlFor: "admin-email",
|
|
781
|
+
invalid: !!adminEmailError,
|
|
782
|
+
errorText: adminEmailError || void 0,
|
|
783
|
+
required: true,
|
|
784
|
+
children: /* @__PURE__ */ jsx(
|
|
785
|
+
Input,
|
|
786
|
+
{
|
|
787
|
+
id: "admin-email",
|
|
788
|
+
type: "email",
|
|
789
|
+
value: adminEmail,
|
|
790
|
+
onChange: handleAdminEmailChange,
|
|
791
|
+
placeholder: t("AbpTenantManagement::DisplayName:AdminEmailAddress")
|
|
792
|
+
}
|
|
793
|
+
)
|
|
794
|
+
}
|
|
795
|
+
),
|
|
796
|
+
/* @__PURE__ */ jsx(
|
|
797
|
+
FormField,
|
|
667
798
|
{
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
799
|
+
label: t("AbpTenantManagement::DisplayName:AdminPassword"),
|
|
800
|
+
htmlFor: "admin-password",
|
|
801
|
+
invalid: !!adminPasswordError,
|
|
802
|
+
errorText: adminPasswordError || void 0,
|
|
803
|
+
required: true,
|
|
804
|
+
children: /* @__PURE__ */ jsx(
|
|
805
|
+
Input,
|
|
806
|
+
{
|
|
807
|
+
id: "admin-password",
|
|
808
|
+
type: "password",
|
|
809
|
+
value: adminPassword,
|
|
810
|
+
onChange: handleAdminPasswordChange,
|
|
811
|
+
placeholder: t("AbpTenantManagement::DisplayName:AdminPassword")
|
|
812
|
+
}
|
|
813
|
+
)
|
|
673
814
|
}
|
|
674
815
|
)
|
|
675
|
-
}
|
|
676
|
-
|
|
816
|
+
] })
|
|
817
|
+
] });
|
|
677
818
|
const renderConnectionStringForm = () => /* @__PURE__ */ jsxs(VStack, { gap: 4, align: "stretch", children: [
|
|
678
819
|
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
|
|
679
820
|
Checkbox,
|
package/dist/models/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tenant Management module type definitions
|
|
3
|
-
* Translated from @abp/ng.tenant-management v2.
|
|
3
|
+
* Translated from @abp/ng.tenant-management v2.4.0
|
|
4
4
|
*/
|
|
5
5
|
import type { ABP } from '@abpjs/core';
|
|
6
6
|
/**
|
|
@@ -27,15 +27,25 @@ export declare namespace TenantManagement {
|
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Request payload for creating a new tenant
|
|
30
|
+
* @since 2.4.0 Added adminEmailAddress and adminPassword fields
|
|
30
31
|
*/
|
|
31
32
|
interface AddRequest {
|
|
33
|
+
/** Admin email address for the new tenant */
|
|
34
|
+
adminEmailAddress: string;
|
|
35
|
+
/** Admin password for the new tenant */
|
|
36
|
+
adminPassword: string;
|
|
37
|
+
/** Tenant name */
|
|
32
38
|
name: string;
|
|
33
39
|
}
|
|
34
40
|
/**
|
|
35
41
|
* Request payload for updating an existing tenant
|
|
42
|
+
* @since 2.4.0 No longer extends AddRequest (only id and name needed for update)
|
|
36
43
|
*/
|
|
37
|
-
interface UpdateRequest
|
|
44
|
+
interface UpdateRequest {
|
|
45
|
+
/** Tenant ID */
|
|
38
46
|
id: string;
|
|
47
|
+
/** Tenant name */
|
|
48
|
+
name: string;
|
|
39
49
|
}
|
|
40
50
|
/**
|
|
41
51
|
* Request payload for updating tenant's default connection string
|
|
@@ -2,10 +2,15 @@ import { RestService, ABP } from '@abpjs/core';
|
|
|
2
2
|
import { TenantManagement } from '../models';
|
|
3
3
|
/**
|
|
4
4
|
* Service for tenant management API calls
|
|
5
|
-
* Translated from @abp/ng.tenant-management
|
|
5
|
+
* Translated from @abp/ng.tenant-management v2.4.0
|
|
6
6
|
*/
|
|
7
7
|
export declare class TenantManagementService {
|
|
8
8
|
private rest;
|
|
9
|
+
/**
|
|
10
|
+
* The API name used for REST requests.
|
|
11
|
+
* @since 2.4.0
|
|
12
|
+
*/
|
|
13
|
+
apiName: string;
|
|
9
14
|
constructor(rest: RestService);
|
|
10
15
|
/**
|
|
11
16
|
* Get all tenants (paginated)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abpjs/tenant-management",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "ABP Framework tenant-management components for React - translated from @abp/ng.tenant-management",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@chakra-ui/react": "^3.2.0",
|
|
25
25
|
"@emotion/react": "^11.11.0",
|
|
26
|
-
"@abpjs/core": "2.
|
|
27
|
-
"@abpjs/theme-shared": "2.
|
|
26
|
+
"@abpjs/core": "2.4.0",
|
|
27
|
+
"@abpjs/theme-shared": "2.4.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@abp/ng.tenant-management": "2.
|
|
30
|
+
"@abp/ng.tenant-management": "2.4.0",
|
|
31
31
|
"@testing-library/jest-dom": "^6.4.0",
|
|
32
32
|
"@testing-library/react": "^14.2.0",
|
|
33
33
|
"@types/react": "^18.2.0",
|