@strapi/plugin-users-permissions 4.20.5 → 5.0.0-alpha.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/admin/src/components/FormModal/index.jsx +1 -2
- package/admin/src/components/Permissions/reducer.js +1 -1
- package/admin/src/components/UsersPermissions/reducer.js +1 -1
- package/admin/src/index.js +14 -30
- package/admin/src/pages/AdvancedSettings/index.jsx +69 -107
- package/admin/src/pages/AdvancedSettings/utils/layout.js +20 -35
- package/admin/src/pages/AdvancedSettings/utils/schema.js +5 -2
- package/admin/src/pages/EmailTemplates/components/EmailForm.jsx +47 -74
- package/admin/src/pages/EmailTemplates/index.jsx +22 -50
- package/admin/src/pages/EmailTemplates/utils/schema.js +18 -6
- package/admin/src/pages/Providers/index.jsx +91 -96
- package/admin/src/pages/Providers/utils/forms.js +11 -11
- package/admin/src/pages/Roles/constants.js +3 -3
- package/admin/src/pages/Roles/hooks/usePlugins.js +5 -4
- package/admin/src/pages/Roles/index.jsx +9 -18
- package/admin/src/pages/Roles/pages/CreatePage.jsx +21 -28
- package/admin/src/pages/Roles/pages/EditPage.jsx +23 -40
- package/admin/src/pages/Roles/pages/ListPage/components/TableBody.jsx +23 -27
- package/admin/src/pages/Roles/pages/ListPage/index.jsx +42 -38
- package/admin/src/pages/Roles/pages/ListPage/utils/api.js +6 -6
- package/admin/src/translations/en.json +1 -1
- package/dist/_chunks/EditViewPage-xYzUSAwS-5mOQ_-nB.mjs +84370 -0
- package/dist/_chunks/EditViewPage-xYzUSAwS-5mOQ_-nB.mjs.map +1 -0
- package/dist/_chunks/EditViewPage-xYzUSAwS-wpHlxdkC.js +84398 -0
- package/dist/_chunks/EditViewPage-xYzUSAwS-wpHlxdkC.js.map +1 -0
- package/dist/_chunks/Helmet-d9JljxUo.js +1010 -0
- package/dist/_chunks/Helmet-d9JljxUo.js.map +1 -0
- package/dist/_chunks/Helmet-kyJ1Zklj.mjs +1008 -0
- package/dist/_chunks/Helmet-kyJ1Zklj.mjs.map +1 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-elahT0e9.js +1618 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-elahT0e9.js.map +1 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-lbfb219V.mjs +1595 -0
- package/dist/_chunks/ListViewPage-xOVa04T_-lbfb219V.mjs.map +1 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-IWfB3WVH.mjs +33 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-IWfB3WVH.mjs.map +1 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-m8hslkeI.js +33 -0
- package/dist/_chunks/ReviewWorkflowsColumn-FDxVKdto-m8hslkeI.js.map +1 -0
- package/dist/_chunks/constants-WjN6I3sL-7e3gpx4b.mjs +190 -0
- package/dist/_chunks/constants-WjN6I3sL-7e3gpx4b.mjs.map +1 -0
- package/dist/_chunks/constants-WjN6I3sL-cDZPE6ED.js +209 -0
- package/dist/_chunks/constants-WjN6I3sL-cDZPE6ED.js.map +1 -0
- package/dist/_chunks/{en-m608rMZx.js → en-TaNIVnDO.js} +2 -2
- package/dist/_chunks/en-TaNIVnDO.js.map +1 -0
- package/dist/_chunks/{en-CE3wEy_c.mjs → en-jvJ-d-Qq.mjs} +2 -2
- package/dist/_chunks/en-jvJ-d-Qq.mjs.map +1 -0
- package/dist/_chunks/{index-iNtwnT3f.mjs → index-53jX2hhF.mjs} +26 -34
- package/dist/_chunks/index-53jX2hhF.mjs.map +1 -0
- package/dist/_chunks/index-5ZvCaCyY-06DLg5eU.mjs +16421 -0
- package/dist/_chunks/index-5ZvCaCyY-06DLg5eU.mjs.map +1 -0
- package/dist/_chunks/index-5ZvCaCyY-JgYo3Jws.js +16446 -0
- package/dist/_chunks/index-5ZvCaCyY-JgYo3Jws.js.map +1 -0
- package/dist/_chunks/{index-rryiT0-Z.mjs → index-A3oJlPcE.mjs} +111 -108
- package/dist/_chunks/index-A3oJlPcE.mjs.map +1 -0
- package/dist/_chunks/{index-XqdaO5WZ.js → index-MEUac_4V.js} +124 -122
- package/dist/_chunks/index-MEUac_4V.js.map +1 -0
- package/dist/_chunks/index-N-GcFWtg.mjs +261 -0
- package/dist/_chunks/index-N-GcFWtg.mjs.map +1 -0
- package/dist/_chunks/{index-O9AAUvyy.js → index-TJUxOCtJ.js} +26 -34
- package/dist/_chunks/index-TJUxOCtJ.js.map +1 -0
- package/dist/_chunks/{index-6Kdo3KXv.js → index-VgvlwVA7.js} +106 -147
- package/dist/_chunks/index-VgvlwVA7.js.map +1 -0
- package/dist/_chunks/{index-1uupZmu0.js → index-bRuKnVcH.js} +39 -32
- package/dist/_chunks/index-bRuKnVcH.js.map +1 -0
- package/dist/_chunks/{index-ethhTEkj.mjs → index-ee_14Ldw.mjs} +36 -29
- package/dist/_chunks/index-ee_14Ldw.mjs.map +1 -0
- package/dist/_chunks/index-mzJ2Vb5u.js +280 -0
- package/dist/_chunks/index-mzJ2Vb5u.js.map +1 -0
- package/dist/_chunks/{index-a9oKDd3C.mjs → index-vXywiVeM.mjs} +101 -142
- package/dist/_chunks/index-vXywiVeM.mjs.map +1 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-Z54sMEPM.mjs +39 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-Z54sMEPM.mjs.map +1 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-h8HqtZ6y.js +57 -0
- package/dist/_chunks/useSyncRbac-Kt8Li0Yf-h8HqtZ6y.js.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/style.css +84 -0
- package/package.json +13 -13
- package/server/bootstrap/grant-config.js +9 -0
- package/server/bootstrap/index.js +2 -39
- package/server/content-types/user/index.js +0 -1
- package/server/controllers/auth.js +24 -53
- package/server/controllers/content-manager-user.js +24 -28
- package/server/controllers/role.js +1 -1
- package/server/controllers/user.js +5 -5
- package/server/middlewares/rateLimit.js +1 -1
- package/server/register.js +1 -1
- package/server/services/jwt.js +3 -3
- package/server/services/permission.js +3 -7
- package/server/services/providers-registry.js +15 -0
- package/server/services/providers.js +10 -5
- package/server/services/role.js +15 -13
- package/server/services/user.js +28 -14
- package/server/services/users-permissions.js +12 -10
- package/server/utils/sanitize/sanitizers.js +2 -2
- package/dist/_chunks/en-CE3wEy_c.mjs.map +0 -1
- package/dist/_chunks/en-m608rMZx.js.map +0 -1
- package/dist/_chunks/index-1uupZmu0.js.map +0 -1
- package/dist/_chunks/index-6Kdo3KXv.js.map +0 -1
- package/dist/_chunks/index-O9AAUvyy.js.map +0 -1
- package/dist/_chunks/index-Un-J-cxQ.js +0 -320
- package/dist/_chunks/index-Un-J-cxQ.js.map +0 -1
- package/dist/_chunks/index-X0yw_GgN.mjs +0 -301
- package/dist/_chunks/index-X0yw_GgN.mjs.map +0 -1
- package/dist/_chunks/index-XqdaO5WZ.js.map +0 -1
- package/dist/_chunks/index-a9oKDd3C.mjs.map +0 -1
- package/dist/_chunks/index-ethhTEkj.mjs.map +0 -1
- package/dist/_chunks/index-iNtwnT3f.mjs.map +0 -1
- package/dist/_chunks/index-rryiT0-Z.mjs.map +0 -1
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
|
-
const
|
|
5
|
+
const admin = require("@strapi/strapi/admin");
|
|
6
6
|
const reactRouterDom = require("react-router-dom");
|
|
7
|
-
const index = require("./index-
|
|
7
|
+
const index = require("./index-TJUxOCtJ.js");
|
|
8
8
|
const designSystem = require("@strapi/design-system");
|
|
9
|
-
const
|
|
9
|
+
const helperPlugin = require("@strapi/helper-plugin");
|
|
10
|
+
const Icons = require("@strapi/icons");
|
|
10
11
|
const formik = require("formik");
|
|
12
|
+
const Helmet = require("./Helmet-d9JljxUo.js");
|
|
11
13
|
const reactIntl = require("react-intl");
|
|
12
14
|
const reactQuery = require("react-query");
|
|
13
15
|
const PropTypes = require("prop-types");
|
|
@@ -15,7 +17,7 @@ const upperFirst = require("lodash/upperFirst");
|
|
|
15
17
|
const sortBy = require("lodash/sortBy");
|
|
16
18
|
const get = require("lodash/get");
|
|
17
19
|
const styled = require("styled-components");
|
|
18
|
-
const
|
|
20
|
+
const createNextState2 = require("immer");
|
|
19
21
|
const isEmpty = require("lodash/isEmpty");
|
|
20
22
|
const without = require("lodash/without");
|
|
21
23
|
const map = require("lodash/map");
|
|
@@ -23,6 +25,7 @@ const tail = require("lodash/tail");
|
|
|
23
25
|
const set = require("lodash/set");
|
|
24
26
|
const take = require("lodash/take");
|
|
25
27
|
const yup = require("yup");
|
|
28
|
+
const v2 = require("@strapi/design-system/v2");
|
|
26
29
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
27
30
|
function _interopNamespace(e) {
|
|
28
31
|
if (e && e.__esModule)
|
|
@@ -48,7 +51,6 @@ const upperFirst__default = /* @__PURE__ */ _interopDefault(upperFirst);
|
|
|
48
51
|
const sortBy__default = /* @__PURE__ */ _interopDefault(sortBy);
|
|
49
52
|
const get__default = /* @__PURE__ */ _interopDefault(get);
|
|
50
53
|
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
51
|
-
const produce__default = /* @__PURE__ */ _interopDefault(produce);
|
|
52
54
|
const isEmpty__default = /* @__PURE__ */ _interopDefault(isEmpty);
|
|
53
55
|
const without__default = /* @__PURE__ */ _interopDefault(without);
|
|
54
56
|
const map__default = /* @__PURE__ */ _interopDefault(map);
|
|
@@ -187,7 +189,7 @@ const SubCategory = ({ subCategory }) => {
|
|
|
187
189
|
route: action.name
|
|
188
190
|
}
|
|
189
191
|
) }),
|
|
190
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icons.Cog, {})
|
|
191
193
|
]
|
|
192
194
|
}
|
|
193
195
|
)
|
|
@@ -239,7 +241,7 @@ const initialState$1 = {
|
|
|
239
241
|
};
|
|
240
242
|
const reducer$1 = (state, action) => (
|
|
241
243
|
// eslint-disable-next-line consistent-return
|
|
242
|
-
|
|
244
|
+
createNextState2.produce(state, (draftState) => {
|
|
243
245
|
switch (action.type) {
|
|
244
246
|
case "TOGGLE_COLLAPSE": {
|
|
245
247
|
draftState.collapses = state.collapses.map((collapse, index2) => {
|
|
@@ -427,7 +429,7 @@ const initialState = {
|
|
|
427
429
|
selectedAction: "",
|
|
428
430
|
policies: []
|
|
429
431
|
};
|
|
430
|
-
const reducer = (state, action) =>
|
|
432
|
+
const reducer = (state, action) => createNextState2.produce(state, (draftState) => {
|
|
431
433
|
switch (action.type) {
|
|
432
434
|
case "ON_CHANGE": {
|
|
433
435
|
const keysLength = action.keys.length;
|
|
@@ -529,8 +531,8 @@ UsersPermissions.propTypes = {
|
|
|
529
531
|
};
|
|
530
532
|
const UsersPermissions$1 = React.memo(UsersPermissions);
|
|
531
533
|
const createRoleSchema = yup__namespace.object().shape({
|
|
532
|
-
name: yup__namespace.string().required(
|
|
533
|
-
description: yup__namespace.string().required(
|
|
534
|
+
name: yup__namespace.string().required(admin.translatedErrors.required.id),
|
|
535
|
+
description: yup__namespace.string().required(admin.translatedErrors.required.id)
|
|
534
536
|
});
|
|
535
537
|
const cleanPermissions = (permissions) => Object.keys(permissions).reduce((acc, current) => {
|
|
536
538
|
const currentPermission = permissions[current].controllers;
|
|
@@ -548,9 +550,9 @@ const cleanPermissions = (permissions) => Object.keys(permissions).reduce((acc,
|
|
|
548
550
|
return acc;
|
|
549
551
|
}, {});
|
|
550
552
|
const usePlugins = () => {
|
|
551
|
-
const toggleNotification =
|
|
553
|
+
const { toggleNotification } = admin.useNotification();
|
|
552
554
|
const { get: get2 } = helperPlugin.useFetchClient();
|
|
553
|
-
const { formatAPIError } =
|
|
555
|
+
const { formatAPIError } = admin.useAPIErrorHandler(index.getTrad);
|
|
554
556
|
const [
|
|
555
557
|
{
|
|
556
558
|
data: permissions,
|
|
@@ -585,7 +587,7 @@ const usePlugins = () => {
|
|
|
585
587
|
React.useEffect(() => {
|
|
586
588
|
if (permissionsError) {
|
|
587
589
|
toggleNotification({
|
|
588
|
-
type: "
|
|
590
|
+
type: "danger",
|
|
589
591
|
message: formatAPIError(permissionsError)
|
|
590
592
|
});
|
|
591
593
|
}
|
|
@@ -593,7 +595,7 @@ const usePlugins = () => {
|
|
|
593
595
|
React.useEffect(() => {
|
|
594
596
|
if (routesError) {
|
|
595
597
|
toggleNotification({
|
|
596
|
-
type: "
|
|
598
|
+
type: "danger",
|
|
597
599
|
message: formatAPIError(routesError)
|
|
598
600
|
});
|
|
599
601
|
}
|
|
@@ -611,43 +613,48 @@ const usePlugins = () => {
|
|
|
611
613
|
};
|
|
612
614
|
const CreatePage = () => {
|
|
613
615
|
const { formatMessage } = reactIntl.useIntl();
|
|
614
|
-
const toggleNotification =
|
|
615
|
-
const
|
|
616
|
-
const { lockApp, unlockApp } = helperPlugin.useOverlayBlocker();
|
|
616
|
+
const { toggleNotification } = admin.useNotification();
|
|
617
|
+
const navigate = reactRouterDom.useNavigate();
|
|
617
618
|
const { isLoading: isLoadingPlugins, permissions, routes } = usePlugins();
|
|
618
|
-
const { trackUsage } =
|
|
619
|
+
const { trackUsage } = admin.useTracking();
|
|
619
620
|
const permissionsRef = React__namespace.useRef();
|
|
620
621
|
const { post } = helperPlugin.useFetchClient();
|
|
621
622
|
const mutation = reactQuery.useMutation((body) => post(`/users-permissions/roles`, body), {
|
|
622
623
|
onError() {
|
|
623
624
|
toggleNotification({
|
|
624
|
-
type: "
|
|
625
|
-
message: {
|
|
625
|
+
type: "danger",
|
|
626
|
+
message: formatMessage({
|
|
626
627
|
id: "notification.error",
|
|
627
628
|
defaultMessage: "An error occurred"
|
|
628
|
-
}
|
|
629
|
+
})
|
|
629
630
|
});
|
|
630
631
|
},
|
|
631
632
|
onSuccess() {
|
|
632
633
|
trackUsage("didCreateRole");
|
|
633
634
|
toggleNotification({
|
|
634
635
|
type: "success",
|
|
635
|
-
message: {
|
|
636
|
+
message: formatMessage({
|
|
636
637
|
id: index.getTrad("Settings.roles.created"),
|
|
637
638
|
defaultMessage: "Role created"
|
|
638
|
-
}
|
|
639
|
+
})
|
|
639
640
|
});
|
|
640
|
-
|
|
641
|
+
navigate(-1);
|
|
641
642
|
}
|
|
642
643
|
});
|
|
643
644
|
const handleCreateRoleSubmit = async (data) => {
|
|
644
|
-
lockApp();
|
|
645
645
|
const permissions2 = permissionsRef.current.getPermissions();
|
|
646
646
|
await mutation.mutate({ ...data, ...permissions2, users: [] });
|
|
647
|
-
unlockApp();
|
|
648
647
|
};
|
|
649
648
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { children: [
|
|
650
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
649
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
650
|
+
Helmet.HelmetExport,
|
|
651
|
+
{
|
|
652
|
+
title: formatMessage(
|
|
653
|
+
{ id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
|
|
654
|
+
{ name: "Roles" }
|
|
655
|
+
)
|
|
656
|
+
}
|
|
657
|
+
),
|
|
651
658
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
652
659
|
formik.Formik,
|
|
653
660
|
{
|
|
@@ -655,11 +662,11 @@ const CreatePage = () => {
|
|
|
655
662
|
initialValues: { name: "", description: "" },
|
|
656
663
|
onSubmit: handleCreateRoleSubmit,
|
|
657
664
|
validationSchema: createRoleSchema,
|
|
658
|
-
children: ({ handleSubmit, values, handleChange, errors }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
665
|
+
children: ({ handleSubmit, values, handleChange, errors }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { noValidate: true, onSubmit: handleSubmit, children: [
|
|
659
666
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
660
667
|
designSystem.HeaderLayout,
|
|
661
668
|
{
|
|
662
|
-
primaryAction: !isLoadingPlugins && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", loading: mutation.isLoading, startIcon: /* @__PURE__ */ jsxRuntime.jsx(
|
|
669
|
+
primaryAction: !isLoadingPlugins && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", loading: mutation.isLoading, startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}), children: formatMessage({
|
|
663
670
|
id: "global.save",
|
|
664
671
|
defaultMessage: "Save"
|
|
665
672
|
}) }),
|
|
@@ -742,14 +749,13 @@ const CreatePage = () => {
|
|
|
742
749
|
)
|
|
743
750
|
] });
|
|
744
751
|
};
|
|
745
|
-
const ProtectedRolesCreatePage = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
752
|
+
const ProtectedRolesCreatePage = () => /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: index.PERMISSIONS.createRole, children: /* @__PURE__ */ jsxRuntime.jsx(CreatePage, {}) });
|
|
746
753
|
const EditPage = () => {
|
|
747
754
|
const { formatMessage } = reactIntl.useIntl();
|
|
748
|
-
const toggleNotification =
|
|
749
|
-
const { lockApp, unlockApp } = helperPlugin.useOverlayBlocker();
|
|
755
|
+
const { toggleNotification } = admin.useNotification();
|
|
750
756
|
const {
|
|
751
757
|
params: { id }
|
|
752
|
-
} = reactRouterDom.
|
|
758
|
+
} = reactRouterDom.useMatch(`/settings/users-permissions/roles/:id`);
|
|
753
759
|
const { get: get2 } = helperPlugin.useFetchClient();
|
|
754
760
|
const { isLoading: isLoadingPlugins, routes } = usePlugins();
|
|
755
761
|
const {
|
|
@@ -764,36 +770,42 @@ const EditPage = () => {
|
|
|
764
770
|
});
|
|
765
771
|
const permissionsRef = React__namespace.useRef();
|
|
766
772
|
const { put } = helperPlugin.useFetchClient();
|
|
767
|
-
const { formatAPIError } =
|
|
773
|
+
const { formatAPIError } = admin.useAPIErrorHandler();
|
|
768
774
|
const mutation = reactQuery.useMutation((body) => put(`/users-permissions/roles/${id}`, body), {
|
|
769
775
|
onError(error) {
|
|
770
776
|
toggleNotification({
|
|
771
|
-
type: "
|
|
777
|
+
type: "danger",
|
|
772
778
|
message: formatAPIError(error)
|
|
773
779
|
});
|
|
774
780
|
},
|
|
775
781
|
async onSuccess() {
|
|
776
782
|
toggleNotification({
|
|
777
783
|
type: "success",
|
|
778
|
-
message: {
|
|
784
|
+
message: formatMessage({
|
|
779
785
|
id: index.getTrad("Settings.roles.created"),
|
|
780
786
|
defaultMessage: "Role edited"
|
|
781
|
-
}
|
|
787
|
+
})
|
|
782
788
|
});
|
|
783
789
|
await refetchRole();
|
|
784
790
|
}
|
|
785
791
|
});
|
|
786
792
|
const handleEditRoleSubmit = async (data) => {
|
|
787
|
-
lockApp();
|
|
788
793
|
const permissions = permissionsRef.current.getPermissions();
|
|
789
794
|
await mutation.mutate({ ...data, ...permissions, users: [] });
|
|
790
|
-
unlockApp();
|
|
791
795
|
};
|
|
792
796
|
if (isLoadingRole) {
|
|
793
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
797
|
+
return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Loading, {});
|
|
794
798
|
}
|
|
795
799
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { children: [
|
|
796
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
800
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
801
|
+
Helmet.HelmetExport,
|
|
802
|
+
{
|
|
803
|
+
title: formatMessage(
|
|
804
|
+
{ id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
|
|
805
|
+
{ name: "Roles" }
|
|
806
|
+
)
|
|
807
|
+
}
|
|
808
|
+
),
|
|
797
809
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
798
810
|
formik.Formik,
|
|
799
811
|
{
|
|
@@ -801,29 +813,26 @@ const EditPage = () => {
|
|
|
801
813
|
initialValues: { name: role.name, description: role.description },
|
|
802
814
|
onSubmit: handleEditRoleSubmit,
|
|
803
815
|
validationSchema: createRoleSchema,
|
|
804
|
-
children: ({ handleSubmit, values, handleChange, errors }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
816
|
+
children: ({ handleSubmit, values, handleChange, errors }) => /* @__PURE__ */ jsxRuntime.jsxs(formik.Form, { noValidate: true, onSubmit: handleSubmit, children: [
|
|
805
817
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
806
818
|
designSystem.HeaderLayout,
|
|
807
819
|
{
|
|
808
|
-
primaryAction: !isLoadingPlugins
|
|
820
|
+
primaryAction: !isLoadingPlugins ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
809
821
|
designSystem.Button,
|
|
810
822
|
{
|
|
811
823
|
disabled: role.code === "strapi-super-admin",
|
|
812
824
|
type: "submit",
|
|
813
825
|
loading: mutation.isLoading,
|
|
814
|
-
startIcon: /* @__PURE__ */ jsxRuntime.jsx(
|
|
826
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Check, {}),
|
|
815
827
|
children: formatMessage({
|
|
816
828
|
id: "global.save",
|
|
817
829
|
defaultMessage: "Save"
|
|
818
830
|
})
|
|
819
831
|
}
|
|
820
|
-
),
|
|
832
|
+
) : null,
|
|
821
833
|
title: role.name,
|
|
822
834
|
subtitle: role.description,
|
|
823
|
-
navigationAction: /* @__PURE__ */ jsxRuntime.jsx(
|
|
824
|
-
id: "global.back",
|
|
825
|
-
defaultMessage: "Back"
|
|
826
|
-
}) })
|
|
835
|
+
navigationAction: /* @__PURE__ */ jsxRuntime.jsx(admin.BackButton, {})
|
|
827
836
|
}
|
|
828
837
|
),
|
|
829
838
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.ContentLayout, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -895,18 +904,18 @@ const EditPage = () => {
|
|
|
895
904
|
)
|
|
896
905
|
] });
|
|
897
906
|
};
|
|
898
|
-
const ProtectedRolesEditPage = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
907
|
+
const ProtectedRolesEditPage = () => /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: index.PERMISSIONS.updateRole, children: /* @__PURE__ */ jsxRuntime.jsx(EditPage, {}) });
|
|
899
908
|
const EditLink = styled__default.default(designSystem.Link)`
|
|
900
909
|
align-items: center;
|
|
901
|
-
height: ${
|
|
910
|
+
height: ${32 / 16}rem;
|
|
902
911
|
display: flex;
|
|
903
912
|
justify-content: center;
|
|
904
913
|
padding: ${({ theme }) => `${theme.spaces[2]}}`};
|
|
905
|
-
width: ${
|
|
914
|
+
width: ${32 / 16}rem;
|
|
906
915
|
|
|
907
916
|
svg {
|
|
908
|
-
height: ${
|
|
909
|
-
width: ${
|
|
917
|
+
height: ${12 / 16}rem;
|
|
918
|
+
width: ${12 / 16}rem;
|
|
910
919
|
|
|
911
920
|
path {
|
|
912
921
|
fill: ${({ theme }) => theme.colors.neutral500};
|
|
@@ -922,19 +931,16 @@ const EditLink = styled__default.default(designSystem.Link)`
|
|
|
922
931
|
}
|
|
923
932
|
}
|
|
924
933
|
`;
|
|
925
|
-
const TableBody = ({ sortedRoles, canDelete,
|
|
934
|
+
const TableBody = ({ sortedRoles, canDelete, canUpdate, setRoleToDelete, onDelete }) => {
|
|
926
935
|
const { formatMessage } = reactIntl.useIntl();
|
|
927
|
-
const
|
|
936
|
+
const navigate = reactRouterDom.useNavigate();
|
|
928
937
|
const [showConfirmDelete, setShowConfirmDelete] = onDelete;
|
|
929
938
|
const checkCanDeleteRole = (role) => canDelete && !["public", "authenticated"].includes(role.type);
|
|
930
939
|
const handleClickDelete = (id) => {
|
|
931
940
|
setRoleToDelete(id);
|
|
932
941
|
setShowConfirmDelete(!showConfirmDelete);
|
|
933
942
|
};
|
|
934
|
-
|
|
935
|
-
push(`/settings/users-permissions/roles/${id}`);
|
|
936
|
-
};
|
|
937
|
-
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: sortedRoles?.map((role) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { ...helperPlugin.onRowClick({ fn: () => handleClickEdit(role.id) }), children: [
|
|
943
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: sortedRoles?.map((role) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { ...helperPlugin.onRowClick({ fn: () => navigate(role.id.toString()) }), children: [
|
|
938
944
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "20%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: role.name }) }),
|
|
939
945
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "50%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: role.description }) }),
|
|
940
946
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { width: "30%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage(
|
|
@@ -945,43 +951,45 @@ const TableBody = ({ sortedRoles, canDelete, permissions, setRoleToDelete, onDel
|
|
|
945
951
|
{ number: role.nb_users }
|
|
946
952
|
) }) }),
|
|
947
953
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "end", ...helperPlugin.stopPropagation, children: [
|
|
948
|
-
|
|
954
|
+
canUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
949
955
|
EditLink,
|
|
950
956
|
{
|
|
951
|
-
to:
|
|
957
|
+
to: role.id.toString(),
|
|
952
958
|
"aria-label": formatMessage(
|
|
953
959
|
{ id: "app.component.table.edit", defaultMessage: "Edit {target}" },
|
|
954
960
|
{ target: `${role.name}` }
|
|
955
961
|
),
|
|
956
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
962
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Icons.Pencil, {})
|
|
957
963
|
}
|
|
958
|
-
)
|
|
959
|
-
checkCanDeleteRole(role) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
964
|
+
) : null,
|
|
965
|
+
checkCanDeleteRole(role) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
960
966
|
designSystem.IconButton,
|
|
961
967
|
{
|
|
962
|
-
onClick: () => handleClickDelete(role.id),
|
|
968
|
+
onClick: () => handleClickDelete(role.id.toString()),
|
|
963
969
|
noBorder: true,
|
|
964
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
|
970
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Trash, {}),
|
|
965
971
|
label: formatMessage(
|
|
966
972
|
{ id: "global.delete-target", defaultMessage: "Delete {target}" },
|
|
967
973
|
{ target: `${role.name}` }
|
|
968
974
|
)
|
|
969
975
|
}
|
|
970
|
-
)
|
|
976
|
+
)
|
|
971
977
|
] }) })
|
|
972
978
|
] }, role.name)) });
|
|
973
979
|
};
|
|
974
980
|
TableBody.defaultProps = {
|
|
975
|
-
canDelete: false
|
|
981
|
+
canDelete: false,
|
|
982
|
+
canUpdate: false
|
|
976
983
|
};
|
|
977
984
|
TableBody.propTypes = {
|
|
978
985
|
onDelete: PropTypes__default.default.array.isRequired,
|
|
979
986
|
permissions: PropTypes__default.default.object.isRequired,
|
|
980
987
|
setRoleToDelete: PropTypes__default.default.func.isRequired,
|
|
981
988
|
sortedRoles: PropTypes__default.default.array.isRequired,
|
|
982
|
-
canDelete: PropTypes__default.default.bool
|
|
989
|
+
canDelete: PropTypes__default.default.bool,
|
|
990
|
+
canUpdate: PropTypes__default.default.bool
|
|
983
991
|
};
|
|
984
|
-
const fetchData = async (toggleNotification, notifyStatus) => {
|
|
992
|
+
const fetchData = async (toggleNotification, formatMessage, notifyStatus) => {
|
|
985
993
|
try {
|
|
986
994
|
const { get: get2 } = helperPlugin.getFetchClient();
|
|
987
995
|
const { data } = await get2("/users-permissions/roles");
|
|
@@ -989,37 +997,36 @@ const fetchData = async (toggleNotification, notifyStatus) => {
|
|
|
989
997
|
return data;
|
|
990
998
|
} catch (err) {
|
|
991
999
|
toggleNotification({
|
|
992
|
-
type: "
|
|
993
|
-
message: { id: "notification.error" }
|
|
1000
|
+
type: "danger",
|
|
1001
|
+
message: formatMessage({ id: "notification.error" })
|
|
994
1002
|
});
|
|
995
1003
|
throw new Error(err);
|
|
996
1004
|
}
|
|
997
1005
|
};
|
|
998
|
-
const deleteData = async (id, toggleNotification) => {
|
|
1006
|
+
const deleteData = async (id, formatMessage, toggleNotification) => {
|
|
999
1007
|
try {
|
|
1000
1008
|
const { del } = helperPlugin.getFetchClient();
|
|
1001
1009
|
await del(`/users-permissions/roles/${id}`);
|
|
1002
1010
|
} catch (error) {
|
|
1003
1011
|
toggleNotification({
|
|
1004
|
-
type: "
|
|
1005
|
-
message: { id: "notification.error", defaultMessage: "An error occured" }
|
|
1012
|
+
type: "danger",
|
|
1013
|
+
message: formatMessage({ id: "notification.error", defaultMessage: "An error occured" })
|
|
1006
1014
|
});
|
|
1007
1015
|
}
|
|
1008
1016
|
};
|
|
1009
1017
|
const RolesListPage = () => {
|
|
1010
|
-
const { trackUsage } =
|
|
1018
|
+
const { trackUsage } = admin.useTracking();
|
|
1011
1019
|
const { formatMessage, locale } = reactIntl.useIntl();
|
|
1012
|
-
const toggleNotification =
|
|
1020
|
+
const { toggleNotification } = admin.useNotification();
|
|
1013
1021
|
const { notifyStatus } = designSystem.useNotifyAT();
|
|
1014
1022
|
const [{ query }] = helperPlugin.useQueryParams();
|
|
1015
1023
|
const _q = query?._q || "";
|
|
1016
1024
|
const [showConfirmDelete, setShowConfirmDelete] = React.useState(false);
|
|
1017
|
-
const [isConfirmButtonLoading, setIsConfirmButtonLoading] = React.useState(false);
|
|
1018
1025
|
const [roleToDelete, setRoleToDelete] = React.useState();
|
|
1019
1026
|
helperPlugin.useFocusWhenNavigate();
|
|
1020
1027
|
const {
|
|
1021
1028
|
isLoading: isLoadingForPermissions,
|
|
1022
|
-
allowedActions: { canRead, canDelete }
|
|
1029
|
+
allowedActions: { canRead, canDelete, canCreate, canUpdate }
|
|
1023
1030
|
} = helperPlugin.useRBAC({
|
|
1024
1031
|
create: index.PERMISSIONS.createRole,
|
|
1025
1032
|
read: index.PERMISSIONS.readRoles,
|
|
@@ -1031,17 +1038,17 @@ const RolesListPage = () => {
|
|
|
1031
1038
|
data: { roles },
|
|
1032
1039
|
isFetching,
|
|
1033
1040
|
refetch
|
|
1034
|
-
} = reactQuery.useQuery("get-roles", () => fetchData(toggleNotification, notifyStatus), {
|
|
1041
|
+
} = reactQuery.useQuery("get-roles", () => fetchData(toggleNotification, formatMessage, notifyStatus), {
|
|
1035
1042
|
initialData: {},
|
|
1036
1043
|
enabled: canRead
|
|
1037
1044
|
});
|
|
1038
|
-
const {
|
|
1045
|
+
const { contains } = designSystem.useFilter(locale, {
|
|
1039
1046
|
sensitivity: "base"
|
|
1040
1047
|
});
|
|
1041
|
-
const formatter =
|
|
1048
|
+
const formatter = designSystem.useCollator(locale, {
|
|
1042
1049
|
sensitivity: "base"
|
|
1043
1050
|
});
|
|
1044
|
-
const isLoading = isLoadingForData || isFetching;
|
|
1051
|
+
const isLoading = isLoadingForData || isFetching || isLoadingForPermissions;
|
|
1045
1052
|
const handleShowConfirmDelete = () => {
|
|
1046
1053
|
setShowConfirmDelete(!showConfirmDelete);
|
|
1047
1054
|
};
|
|
@@ -1059,25 +1066,34 @@ const RolesListPage = () => {
|
|
|
1059
1066
|
id: "global.roles",
|
|
1060
1067
|
defaultMessage: "Roles"
|
|
1061
1068
|
});
|
|
1062
|
-
const deleteMutation = reactQuery.useMutation((id) => deleteData(id, toggleNotification), {
|
|
1069
|
+
const deleteMutation = reactQuery.useMutation((id) => deleteData(id, formatMessage, toggleNotification), {
|
|
1063
1070
|
async onSuccess() {
|
|
1064
1071
|
await refetch();
|
|
1065
1072
|
}
|
|
1066
1073
|
});
|
|
1067
1074
|
const handleConfirmDelete = async () => {
|
|
1068
|
-
setIsConfirmButtonLoading(true);
|
|
1069
1075
|
await deleteMutation.mutateAsync(roleToDelete);
|
|
1070
1076
|
setShowConfirmDelete(!showConfirmDelete);
|
|
1071
|
-
setIsConfirmButtonLoading(false);
|
|
1072
1077
|
};
|
|
1073
|
-
const sortedRoles = (roles || []).filter((role) =>
|
|
1078
|
+
const sortedRoles = (roles || []).filter((role) => contains(role.name, _q) || contains(role.description, _q)).sort(
|
|
1074
1079
|
(a, b) => formatter.compare(a.name, b.name) || formatter.compare(a.description, b.description)
|
|
1075
1080
|
);
|
|
1076
1081
|
const emptyContent = _q && !sortedRoles.length ? "search" : "roles";
|
|
1077
1082
|
const colCount = 4;
|
|
1078
1083
|
const rowCount = (roles?.length || 0) + 1;
|
|
1084
|
+
if (isLoading) {
|
|
1085
|
+
return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Loading, {});
|
|
1086
|
+
}
|
|
1079
1087
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Layout, { children: [
|
|
1080
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1088
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1089
|
+
Helmet.HelmetExport,
|
|
1090
|
+
{
|
|
1091
|
+
title: formatMessage(
|
|
1092
|
+
{ id: "Settings.PageTitle", defaultMessage: "Settings - {name}" },
|
|
1093
|
+
{ name: pageTitle }
|
|
1094
|
+
)
|
|
1095
|
+
}
|
|
1096
|
+
),
|
|
1081
1097
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { "aria-busy": isLoading, children: [
|
|
1082
1098
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1083
1099
|
designSystem.HeaderLayout,
|
|
@@ -1090,26 +1106,28 @@ const RolesListPage = () => {
|
|
|
1090
1106
|
id: "Settings.roles.list.description",
|
|
1091
1107
|
defaultMessage: "List of roles"
|
|
1092
1108
|
}),
|
|
1093
|
-
primaryAction:
|
|
1094
|
-
|
|
1109
|
+
primaryAction: canCreate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1110
|
+
v2.LinkButton,
|
|
1095
1111
|
{
|
|
1096
|
-
to: "
|
|
1112
|
+
to: "new",
|
|
1113
|
+
as: reactRouterDom.NavLink,
|
|
1097
1114
|
onClick: () => trackUsage("willCreateRole"),
|
|
1098
|
-
startIcon: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1115
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(Icons.Plus, {}),
|
|
1099
1116
|
size: "S",
|
|
1100
1117
|
children: formatMessage({
|
|
1101
1118
|
id: index.getTrad("List.button.roles"),
|
|
1102
1119
|
defaultMessage: "Add new role"
|
|
1103
1120
|
})
|
|
1104
1121
|
}
|
|
1105
|
-
)
|
|
1122
|
+
) : null,
|
|
1123
|
+
navigationAction: /* @__PURE__ */ jsxRuntime.jsx(admin.BackButton, {})
|
|
1106
1124
|
}
|
|
1107
1125
|
),
|
|
1108
1126
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1109
1127
|
designSystem.ActionLayout,
|
|
1110
1128
|
{
|
|
1111
1129
|
startActions: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1112
|
-
|
|
1130
|
+
admin.SearchInput,
|
|
1113
1131
|
{
|
|
1114
1132
|
label: formatMessage({
|
|
1115
1133
|
id: "app.component.search.label",
|
|
@@ -1120,8 +1138,7 @@ const RolesListPage = () => {
|
|
|
1120
1138
|
}
|
|
1121
1139
|
),
|
|
1122
1140
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.ContentLayout, { children: [
|
|
1123
|
-
!canRead && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1124
|
-
(isLoading || isLoadingForPermissions) && /* @__PURE__ */ jsxRuntime.jsx(helperPlugin.LoadingIndicatorPage, {}),
|
|
1141
|
+
!canRead && /* @__PURE__ */ jsxRuntime.jsx(admin.Page.NoPermissions, {}),
|
|
1125
1142
|
canRead && sortedRoles && sortedRoles?.length ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount, rowCount, children: [
|
|
1126
1143
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
1127
1144
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", textColor: "neutral600", children: formatMessage({ id: "global.name", defaultMessage: "Name" }) }) }),
|
|
@@ -1143,19 +1160,19 @@ const RolesListPage = () => {
|
|
|
1143
1160
|
{
|
|
1144
1161
|
sortedRoles,
|
|
1145
1162
|
canDelete,
|
|
1163
|
+
canUpdate,
|
|
1146
1164
|
permissions: index.PERMISSIONS,
|
|
1147
1165
|
setRoleToDelete,
|
|
1148
1166
|
onDelete: [showConfirmDelete, setShowConfirmDelete]
|
|
1149
1167
|
}
|
|
1150
1168
|
)
|
|
1151
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1169
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.EmptyStateLayout, { content: formatMessage(emptyLayout[emptyContent]) })
|
|
1152
1170
|
] }),
|
|
1153
1171
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1154
|
-
|
|
1172
|
+
admin.ConfirmDialog,
|
|
1155
1173
|
{
|
|
1156
|
-
isConfirmButtonLoading,
|
|
1157
1174
|
onConfirm: handleConfirmDelete,
|
|
1158
|
-
|
|
1175
|
+
onClose: handleShowConfirmDelete,
|
|
1159
1176
|
isOpen: showConfirmDelete
|
|
1160
1177
|
}
|
|
1161
1178
|
)
|
|
@@ -1163,29 +1180,14 @@ const RolesListPage = () => {
|
|
|
1163
1180
|
] });
|
|
1164
1181
|
};
|
|
1165
1182
|
const ProtectedRolesListPage = () => {
|
|
1166
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1183
|
+
return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: index.PERMISSIONS.accessRoles, children: /* @__PURE__ */ jsxRuntime.jsx(RolesListPage, {}) });
|
|
1167
1184
|
};
|
|
1168
1185
|
const Roles = () => {
|
|
1169
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1170
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
path: "/settings/users-permissions/roles/new",
|
|
1174
|
-
component: ProtectedRolesCreatePage,
|
|
1175
|
-
exact: true
|
|
1176
|
-
}
|
|
1177
|
-
),
|
|
1178
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1179
|
-
reactRouterDom.Route,
|
|
1180
|
-
{
|
|
1181
|
-
path: "/settings/users-permissions/roles/:id",
|
|
1182
|
-
component: ProtectedRolesEditPage,
|
|
1183
|
-
exact: true
|
|
1184
|
-
}
|
|
1185
|
-
),
|
|
1186
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/settings/users-permissions/roles", component: ProtectedRolesListPage, exact: true }),
|
|
1187
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "", component: helperPlugin.AnErrorOccurred })
|
|
1186
|
+
return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: index.PERMISSIONS.accessRoles, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
|
|
1187
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(ProtectedRolesListPage, {}) }),
|
|
1188
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "new", element: /* @__PURE__ */ jsxRuntime.jsx(ProtectedRolesCreatePage, {}) }),
|
|
1189
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: ":id", element: /* @__PURE__ */ jsxRuntime.jsx(ProtectedRolesEditPage, {}) })
|
|
1188
1190
|
] }) });
|
|
1189
1191
|
};
|
|
1190
1192
|
exports.default = Roles;
|
|
1191
|
-
//# sourceMappingURL=index-
|
|
1193
|
+
//# sourceMappingURL=index-MEUac_4V.js.map
|