@firecms/user_management 3.3.0 → 3.4.0-canary.00f9be5
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/components/UserManagementPausedNotice.d.ts +7 -0
- package/dist/index.es.js +265 -90
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +265 -90
- package/dist/index.umd.js.map +1 -1
- package/dist/useUserManagementPlugin.d.ts +1 -1
- package/package.json +6 -6
- package/src/components/UserManagementPausedNotice.tsx +37 -0
- package/src/components/roles/RolesView.tsx +15 -1
- package/src/components/users/UsersTable.tsx +2 -2
- package/src/components/users/UsersView.tsx +15 -1
- package/src/hooks/useBuildUserManagement.tsx +11 -3
- package/src/useUserManagementPlugin.tsx +15 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firecms/user_management",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.4.0-canary.00f9be5",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"types": "./dist/index.d.ts",
|
|
30
30
|
"source": "src/index.ts",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@firecms/core": "
|
|
33
|
-
"@firecms/formex": "
|
|
34
|
-
"@firecms/ui": "
|
|
32
|
+
"@firecms/core": "3.4.0-canary.00f9be5",
|
|
33
|
+
"@firecms/formex": "3.4.0-canary.00f9be5",
|
|
34
|
+
"@firecms/ui": "3.4.0-canary.00f9be5",
|
|
35
35
|
"date-fns": "^3.6.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"react-dom": ">=18.3.1 || >=19.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@types/node": "^
|
|
42
|
+
"@types/node": "^26.1.1",
|
|
43
43
|
"@types/react": "^19.2.3",
|
|
44
44
|
"@types/react-dom": "^19.2.3",
|
|
45
45
|
"babel-plugin-react-compiler": "^19.0.0-beta-af1b7da-20250417",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"gitHead": "9ecf37abf793bd2f2daaaed6f517ee5ee19b01ae",
|
|
61
61
|
"repository": {
|
|
62
62
|
"type": "git",
|
|
63
|
-
"url": "https://github.com/
|
|
63
|
+
"url": "git+https://github.com/firecmsco/firecms.git",
|
|
64
64
|
"directory": "packages/user_management"
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { getLicenseSubscribeUrl, useLicenseStatus, useTranslation } from "@firecms/core";
|
|
3
|
+
import { Button, Paper, Typography } from "@firecms/ui";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shown by the Users and Roles views instead of their editors while FireCMS
|
|
7
|
+
* PRO is paused. The user management plugin itself stays mounted, so sign-in
|
|
8
|
+
* and role checks keep working; only editing users and roles is paused.
|
|
9
|
+
*/
|
|
10
|
+
export function UserManagementPausedNotice() {
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const licenseStatus = useLicenseStatus();
|
|
13
|
+
const linkLabel = licenseStatus?.licenseState === "invalid_project"
|
|
14
|
+
? t("license_add_project_to_license")
|
|
15
|
+
: licenseStatus?.licenseState === "over_quota"
|
|
16
|
+
? t("license_update_license")
|
|
17
|
+
: t("license_get_license");
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Paper
|
|
21
|
+
className={"flex flex-col items-start px-4 py-6 bg-white dark:bg-surface-accent-800 gap-2"}>
|
|
22
|
+
<Typography variant={"subtitle2"} className={"uppercase"}>
|
|
23
|
+
{t("pro_features_paused")}
|
|
24
|
+
</Typography>
|
|
25
|
+
<Typography>
|
|
26
|
+
{t("user_management_paused_description")}
|
|
27
|
+
</Typography>
|
|
28
|
+
<Button
|
|
29
|
+
component={"a"}
|
|
30
|
+
href={getLicenseSubscribeUrl(licenseStatus)}
|
|
31
|
+
target={"_blank"}
|
|
32
|
+
rel={"noopener noreferrer"}>
|
|
33
|
+
{linkLabel}
|
|
34
|
+
</Button>
|
|
35
|
+
</Paper>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import React, { useCallback, useState } from "react";
|
|
2
2
|
|
|
3
|
-
import { Role, useNavigationController, useTranslation
|
|
3
|
+
import { isProPaused, Role, useLicenseStatus, useNavigationController, useTranslation
|
|
4
4
|
} from "@firecms/core";
|
|
5
5
|
import { AddIcon, Button, Container, Typography } from "@firecms/ui";
|
|
6
6
|
import { RolesTable } from "./RolesTable";
|
|
7
7
|
import { RolesDetailsForm } from "./RolesDetailsForm";
|
|
8
|
+
import { UserManagementPausedNotice } from "../UserManagementPausedNotice";
|
|
8
9
|
|
|
9
10
|
export const RolesView = React.memo(
|
|
10
11
|
function RolesView({ children }: { children?: React.ReactNode }) {
|
|
11
12
|
const { t } = useTranslation();
|
|
13
|
+
const paused = isProPaused(useLicenseStatus());
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
const { collections } = useNavigationController();
|
|
@@ -25,6 +27,18 @@ export const RolesView = React.memo(
|
|
|
25
27
|
setDialogOpen(false);
|
|
26
28
|
};
|
|
27
29
|
|
|
30
|
+
if (paused) {
|
|
31
|
+
return (
|
|
32
|
+
<Container className="w-full flex flex-col py-4 gap-4" maxWidth={"6xl"}>
|
|
33
|
+
{children}
|
|
34
|
+
<Typography gutterBottom variant="h4"
|
|
35
|
+
className="mt-12"
|
|
36
|
+
component="h4">{t("roles")}</Typography>
|
|
37
|
+
<UserManagementPausedNotice/>
|
|
38
|
+
</Container>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
return (
|
|
29
43
|
<Container className="w-full flex flex-col py-4 gap-4" maxWidth={"6xl"}>
|
|
30
44
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { format } from "date-fns";
|
|
4
|
-
import * as locales from "date-fns/locale";
|
|
5
4
|
|
|
6
5
|
import {
|
|
7
6
|
defaultDateFormat,
|
|
8
7
|
ConfirmationDialog, Role,
|
|
9
8
|
useAuthController,
|
|
10
9
|
useCustomizationController, User,
|
|
10
|
+
useDateFnsLocale,
|
|
11
11
|
useSnackbarController,
|
|
12
12
|
useTranslation
|
|
13
13
|
} from "@firecms/core";
|
|
@@ -44,7 +44,7 @@ export function UsersTable({ onUserClicked }: {
|
|
|
44
44
|
const snackbarController = useSnackbarController();
|
|
45
45
|
|
|
46
46
|
const customizationController = useCustomizationController();
|
|
47
|
-
const dateUtilsLocale = customizationController?.locale
|
|
47
|
+
const dateUtilsLocale = useDateFnsLocale(customizationController?.locale);
|
|
48
48
|
const dateFormat: string = customizationController?.dateTimeFormat ?? defaultDateFormat;
|
|
49
49
|
|
|
50
50
|
const [userToBeDeleted, setUserToBeDeleted] = useState<User | undefined>(undefined);
|
|
@@ -4,11 +4,13 @@ import { UsersTable } from "./UsersTable";
|
|
|
4
4
|
import { UserDetailsForm } from "./UserDetailsForm";
|
|
5
5
|
import React, { useCallback, useState } from "react";
|
|
6
6
|
import { useUserManagement } from "../../hooks/useUserManagement";
|
|
7
|
-
import { User, useTranslation
|
|
7
|
+
import { isProPaused, useLicenseStatus, User, useTranslation
|
|
8
8
|
} from "@firecms/core";
|
|
9
|
+
import { UserManagementPausedNotice } from "../UserManagementPausedNotice";
|
|
9
10
|
|
|
10
11
|
export const UsersView = function UsersView({ children }: { children?: React.ReactNode }) {
|
|
11
12
|
const { t } = useTranslation();
|
|
13
|
+
const paused = isProPaused(useLicenseStatus());
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
|
@@ -33,6 +35,18 @@ export const UsersView = function UsersView({ children }: { children?: React.Rea
|
|
|
33
35
|
setDialogOpen(true);
|
|
34
36
|
}, []);
|
|
35
37
|
|
|
38
|
+
if (paused) {
|
|
39
|
+
return (
|
|
40
|
+
<Container className="w-full flex flex-col py-4 gap-4" maxWidth={"6xl"}>
|
|
41
|
+
{children}
|
|
42
|
+
<Typography gutterBottom variant="h4"
|
|
43
|
+
className="mt-12"
|
|
44
|
+
component="h4">{t("users")}</Typography>
|
|
45
|
+
<UserManagementPausedNotice/>
|
|
46
|
+
</Container>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
36
50
|
return (
|
|
37
51
|
<Container className="w-full flex flex-col py-4 gap-4" maxWidth={"6xl"}>
|
|
38
52
|
|
|
@@ -200,7 +200,7 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<any> =
|
|
|
200
200
|
path: usersPath,
|
|
201
201
|
id: userExists.uid
|
|
202
202
|
}
|
|
203
|
-
await dataSourceDelegate.deleteEntity({ entity })
|
|
203
|
+
await dataSourceDelegate.deleteEntity({ entity, pathSegments: undefined })
|
|
204
204
|
.then(() => {
|
|
205
205
|
console.debug("Deleted previous user", userExists);
|
|
206
206
|
})
|
|
@@ -213,6 +213,10 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<any> =
|
|
|
213
213
|
return dataSourceDelegate.saveEntity({
|
|
214
214
|
status: "existing",
|
|
215
215
|
path: usersPath,
|
|
216
|
+
// `usersPath` / `rolesPath` are configurable path strings this hook never parses.
|
|
217
|
+
// Segments are left undefined rather than split out of one: absent means "not known
|
|
218
|
+
// here", and a split would be wrong for any configured id containing "/".
|
|
219
|
+
pathSegments: undefined,
|
|
216
220
|
entityId: email,
|
|
217
221
|
values: removeUndefined(data)
|
|
218
222
|
}).then(() => user);
|
|
@@ -229,6 +233,10 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<any> =
|
|
|
229
233
|
return dataSourceDelegate.saveEntity({
|
|
230
234
|
status: "existing",
|
|
231
235
|
path: rolesPath,
|
|
236
|
+
// `usersPath` / `rolesPath` are configurable path strings this hook never parses.
|
|
237
|
+
// Segments are left undefined rather than split out of one: absent means "not known
|
|
238
|
+
// here", and a split would be wrong for any configured id containing "/".
|
|
239
|
+
pathSegments: undefined,
|
|
232
240
|
entityId: id,
|
|
233
241
|
values: removeUndefined(roleData)
|
|
234
242
|
}).then(() => {
|
|
@@ -246,7 +254,7 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<any> =
|
|
|
246
254
|
id: uid,
|
|
247
255
|
values: {}
|
|
248
256
|
};
|
|
249
|
-
await dataSourceDelegate.deleteEntity({ entity })
|
|
257
|
+
await dataSourceDelegate.deleteEntity({ entity, pathSegments: undefined })
|
|
250
258
|
}, [usersPath, dataSourceDelegate?.initialised]);
|
|
251
259
|
|
|
252
260
|
const deleteRole = useCallback(async (role: Role): Promise<void> => {
|
|
@@ -259,7 +267,7 @@ export function useBuildUserManagement<CONTROLLER extends AuthController<any> =
|
|
|
259
267
|
id: id,
|
|
260
268
|
values: {}
|
|
261
269
|
};
|
|
262
|
-
await dataSourceDelegate.deleteEntity({ entity })
|
|
270
|
+
await dataSourceDelegate.deleteEntity({ entity, pathSegments: undefined })
|
|
263
271
|
}, [rolesPath, dataSourceDelegate?.initialised]);
|
|
264
272
|
|
|
265
273
|
const collectionPermissions: PermissionsBuilder = useCallback(({
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
FireCMSPlugin,
|
|
3
|
+
isProPaused,
|
|
4
|
+
useAuthController,
|
|
5
|
+
useLicenseStatus,
|
|
6
|
+
User,
|
|
7
|
+
useSnackbarController,
|
|
8
|
+
useTranslation
|
|
9
|
+
} from "@firecms/core";
|
|
2
10
|
import { UserManagementProvider } from "./UserManagementProvider";
|
|
3
11
|
import { UserManagement } from "./types";
|
|
4
12
|
import { AddIcon, Button, Paper, Typography } from "@firecms/ui";
|
|
@@ -47,6 +55,12 @@ export function IntroWidget({
|
|
|
47
55
|
const authController = useAuthController();
|
|
48
56
|
const snackbarController = useSnackbarController();
|
|
49
57
|
const { t } = useTranslation();
|
|
58
|
+
const licenseStatus = useLicenseStatus();
|
|
59
|
+
|
|
60
|
+
// Creating roles and users is paused with PRO; the Users and Roles views
|
|
61
|
+
// say so. The plugin itself stays mounted for sign-in and role checks.
|
|
62
|
+
if (isProPaused(licenseStatus))
|
|
63
|
+
return null;
|
|
50
64
|
|
|
51
65
|
const buttonLabel = noUsers && noRoles
|
|
52
66
|
? t("create_default_roles_and_add_admin")
|