@webiny/app-security-access-management 0.0.0-unstable.78f581c1d2 → 0.0.0-unstable.7be00a75a9
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/Extension.d.ts +2 -0
- package/Extension.js +84 -0
- package/Extension.js.map +1 -0
- package/README.md +7 -111
- package/SecurityPermissions.d.ts +2 -0
- package/SecurityPermissions.js +53 -0
- package/SecurityPermissions.js.map +1 -0
- package/{plugins/constants.d.ts → constants.d.ts} +2 -1
- package/constants.js +9 -0
- package/constants.js.map +1 -0
- package/domain/permissionsSchema.d.ts +20 -0
- package/domain/permissionsSchema.js +34 -0
- package/domain/permissionsSchema.js.map +1 -0
- package/features/permissions/abstractions.d.ts +17 -0
- package/features/permissions/abstractions.js +6 -0
- package/features/permissions/abstractions.js.map +1 -0
- package/features/permissions/feature.d.ts +14 -0
- package/features/permissions/feature.js +7 -0
- package/features/permissions/feature.js.map +1 -0
- package/index.d.ts +1 -9
- package/index.js +1 -80
- package/package.json +24 -37
- package/routes.d.ts +21 -0
- package/routes.js +36 -0
- package/routes.js.map +1 -0
- package/types.d.ts +17 -3
- package/types.js +0 -5
- package/ui/views/ApiKeys/ApiKeyForm.d.ts +5 -3
- package/ui/views/ApiKeys/ApiKeyForm.js +212 -280
- package/ui/views/ApiKeys/ApiKeyForm.js.map +1 -1
- package/ui/views/ApiKeys/ApiKeys.d.ts +1 -7
- package/ui/views/ApiKeys/ApiKeys.js +15 -24
- package/ui/views/ApiKeys/ApiKeys.js.map +1 -1
- package/ui/views/ApiKeys/ApiKeysDataList.d.ts +2 -2
- package/ui/views/ApiKeys/ApiKeysDataList.js +136 -228
- package/ui/views/ApiKeys/ApiKeysDataList.js.map +1 -1
- package/ui/views/ApiKeys/graphql.d.ts +8 -0
- package/ui/views/ApiKeys/graphql.js +83 -25
- package/ui/views/ApiKeys/graphql.js.map +1 -1
- package/ui/views/ApiKeys/index.d.ts +1 -1
- package/ui/views/ApiKeys/index.js +1 -18
- package/ui/views/ApiKeys/utils.d.ts +3 -2
- package/ui/views/ApiKeys/utils.js +15 -18
- package/ui/views/ApiKeys/utils.js.map +1 -1
- package/ui/views/Roles/Roles.d.ts +2 -0
- package/ui/views/Roles/Roles.js +17 -0
- package/ui/views/Roles/Roles.js.map +1 -0
- package/ui/views/Roles/RolesDataList.d.ts +5 -0
- package/ui/views/Roles/RolesDataList.js +141 -0
- package/ui/views/Roles/RolesDataList.js.map +1 -0
- package/ui/views/Roles/RolesForm.d.ts +6 -0
- package/ui/views/Roles/RolesForm.js +213 -0
- package/ui/views/Roles/RolesForm.js.map +1 -0
- package/ui/views/Roles/graphql.d.ts +13 -0
- package/ui/views/Roles/graphql.js +86 -0
- package/ui/views/Roles/graphql.js.map +1 -0
- package/ui/views/Roles/index.d.ts +1 -0
- package/ui/views/Roles/index.js +1 -0
- package/ui/views/Teams/Teams.d.ts +2 -0
- package/ui/views/Teams/Teams.js +17 -0
- package/ui/views/Teams/Teams.js.map +1 -0
- package/ui/views/Teams/TeamsDataList.d.ts +5 -0
- package/ui/views/Teams/TeamsDataList.js +141 -0
- package/ui/views/Teams/TeamsDataList.js.map +1 -0
- package/ui/views/Teams/TeamsForm.d.ts +6 -0
- package/ui/views/Teams/TeamsForm.js +191 -0
- package/ui/views/Teams/TeamsForm.js.map +1 -0
- package/ui/views/Teams/graphql.d.ts +13 -0
- package/ui/views/Teams/graphql.js +90 -0
- package/ui/views/Teams/graphql.js.map +1 -0
- package/ui/views/Teams/index.d.ts +1 -0
- package/ui/views/Teams/index.js +1 -0
- package/ui/views/utils.d.ts +1 -1
- package/ui/views/utils.js +10 -24
- package/ui/views/utils.js.map +1 -1
- package/components/GroupAutocomplete/graphql.d.ts +0 -1
- package/components/GroupAutocomplete/graphql.js +0 -17
- package/components/GroupAutocomplete/graphql.js.map +0 -1
- package/components/GroupAutocomplete/index.d.ts +0 -5
- package/components/GroupAutocomplete/index.js +0 -31
- package/components/GroupAutocomplete/index.js.map +0 -1
- package/components/NotAuthorizedError/NotAuthorizedError.d.ts +0 -2
- package/components/NotAuthorizedError/NotAuthorizedError.js +0 -71
- package/components/NotAuthorizedError/NotAuthorizedError.js.map +0 -1
- package/components/NotAuthorizedError/SecureRouteError.svg +0 -1
- package/components/NotAuthorizedError/index.d.ts +0 -1
- package/components/NotAuthorizedError/index.js +0 -13
- package/components/NotAuthorizedError/index.js.map +0 -1
- package/index.js.map +0 -1
- package/plugins/constants.js +0 -13
- package/plugins/constants.js.map +0 -1
- package/plugins/index.d.ts +0 -3
- package/plugins/index.js +0 -20
- package/plugins/index.js.map +0 -1
- package/plugins/installation.d.ts +0 -3
- package/plugins/installation.js +0 -121
- package/plugins/installation.js.map +0 -1
- package/plugins/permissionRenderer/SecurityPermissions.d.ts +0 -8
- package/plugins/permissionRenderer/SecurityPermissions.js +0 -199
- package/plugins/permissionRenderer/SecurityPermissions.js.map +0 -1
- package/plugins/permissionRenderer/index.d.ts +0 -3
- package/plugins/permissionRenderer/index.js +0 -39
- package/plugins/permissionRenderer/index.js.map +0 -1
- package/plugins/routes.d.ts +0 -3
- package/plugins/routes.js +0 -56
- package/plugins/routes.js.map +0 -1
- package/plugins/secureRouteError.d.ts +0 -7
- package/plugins/secureRouteError.js +0 -22
- package/plugins/secureRouteError.js.map +0 -1
- package/types.js.map +0 -1
- package/ui/elements/GroupAutocompleteElement.d.ts +0 -6
- package/ui/elements/GroupAutocompleteElement.js +0 -64
- package/ui/elements/GroupAutocompleteElement.js.map +0 -1
- package/ui/views/ApiKeys/index.js.map +0 -1
- package/ui/views/Groups/Groups.d.ts +0 -8
- package/ui/views/Groups/Groups.js +0 -26
- package/ui/views/Groups/Groups.js.map +0 -1
- package/ui/views/Groups/GroupsDataList.d.ts +0 -5
- package/ui/views/Groups/GroupsDataList.js +0 -239
- package/ui/views/Groups/GroupsDataList.js.map +0 -1
- package/ui/views/Groups/GroupsForm.d.ts +0 -5
- package/ui/views/Groups/GroupsForm.js +0 -278
- package/ui/views/Groups/GroupsForm.js.map +0 -1
- package/ui/views/Groups/graphql.d.ts +0 -5
- package/ui/views/Groups/graphql.js +0 -26
- package/ui/views/Groups/graphql.js.map +0 -1
- package/ui/views/Groups/index.d.ts +0 -1
- package/ui/views/Groups/index.js +0 -18
- package/ui/views/Groups/index.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui/views/Roles/RolesForm.js","sources":["../../../../src/ui/views/Roles/RolesForm.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { useMutation, useQuery } from \"@apollo/react-hooks\";\nimport get from \"lodash/get.js\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { Bind, Form, useForm, useGenerateSlug } from \"@webiny/form\";\nimport { validation } from \"@webiny/validation\";\nimport {\n SimpleForm,\n SimpleFormFooter,\n SimpleFormContent,\n SimpleFormHeader,\n Permissions,\n EmptyView,\n useRouter,\n useSnackbar\n} from \"@webiny/app-admin\";\nimport { CREATE_ROLE, LIST_ROLES, READ_ROLE, UPDATE_ROLE } from \"./graphql.js\";\nimport isEmpty from \"lodash/isEmpty.js\";\nimport { ReactComponent as AddIcon } from \"@webiny/icons/add.svg\";\nimport { ReactComponent as CopyIcon } from \"@webiny/icons/content_copy.svg\";\nimport { ReactComponent as SettingsIcon } from \"@webiny/icons/settings.svg\";\nimport type { Role } from \"~/types.js\";\nimport {\n Alert,\n Button,\n Grid,\n IconButton,\n Input,\n OverlayLoader,\n Textarea,\n Tooltip\n} from \"@webiny/admin-ui\";\nimport { Routes } from \"~/routes.js\";\n\nconst t = i18n.ns(\"app-security/admin/roles/form\");\n\nexport interface RolesFormProps {\n newEntry: boolean;\n id: string | undefined;\n}\n\nexport const RolesForm = ({ id, newEntry }: RolesFormProps) => {\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n\n const getQuery = useQuery(READ_ROLE, {\n variables: { id },\n skip: !id,\n onCompleted: data => {\n if (!data) {\n return;\n }\n\n const { error } = data.security.role;\n if (error) {\n goToRoute(Routes.Roles.List);\n showSnackbar(error.message);\n }\n }\n });\n\n const [create, createMutation] = useMutation(CREATE_ROLE, {\n refetchQueries: [{ query: LIST_ROLES }]\n });\n\n const [update, updateMutation] = useMutation(UPDATE_ROLE, {\n refetchQueries: [{ query: LIST_ROLES }]\n });\n\n const loading = [getQuery, createMutation, updateMutation].find(item => item.loading);\n\n const onSubmit = useCallback(\n async ({ id, name, description, slug, permissions, createdOn }: Role) => {\n if (!permissions || !permissions.length) {\n showSnackbar(t`You must configure permissions before saving!`, {\n timeout: 60000,\n dismissesOnAction: true\n });\n return;\n }\n\n const isUpdate = createdOn;\n const [operation, args] = isUpdate\n ? [\n update,\n {\n variables: {\n id,\n data: {\n name,\n permissions,\n ...(description && { description })\n }\n }\n }\n ]\n : [\n create,\n {\n variables: {\n data: {\n name,\n slug,\n description,\n permissions\n }\n }\n }\n ];\n\n const response = await operation(args);\n\n const { data: role, error } = response.data.security.role;\n if (error) {\n return showSnackbar(error.message);\n }\n\n if (!isUpdate) {\n goToRoute(Routes.Roles.List, { id: role.id });\n }\n showSnackbar(t`Role saved successfully!`);\n },\n [id]\n );\n\n const data: Role = loading ? {} : get(getQuery, \"data.security.role.data\", {});\n\n const systemRole = data.slug === \"full-access\" || data.system;\n const pluginRole = data.plugin ?? false;\n const canModifyRole = !systemRole && !pluginRole;\n\n const showEmptyView = !newEntry && !loading && isEmpty(data);\n // Render \"No content\" selected view.\n if (showEmptyView) {\n return (\n <EmptyView\n icon={<SettingsIcon />}\n title={t`Click on the left side list to display role details or create a...`}\n action={\n <Button\n icon={<AddIcon />}\n text={t`New Role`}\n data-testid=\"new-record-button\"\n onClick={() => {\n goToRoute(Routes.Roles.List, { new: true });\n }}\n />\n }\n />\n );\n }\n\n return (\n <Form data={data} onSubmit={onSubmit}>\n {({ data, form, Bind }) => {\n return (\n <SimpleForm size={\"lg\"}>\n {loading && <OverlayLoader />}\n <SimpleFormHeader title={data.name ? data.name : \"Untitled\"} />\n <SimpleFormContent>\n <FormContent\n pluginRole={pluginRole}\n canModifyRole={canModifyRole}\n newEntry={newEntry}\n />\n </SimpleFormContent>\n <SimpleFormHeader title={\"Permissions\"} rounded={false}>\n <div className={\"flex justify-end\"}>\n <Tooltip\n content=\"Copy permissions as JSON\"\n trigger={\n <IconButton\n variant={\"ghost\"}\n icon={<CopyIcon />}\n onClick={() => {\n navigator.clipboard.writeText(\n JSON.stringify(data.permissions, null, 2)\n );\n showSnackbar(\"JSON data copied to clipboard.\");\n }}\n />\n }\n />\n </div>\n </SimpleFormHeader>\n <SimpleFormContent>\n {systemRole && (\n <Grid.Column span={12}>\n <Alert type={\"warning\"} title={\"Permissions are locked\"}>\n This is a protected system role and you can't modify\n its permissions.\n </Alert>\n </Grid.Column>\n )}\n <Grid>\n <>\n {canModifyRole && (\n <Grid.Column span={12}>\n <Bind name={\"permissions\"} defaultValue={[]}>\n {bind => (\n <Permissions id={data.id || \"new\"} {...bind} />\n )}\n </Bind>\n </Grid.Column>\n )}\n </>\n </Grid>\n </SimpleFormContent>\n <SimpleFormFooter>\n {canModifyRole && (\n <>\n <Button\n variant={\"secondary\"}\n text={t`Cancel`}\n onClick={() => {\n goToRoute(Routes.Roles.List);\n }}\n data-testid=\"pb.category.new.form.button.cancel\"\n />\n <Button\n text={t`Save`}\n data-testid=\"admin.am.role.new.save\"\n onClick={ev => {\n form.submit(ev);\n }}\n />\n </>\n )}\n </SimpleFormFooter>\n </SimpleForm>\n );\n }}\n </Form>\n );\n};\n\ninterface FormContentProps {\n pluginRole: boolean;\n canModifyRole: boolean;\n newEntry: boolean;\n}\n\nconst FormContent = (props: FormContentProps) => {\n const { pluginRole, canModifyRole, newEntry } = props;\n const form = useForm();\n const { generateSlug } = useGenerateSlug(form, \"name\", \"slug\");\n\n return (\n <Grid>\n <>\n {pluginRole && (\n <Grid.Column span={12}>\n <Alert type={\"warning\"} title={\"Permissions are locked\"}>\n This role is registered via an extension, and cannot be modified.\n </Alert>\n </Grid.Column>\n )}\n <Grid.Column span={6}>\n <Bind name=\"name\" validators={validation.create(\"required,minLength:1\")}>\n <Input\n required\n label={t`Name`}\n disabled={!canModifyRole}\n onBlur={generateSlug}\n data-testid=\"admin.am.role.new.name\"\n />\n </Bind>\n </Grid.Column>\n <Grid.Column span={6}>\n <Bind name=\"slug\" validators={validation.create(\"required,minLength:1\")}>\n <Input\n required\n disabled={!canModifyRole || !newEntry}\n label={t`Slug`}\n data-testid=\"admin.am.role.new.slug\"\n />\n </Bind>\n </Grid.Column>\n <Grid.Column span={12}>\n <Bind\n name=\"description\"\n validators={validation.create(\"maxLength:500\")}\n defaultValue={\"\"}\n >\n <Textarea\n label={t`Description`}\n rows={3}\n disabled={!canModifyRole}\n data-testid=\"admin.am.role.new.description\"\n />\n </Bind>\n </Grid.Column>\n </>\n </Grid>\n );\n};\n"],"names":["t","i18n","RolesForm","id","newEntry","goToRoute","useRouter","showSnackbar","useSnackbar","getQuery","useQuery","READ_ROLE","data","error","Routes","create","createMutation","useMutation","CREATE_ROLE","LIST_ROLES","update","updateMutation","UPDATE_ROLE","loading","item","onSubmit","useCallback","name","description","slug","permissions","createdOn","isUpdate","operation","args","response","role","get","systemRole","pluginRole","canModifyRole","showEmptyView","isEmpty","EmptyView","SettingsIcon","Button","AddIcon","Form","form","Bind","SimpleForm","OverlayLoader","SimpleFormHeader","SimpleFormContent","FormContent","Tooltip","IconButton","CopyIcon","navigator","JSON","Grid","Alert","bind","Permissions","SimpleFormFooter","ev","props","useForm","generateSlug","useGenerateSlug","validation","Input","Textarea"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Role } from "../../../types.js";
|
|
2
|
+
export interface ListRolesResponse {
|
|
3
|
+
security: {
|
|
4
|
+
roles: {
|
|
5
|
+
data: Role[];
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare const LIST_ROLES: import("graphql").DocumentNode;
|
|
10
|
+
export declare const READ_ROLE: import("graphql").DocumentNode;
|
|
11
|
+
export declare const CREATE_ROLE: import("graphql").DocumentNode;
|
|
12
|
+
export declare const UPDATE_ROLE: import("graphql").DocumentNode;
|
|
13
|
+
export declare const DELETE_ROLE: import("graphql").DocumentNode;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import graphql_tag from "graphql-tag";
|
|
2
|
+
const fields = `
|
|
3
|
+
id
|
|
4
|
+
name
|
|
5
|
+
slug
|
|
6
|
+
description
|
|
7
|
+
permissions
|
|
8
|
+
system
|
|
9
|
+
plugin
|
|
10
|
+
createdOn
|
|
11
|
+
`;
|
|
12
|
+
const LIST_ROLES = graphql_tag`
|
|
13
|
+
query listRoles {
|
|
14
|
+
security {
|
|
15
|
+
roles: listRoles {
|
|
16
|
+
data {
|
|
17
|
+
${fields}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
const READ_ROLE = graphql_tag`
|
|
24
|
+
query getRole($id: ID!) {
|
|
25
|
+
security {
|
|
26
|
+
role: getRole(where: { id: $id }){
|
|
27
|
+
data {
|
|
28
|
+
${fields}
|
|
29
|
+
}
|
|
30
|
+
error {
|
|
31
|
+
code
|
|
32
|
+
message
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
const CREATE_ROLE = graphql_tag`
|
|
39
|
+
mutation createRole($data: SecurityRoleCreateInput!){
|
|
40
|
+
security {
|
|
41
|
+
role: createRole(data: $data) {
|
|
42
|
+
data {
|
|
43
|
+
${fields}
|
|
44
|
+
}
|
|
45
|
+
error {
|
|
46
|
+
code
|
|
47
|
+
message
|
|
48
|
+
data
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
const UPDATE_ROLE = graphql_tag`
|
|
55
|
+
mutation updateRole($id: ID!, $data: SecurityRoleUpdateInput!){
|
|
56
|
+
security {
|
|
57
|
+
role: updateRole(id: $id, data: $data) {
|
|
58
|
+
data {
|
|
59
|
+
${fields}
|
|
60
|
+
}
|
|
61
|
+
error {
|
|
62
|
+
code
|
|
63
|
+
message
|
|
64
|
+
data
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
const DELETE_ROLE = graphql_tag`
|
|
71
|
+
mutation deleteRole($id: ID!) {
|
|
72
|
+
security {
|
|
73
|
+
deleteRole(id: $id) {
|
|
74
|
+
data
|
|
75
|
+
error {
|
|
76
|
+
code
|
|
77
|
+
message
|
|
78
|
+
data
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
export { CREATE_ROLE, DELETE_ROLE, LIST_ROLES, READ_ROLE, UPDATE_ROLE };
|
|
85
|
+
|
|
86
|
+
//# sourceMappingURL=graphql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui/views/Roles/graphql.js","sources":["../../../../src/ui/views/Roles/graphql.ts"],"sourcesContent":["import gql from \"graphql-tag\";\nimport type { Role } from \"~/types.js\";\n\nconst fields = `\n id\n name\n slug\n description\n permissions\n system\n plugin\n createdOn\n`;\n\nexport interface ListRolesResponse {\n security: {\n roles: {\n data: Role[];\n };\n };\n}\n\nexport const LIST_ROLES = gql`\n query listRoles {\n security {\n roles: listRoles {\n data {\n ${fields}\n }\n }\n }\n }\n`;\n\nexport const READ_ROLE = gql`\n query getRole($id: ID!) {\n security {\n role: getRole(where: { id: $id }){\n data {\n ${fields}\n }\n error {\n code\n message\n }\n }\n }\n }\n`;\n\nexport const CREATE_ROLE = gql`\n mutation createRole($data: SecurityRoleCreateInput!){\n security {\n role: createRole(data: $data) {\n data {\n ${fields}\n }\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n\nexport const UPDATE_ROLE = gql`\n mutation updateRole($id: ID!, $data: SecurityRoleUpdateInput!){\n security {\n role: updateRole(id: $id, data: $data) {\n data {\n ${fields}\n }\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n\nexport const DELETE_ROLE = gql`\n mutation deleteRole($id: ID!) {\n security {\n deleteRole(id: $id) {\n data\n error {\n code\n message\n data\n }\n }\n }\n }\n`;\n"],"names":["fields","LIST_ROLES","gql","READ_ROLE","CREATE_ROLE","UPDATE_ROLE","DELETE_ROLE"],"mappings":";AAGA,MAAMA,SAAS,CAAC;;;;;;;;;AAShB,CAAC;AAUM,MAAMC,aAAaC,WAAG,CAAC;;;;;oBAKV,EAAEF,OAAO;;;;;AAK7B,CAAC;AAEM,MAAMG,YAAYD,WAAG,CAAC;;;;;oBAKT,EAAEF,OAAO;;;;;;;;;AAS7B,CAAC;AAEM,MAAMI,cAAcF,WAAG,CAAC;;;;;oBAKX,EAAEF,OAAO;;;;;;;;;;AAU7B,CAAC;AAEM,MAAMK,cAAcH,WAAG,CAAC;;;;;oBAKX,EAAEF,OAAO;;;;;;;;;;AAU7B,CAAC;AAEM,MAAMM,cAAcJ,WAAG,CAAC;;;;;;;;;;;;;AAa/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Roles.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Roles.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import react from "react";
|
|
2
|
+
import { TeamsDataList } from "./TeamsDataList.js";
|
|
3
|
+
import { TeamsForm } from "./TeamsForm.js";
|
|
4
|
+
import { LeftPanel, RightPanel, SplitView, useRoute } from "@webiny/app-admin";
|
|
5
|
+
import { Routes } from "../../../routes.js";
|
|
6
|
+
const Teams = ()=>{
|
|
7
|
+
const { route } = useRoute(Routes.Roles.List);
|
|
8
|
+
return /*#__PURE__*/ react.createElement(SplitView, null, /*#__PURE__*/ react.createElement(LeftPanel, null, /*#__PURE__*/ react.createElement(TeamsDataList, {
|
|
9
|
+
activeId: route.params.id
|
|
10
|
+
})), /*#__PURE__*/ react.createElement(RightPanel, null, /*#__PURE__*/ react.createElement(TeamsForm, {
|
|
11
|
+
newEntry: true === route.params.new,
|
|
12
|
+
id: route.params.id
|
|
13
|
+
})));
|
|
14
|
+
};
|
|
15
|
+
export { Teams };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=Teams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui/views/Teams/Teams.js","sources":["../../../../src/ui/views/Teams/Teams.tsx"],"sourcesContent":["import React from \"react\";\nimport { TeamsDataList } from \"./TeamsDataList.js\";\nimport { TeamsForm } from \"./TeamsForm.js\";\nimport { SplitView, LeftPanel, RightPanel, useRoute } from \"@webiny/app-admin\";\nimport { Routes } from \"~/routes.js\";\n\nexport const Teams = () => {\n const { route } = useRoute(Routes.Roles.List);\n\n return (\n <SplitView>\n <LeftPanel>\n <TeamsDataList activeId={route.params.id} />\n </LeftPanel>\n <RightPanel>\n <TeamsForm newEntry={route.params.new === true} id={route.params.id} />\n </RightPanel>\n </SplitView>\n );\n};\n"],"names":["Teams","route","useRoute","Routes","SplitView","LeftPanel","TeamsDataList","RightPanel","TeamsForm"],"mappings":";;;;;AAMO,MAAMA,QAAQ;IACjB,MAAM,EAAEC,KAAK,EAAE,GAAGC,SAASC,OAAO,KAAK,CAAC,IAAI;IAE5C,OAAO,WAAP,GACI,oBAACC,WAASA,MAAAA,WAAAA,GACN,oBAACC,WAASA,MAAAA,WAAAA,GACN,oBAACC,eAAaA;QAAC,UAAUL,MAAM,MAAM,CAAC,EAAE;uBAE5C,oBAACM,YAAUA,MAAAA,WAAAA,GACP,oBAACC,WAASA;QAAC,UAAUP,AAAqB,SAArBA,MAAM,MAAM,CAAC,GAAG;QAAW,IAAIA,MAAM,MAAM,CAAC,EAAE;;AAInF"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import react, { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import orderBy from "lodash/orderBy.js";
|
|
3
|
+
import { Button, DataList, DataListModal, DeleteIcon, Grid, List, Select, Tooltip } from "@webiny/admin-ui";
|
|
4
|
+
import { ReactComponent } from "@webiny/icons/add.svg";
|
|
5
|
+
import { i18n } from "@webiny/app/i18n/index.js";
|
|
6
|
+
import { SearchUI, useConfirmationDialog, useRouter, useSnackbar } from "@webiny/app-admin";
|
|
7
|
+
import { useMutation, useQuery } from "@apollo/react-hooks";
|
|
8
|
+
import { DELETE_TEAM, LIST_TEAMS } from "./graphql.js";
|
|
9
|
+
import { deserializeSorters } from "../utils.js";
|
|
10
|
+
import { Routes } from "../../../routes.js";
|
|
11
|
+
const t = i18n.ns("app-security/admin/teams/data-list");
|
|
12
|
+
const SORTERS = [
|
|
13
|
+
{
|
|
14
|
+
label: t`Newest to oldest`,
|
|
15
|
+
sorter: "createdOn_DESC"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
label: t`Oldest to newest`,
|
|
19
|
+
sorter: "createdOn_ASC"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: t`Name A-Z`,
|
|
23
|
+
sorter: "name_ASC"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: t`Name Z-A`,
|
|
27
|
+
sorter: "name_DESC"
|
|
28
|
+
}
|
|
29
|
+
];
|
|
30
|
+
const TeamsDataList = ({ activeId })=>{
|
|
31
|
+
const [filter, setFilter] = useState("");
|
|
32
|
+
const [sort, setSort] = useState(SORTERS[0].sorter);
|
|
33
|
+
const { goToRoute } = useRouter();
|
|
34
|
+
const { showSnackbar } = useSnackbar();
|
|
35
|
+
const { showConfirmation } = useConfirmationDialog({
|
|
36
|
+
dataTestId: "default-data-list.delete-dialog"
|
|
37
|
+
});
|
|
38
|
+
const { data: listResponse, loading: listLoading } = useQuery(LIST_TEAMS);
|
|
39
|
+
const [deleteIt, { loading: deleteLoading }] = useMutation(DELETE_TEAM, {
|
|
40
|
+
refetchQueries: [
|
|
41
|
+
{
|
|
42
|
+
query: LIST_TEAMS
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
const data = listLoading && !listResponse ? [] : listResponse?.security.teams.data || [];
|
|
47
|
+
const filterTeam = useCallback(({ name, slug, description })=>name.toLowerCase().includes(filter) || slug.toLowerCase().includes(filter) || description && description.toLowerCase().includes(filter), [
|
|
48
|
+
filter
|
|
49
|
+
]);
|
|
50
|
+
const sortTeams = useCallback((teams)=>{
|
|
51
|
+
if (!sort) return teams;
|
|
52
|
+
const [key, sortBy] = deserializeSorters(sort);
|
|
53
|
+
return orderBy(teams, [
|
|
54
|
+
key
|
|
55
|
+
], [
|
|
56
|
+
sortBy
|
|
57
|
+
]);
|
|
58
|
+
}, [
|
|
59
|
+
sort
|
|
60
|
+
]);
|
|
61
|
+
const deleteItem = useCallback((item)=>{
|
|
62
|
+
showConfirmation(async ()=>{
|
|
63
|
+
const { data } = await deleteIt({
|
|
64
|
+
variables: item
|
|
65
|
+
});
|
|
66
|
+
const { error } = data.security.deleteTeam;
|
|
67
|
+
if (error) return showSnackbar(error.message);
|
|
68
|
+
showSnackbar(t`Team "{slug}" deleted.`({
|
|
69
|
+
slug: item.slug
|
|
70
|
+
}));
|
|
71
|
+
if (activeId === item.id) goToRoute(Routes.Teams.List);
|
|
72
|
+
});
|
|
73
|
+
}, [
|
|
74
|
+
activeId
|
|
75
|
+
]);
|
|
76
|
+
const teamsDataListModalOverlay = useMemo(()=>/*#__PURE__*/ react.createElement(DataListModal.Content, null, /*#__PURE__*/ react.createElement(Grid, null, /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
77
|
+
span: 12
|
|
78
|
+
}, /*#__PURE__*/ react.createElement(Select, {
|
|
79
|
+
value: sort,
|
|
80
|
+
onChange: setSort,
|
|
81
|
+
label: t`Sort by`,
|
|
82
|
+
options: SORTERS.map(({ label, sorter: value })=>({
|
|
83
|
+
label,
|
|
84
|
+
value
|
|
85
|
+
}))
|
|
86
|
+
})))), [
|
|
87
|
+
sort
|
|
88
|
+
]);
|
|
89
|
+
const filteredData = "" === filter ? data : data.filter(filterTeam);
|
|
90
|
+
const teamList = sortTeams(filteredData);
|
|
91
|
+
return /*#__PURE__*/ react.createElement(DataList, {
|
|
92
|
+
title: t`Teams`,
|
|
93
|
+
actions: /*#__PURE__*/ react.createElement(Button, {
|
|
94
|
+
text: t`New`,
|
|
95
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
96
|
+
size: "sm",
|
|
97
|
+
className: "ml-xs",
|
|
98
|
+
"data-testid": "new-record-button",
|
|
99
|
+
onClick: ()=>{
|
|
100
|
+
goToRoute(Routes.Teams.List, {
|
|
101
|
+
new: true
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}),
|
|
105
|
+
data: teamList,
|
|
106
|
+
loading: listLoading || deleteLoading,
|
|
107
|
+
search: /*#__PURE__*/ react.createElement(SearchUI, {
|
|
108
|
+
value: filter,
|
|
109
|
+
onChange: setFilter,
|
|
110
|
+
inputPlaceholder: t`Search teams...`
|
|
111
|
+
}),
|
|
112
|
+
modalOverlay: teamsDataListModalOverlay,
|
|
113
|
+
modalOverlayAction: /*#__PURE__*/ react.createElement(DataListModal.Trigger, {
|
|
114
|
+
"data-testid": "default-data-list.filter"
|
|
115
|
+
})
|
|
116
|
+
}, ({ data })=>/*#__PURE__*/ react.createElement(List, {
|
|
117
|
+
"data-testid": "default-data-list"
|
|
118
|
+
}, data.map((item)=>/*#__PURE__*/ react.createElement(List.Item, {
|
|
119
|
+
key: item.id,
|
|
120
|
+
selected: item.id === activeId,
|
|
121
|
+
title: item.name,
|
|
122
|
+
description: item.description ?? "(no description)",
|
|
123
|
+
onClick: ()=>{
|
|
124
|
+
goToRoute(Routes.Teams.List, {
|
|
125
|
+
id: item.id
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
actions: item.system || item.plugin ? /*#__PURE__*/ react.createElement(Tooltip, {
|
|
129
|
+
content: /*#__PURE__*/ react.createElement("span", null, item.system ? t`Cannot delete system teams.` : t`Cannot delete teams created via extensions.`),
|
|
130
|
+
trigger: /*#__PURE__*/ react.createElement(DeleteIcon, {
|
|
131
|
+
disabled: true
|
|
132
|
+
})
|
|
133
|
+
}) : /*#__PURE__*/ react.createElement(DeleteIcon, {
|
|
134
|
+
onClick: ()=>deleteItem(item),
|
|
135
|
+
"data-testid": "default-data-list.delete"
|
|
136
|
+
})
|
|
137
|
+
}))));
|
|
138
|
+
};
|
|
139
|
+
export { TeamsDataList };
|
|
140
|
+
|
|
141
|
+
//# sourceMappingURL=TeamsDataList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui/views/Teams/TeamsDataList.js","sources":["../../../../src/ui/views/Teams/TeamsDataList.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from \"react\";\nimport orderBy from \"lodash/orderBy.js\";\nimport { Button, Grid, Select, Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as AddIcon } from \"@webiny/icons/add.svg\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { List, DataList, DataListModal, DeleteIcon } from \"@webiny/admin-ui\";\n\nimport { useRouter, useSnackbar, useConfirmationDialog, SearchUI } from \"@webiny/app-admin\";\nimport { useQuery, useMutation } from \"@apollo/react-hooks\";\nimport type { ListTeamsResponse } from \"./graphql.js\";\nimport { LIST_TEAMS, DELETE_TEAM } from \"./graphql.js\";\nimport { deserializeSorters } from \"../utils.js\";\nimport type { Team } from \"~/types.js\";\nimport { Routes } from \"~/routes.js\";\n\nconst t = i18n.ns(\"app-security/admin/teams/data-list\");\n\nconst SORTERS = [\n {\n label: t`Newest to oldest`,\n sorter: \"createdOn_DESC\"\n },\n {\n label: t`Oldest to newest`,\n sorter: \"createdOn_ASC\"\n },\n {\n label: t`Name A-Z`,\n sorter: \"name_ASC\"\n },\n {\n label: t`Name Z-A`,\n sorter: \"name_DESC\"\n }\n];\n\nexport interface TeamsDataListProps {\n activeId: string | undefined;\n}\n\nexport const TeamsDataList = ({ activeId }: TeamsDataListProps) => {\n const [filter, setFilter] = useState(\"\");\n const [sort, setSort] = useState(SORTERS[0].sorter);\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n const { showConfirmation } = useConfirmationDialog({\n dataTestId: \"default-data-list.delete-dialog\"\n });\n\n const { data: listResponse, loading: listLoading } = useQuery<ListTeamsResponse>(LIST_TEAMS);\n\n const [deleteIt, { loading: deleteLoading }] = useMutation(DELETE_TEAM, {\n refetchQueries: [{ query: LIST_TEAMS }]\n });\n\n const data = listLoading && !listResponse ? [] : listResponse?.security.teams.data || [];\n\n const filterTeam = useCallback(\n ({ name, slug, description }: Team) => {\n return (\n name.toLowerCase().includes(filter) ||\n slug.toLowerCase().includes(filter) ||\n (description && description.toLowerCase().includes(filter))\n );\n },\n [filter]\n );\n\n const sortTeams = useCallback(\n (teams: Team[]) => {\n if (!sort) {\n return teams;\n }\n const [key, sortBy] = deserializeSorters(sort);\n return orderBy(teams, [key], [sortBy]);\n },\n [sort]\n );\n\n const deleteItem = useCallback(\n (item: Team) => {\n showConfirmation(async () => {\n const { data } = await deleteIt({\n variables: item\n });\n\n const { error } = data.security.deleteTeam;\n if (error) {\n return showSnackbar(error.message);\n }\n\n showSnackbar(t`Team \"{slug}\" deleted.`({ slug: item.slug }));\n\n if (activeId === item.id) {\n goToRoute(Routes.Teams.List);\n }\n });\n },\n [activeId]\n );\n\n const teamsDataListModalOverlay = useMemo(\n () => (\n <DataListModal.Content>\n <Grid>\n <Grid.Column span={12}>\n <Select\n value={sort}\n onChange={setSort}\n label={t`Sort by`}\n options={SORTERS.map(({ label, sorter: value }) => {\n return {\n label,\n value\n };\n })}\n />\n </Grid.Column>\n </Grid>\n </DataListModal.Content>\n ),\n [sort]\n );\n\n const filteredData = filter === \"\" ? data : data.filter(filterTeam);\n const teamList = sortTeams(filteredData);\n\n return (\n <DataList\n title={t`Teams`}\n actions={\n <Button\n text={t`New`}\n icon={<AddIcon />}\n size={\"sm\"}\n className={\"ml-xs\"}\n data-testid=\"new-record-button\"\n onClick={() => {\n goToRoute(Routes.Teams.List, { new: true });\n }}\n />\n }\n data={teamList}\n loading={listLoading || deleteLoading}\n search={\n <SearchUI\n value={filter}\n onChange={setFilter}\n inputPlaceholder={t`Search teams...`}\n />\n }\n modalOverlay={teamsDataListModalOverlay}\n modalOverlayAction={<DataListModal.Trigger data-testid={\"default-data-list.filter\"} />}\n >\n {({ data }: { data: Team[] }) => (\n <List data-testid=\"default-data-list\">\n {data.map(item => (\n <List.Item\n key={item.id}\n selected={item.id === activeId}\n title={item.name}\n description={item.description ?? \"(no description)\"}\n onClick={() => {\n goToRoute(Routes.Teams.List, { id: item.id });\n }}\n actions={\n item.system || item.plugin ? (\n <Tooltip\n content={\n <span>\n {item.system\n ? t`Cannot delete system teams.`\n : t`Cannot delete teams created via extensions.`}\n </span>\n }\n trigger={<DeleteIcon disabled />}\n />\n ) : (\n <DeleteIcon\n onClick={() => deleteItem(item)}\n data-testid={\"default-data-list.delete\"}\n />\n )\n }\n />\n ))}\n </List>\n )}\n </DataList>\n );\n};\n"],"names":["t","i18n","SORTERS","TeamsDataList","activeId","filter","setFilter","useState","sort","setSort","goToRoute","useRouter","showSnackbar","useSnackbar","showConfirmation","useConfirmationDialog","listResponse","listLoading","useQuery","LIST_TEAMS","deleteIt","deleteLoading","useMutation","DELETE_TEAM","data","filterTeam","useCallback","name","slug","description","sortTeams","teams","key","sortBy","deserializeSorters","orderBy","deleteItem","item","error","Routes","teamsDataListModalOverlay","useMemo","DataListModal","Grid","Select","label","value","filteredData","teamList","DataList","Button","AddIcon","SearchUI","List","Tooltip","DeleteIcon"],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import react, { useCallback } from "react";
|
|
2
|
+
import { useMutation, useQuery } from "@apollo/react-hooks";
|
|
3
|
+
import pick from "lodash/pick.js";
|
|
4
|
+
import get from "lodash/get.js";
|
|
5
|
+
import { i18n } from "@webiny/app/i18n/index.js";
|
|
6
|
+
import { Bind, Form, useForm, useGenerateSlug } from "@webiny/form";
|
|
7
|
+
import { validation } from "@webiny/validation";
|
|
8
|
+
import { EmptyView, RolesMultiAutocomplete, SimpleForm, SimpleFormContent, SimpleFormFooter, SimpleFormHeader, useRouter, useSnackbar } from "@webiny/app-admin";
|
|
9
|
+
import { CREATE_TEAM, LIST_TEAMS, READ_TEAM, UPDATE_TEAM } from "./graphql.js";
|
|
10
|
+
import isEmpty from "lodash/isEmpty.js";
|
|
11
|
+
import { ReactComponent } from "@webiny/app-admin/assets/icons/add-18px.svg";
|
|
12
|
+
import { ReactComponent as settings_svg_ReactComponent } from "@webiny/icons/settings.svg";
|
|
13
|
+
import { Alert, Button, Grid, Input, OverlayLoader, Textarea } from "@webiny/admin-ui";
|
|
14
|
+
import { Routes } from "../../../routes.js";
|
|
15
|
+
const t = i18n.ns("app-security/admin/teams/form");
|
|
16
|
+
const TeamsForm = ({ newEntry, id })=>{
|
|
17
|
+
const { goToRoute } = useRouter();
|
|
18
|
+
const { showSnackbar } = useSnackbar();
|
|
19
|
+
const getQuery = useQuery(READ_TEAM, {
|
|
20
|
+
variables: {
|
|
21
|
+
id
|
|
22
|
+
},
|
|
23
|
+
skip: !id,
|
|
24
|
+
onCompleted: (data)=>{
|
|
25
|
+
if (!data) return;
|
|
26
|
+
const { error } = data.security.team;
|
|
27
|
+
if (error) {
|
|
28
|
+
goToRoute(Routes.Teams.List);
|
|
29
|
+
showSnackbar(error.message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
const [create, createMutation] = useMutation(CREATE_TEAM, {
|
|
34
|
+
refetchQueries: [
|
|
35
|
+
{
|
|
36
|
+
query: LIST_TEAMS
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
const [update, updateMutation] = useMutation(UPDATE_TEAM, {
|
|
41
|
+
refetchQueries: [
|
|
42
|
+
{
|
|
43
|
+
query: LIST_TEAMS
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
});
|
|
47
|
+
const loading = [
|
|
48
|
+
getQuery,
|
|
49
|
+
createMutation,
|
|
50
|
+
updateMutation
|
|
51
|
+
].find((item)=>item.loading);
|
|
52
|
+
const onSubmit = useCallback(async (formData)=>{
|
|
53
|
+
const isUpdate = formData.createdOn;
|
|
54
|
+
const [operation, args] = isUpdate ? [
|
|
55
|
+
update,
|
|
56
|
+
{
|
|
57
|
+
variables: {
|
|
58
|
+
id: formData.id,
|
|
59
|
+
data: pick(formData, [
|
|
60
|
+
"name",
|
|
61
|
+
"description",
|
|
62
|
+
"roles"
|
|
63
|
+
])
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
] : [
|
|
67
|
+
create,
|
|
68
|
+
{
|
|
69
|
+
variables: {
|
|
70
|
+
data: pick(formData, [
|
|
71
|
+
"name",
|
|
72
|
+
"slug",
|
|
73
|
+
"description",
|
|
74
|
+
"roles"
|
|
75
|
+
])
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
];
|
|
79
|
+
const response = await operation(args);
|
|
80
|
+
const { data: team, error } = response.data.security.team;
|
|
81
|
+
if (error) return showSnackbar(error.message);
|
|
82
|
+
if (!isUpdate) goToRoute(Routes.Teams.List, {
|
|
83
|
+
id: team.id
|
|
84
|
+
});
|
|
85
|
+
showSnackbar(t`Team saved successfully!`);
|
|
86
|
+
}, [
|
|
87
|
+
id
|
|
88
|
+
]);
|
|
89
|
+
const data = loading ? {} : get(getQuery, "data.security.team.data", {});
|
|
90
|
+
const systemTeam = data.system;
|
|
91
|
+
const pluginTeam = data.plugin ?? false;
|
|
92
|
+
const canModifyTeam = !systemTeam && !pluginTeam;
|
|
93
|
+
const showEmptyView = !newEntry && !loading && isEmpty(data);
|
|
94
|
+
if (showEmptyView) return /*#__PURE__*/ react.createElement(EmptyView, {
|
|
95
|
+
icon: /*#__PURE__*/ react.createElement(settings_svg_ReactComponent, null),
|
|
96
|
+
title: t`Click on the left side list to display team details or create a...`,
|
|
97
|
+
action: /*#__PURE__*/ react.createElement(Button, {
|
|
98
|
+
text: t`New Team`,
|
|
99
|
+
icon: /*#__PURE__*/ react.createElement(ReactComponent, null),
|
|
100
|
+
"data-testid": "new-record-button",
|
|
101
|
+
onClick: ()=>{
|
|
102
|
+
goToRoute(Routes.Teams.List, {
|
|
103
|
+
new: true
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
return /*#__PURE__*/ react.createElement(Form, {
|
|
109
|
+
data: data,
|
|
110
|
+
onSubmit: onSubmit
|
|
111
|
+
}, ({ data, form })=>/*#__PURE__*/ react.createElement(SimpleForm, null, loading && /*#__PURE__*/ react.createElement(OverlayLoader, null), /*#__PURE__*/ react.createElement(SimpleFormHeader, {
|
|
112
|
+
title: data.name ? data.name : "Untitled"
|
|
113
|
+
}), /*#__PURE__*/ react.createElement(SimpleFormContent, null, /*#__PURE__*/ react.createElement(FormContent, {
|
|
114
|
+
pluginTeam: pluginTeam,
|
|
115
|
+
systemTeam: systemTeam,
|
|
116
|
+
canModifyTeam: canModifyTeam,
|
|
117
|
+
newEntry: newEntry
|
|
118
|
+
})), /*#__PURE__*/ react.createElement(SimpleFormFooter, null, /*#__PURE__*/ react.createElement(Button, {
|
|
119
|
+
variant: "secondary",
|
|
120
|
+
text: t`Cancel`,
|
|
121
|
+
onClick: ()=>{
|
|
122
|
+
goToRoute(Routes.Teams.List);
|
|
123
|
+
}
|
|
124
|
+
}), canModifyTeam && /*#__PURE__*/ react.createElement(Button, {
|
|
125
|
+
text: t`Save`,
|
|
126
|
+
"data-testid": "admin.am.team.new.save",
|
|
127
|
+
onClick: (ev)=>{
|
|
128
|
+
form.submit(ev);
|
|
129
|
+
}
|
|
130
|
+
}))));
|
|
131
|
+
};
|
|
132
|
+
const FormContent = (props)=>{
|
|
133
|
+
const { newEntry, pluginTeam, systemTeam, canModifyTeam } = props;
|
|
134
|
+
const form = useForm();
|
|
135
|
+
const { generateSlug } = useGenerateSlug(form, "name", "slug");
|
|
136
|
+
return /*#__PURE__*/ react.createElement(Grid, null, /*#__PURE__*/ react.createElement(react.Fragment, null, systemTeam && /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
137
|
+
span: 12
|
|
138
|
+
}, /*#__PURE__*/ react.createElement(Alert, {
|
|
139
|
+
type: "info",
|
|
140
|
+
title: "Permissions are locked"
|
|
141
|
+
}, "This is a protected system team and you can't modify its permissions.")), pluginTeam && /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
142
|
+
span: 12
|
|
143
|
+
}, /*#__PURE__*/ react.createElement(Alert, {
|
|
144
|
+
type: "info",
|
|
145
|
+
title: "Important"
|
|
146
|
+
}, "This team is registered via an extension, and cannot be modified."))), /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
147
|
+
span: 6
|
|
148
|
+
}, /*#__PURE__*/ react.createElement(Bind, {
|
|
149
|
+
name: "name",
|
|
150
|
+
validators: validation.create("required,minLength:1")
|
|
151
|
+
}, /*#__PURE__*/ react.createElement(Input, {
|
|
152
|
+
required: true,
|
|
153
|
+
onBlur: generateSlug,
|
|
154
|
+
disabled: !canModifyTeam,
|
|
155
|
+
label: t`Name`,
|
|
156
|
+
"data-testid": "admin.am.team.new.name"
|
|
157
|
+
}))), /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
158
|
+
span: 6
|
|
159
|
+
}, /*#__PURE__*/ react.createElement(Bind, {
|
|
160
|
+
name: "slug",
|
|
161
|
+
validators: validation.create("required,minLength:1")
|
|
162
|
+
}, /*#__PURE__*/ react.createElement(Input, {
|
|
163
|
+
required: true,
|
|
164
|
+
disabled: !canModifyTeam || !newEntry,
|
|
165
|
+
label: t`Slug`,
|
|
166
|
+
"data-testid": "admin.am.team.new.slug"
|
|
167
|
+
}))), /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
168
|
+
span: 12
|
|
169
|
+
}, /*#__PURE__*/ react.createElement(Bind, {
|
|
170
|
+
name: "description",
|
|
171
|
+
validators: validation.create("maxLength:500"),
|
|
172
|
+
defaultValue: ""
|
|
173
|
+
}, /*#__PURE__*/ react.createElement(Textarea, {
|
|
174
|
+
disabled: !canModifyTeam,
|
|
175
|
+
label: t`Description`,
|
|
176
|
+
rows: 3,
|
|
177
|
+
"data-testid": "admin.am.team.new.description"
|
|
178
|
+
}))), /*#__PURE__*/ react.createElement(Grid.Column, {
|
|
179
|
+
span: 12
|
|
180
|
+
}, /*#__PURE__*/ react.createElement(Bind, {
|
|
181
|
+
name: "roles",
|
|
182
|
+
validators: validation.create("required")
|
|
183
|
+
}, /*#__PURE__*/ react.createElement(RolesMultiAutocomplete, {
|
|
184
|
+
disabled: !canModifyTeam,
|
|
185
|
+
label: t`Roles`,
|
|
186
|
+
"data-testid": "admin.am.team.new.roles"
|
|
187
|
+
}))));
|
|
188
|
+
};
|
|
189
|
+
export { TeamsForm };
|
|
190
|
+
|
|
191
|
+
//# sourceMappingURL=TeamsForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui/views/Teams/TeamsForm.js","sources":["../../../../src/ui/views/Teams/TeamsForm.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { useMutation, useQuery } from \"@apollo/react-hooks\";\nimport pick from \"lodash/pick.js\";\nimport get from \"lodash/get.js\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { Bind, Form, useForm, useGenerateSlug } from \"@webiny/form\";\nimport { validation } from \"@webiny/validation\";\nimport {\n SimpleForm,\n SimpleFormFooter,\n SimpleFormContent,\n SimpleFormHeader,\n EmptyView,\n useSnackbar,\n useRouter\n} from \"@webiny/app-admin\";\nimport { CREATE_TEAM, LIST_TEAMS, READ_TEAM, UPDATE_TEAM } from \"./graphql.js\";\nimport isEmpty from \"lodash/isEmpty.js\";\nimport { ReactComponent as AddIcon } from \"@webiny/app-admin/assets/icons/add-18px.svg\";\nimport type { Team } from \"~/types.js\";\nimport { ReactComponent as SettingsIcon } from \"@webiny/icons/settings.svg\";\nimport { Alert, Button, Grid, Input, OverlayLoader, Textarea } from \"@webiny/admin-ui\";\nimport { RolesMultiAutocomplete } from \"@webiny/app-admin\";\nimport { Routes } from \"~/routes.js\";\n\nconst t = i18n.ns(\"app-security/admin/teams/form\");\n\nexport interface TeamsFormProps {\n newEntry: boolean;\n id: string | undefined;\n}\n\nexport const TeamsForm = ({ newEntry, id }: TeamsFormProps) => {\n const { goToRoute } = useRouter();\n const { showSnackbar } = useSnackbar();\n\n const getQuery = useQuery(READ_TEAM, {\n variables: { id },\n skip: !id,\n onCompleted: data => {\n if (!data) {\n return;\n }\n\n const { error } = data.security.team;\n if (error) {\n goToRoute(Routes.Teams.List);\n showSnackbar(error.message);\n }\n }\n });\n\n const [create, createMutation] = useMutation(CREATE_TEAM, {\n refetchQueries: [{ query: LIST_TEAMS }]\n });\n\n const [update, updateMutation] = useMutation(UPDATE_TEAM, {\n refetchQueries: [{ query: LIST_TEAMS }]\n });\n\n const loading = [getQuery, createMutation, updateMutation].find(item => item.loading);\n\n const onSubmit = useCallback(\n async (formData: Team) => {\n const isUpdate = formData.createdOn;\n const [operation, args] = isUpdate\n ? [\n update,\n {\n variables: {\n id: formData.id,\n data: pick(formData, [\"name\", \"description\", \"roles\"])\n }\n }\n ]\n : [\n create,\n {\n variables: {\n data: pick(formData, [\"name\", \"slug\", \"description\", \"roles\"])\n }\n }\n ];\n\n const response = await operation(args);\n\n const { data: team, error } = response.data.security.team;\n if (error) {\n return showSnackbar(error.message);\n }\n\n if (!isUpdate) {\n goToRoute(Routes.Teams.List, { id: team.id });\n }\n showSnackbar(t`Team saved successfully!`);\n },\n [id]\n );\n\n const data = loading ? {} : get(getQuery, \"data.security.team.data\", {});\n\n const systemTeam = data.system;\n const pluginTeam = data.plugin ?? false;\n const canModifyTeam = !systemTeam && !pluginTeam;\n\n const showEmptyView = !newEntry && !loading && isEmpty(data);\n // Render \"No content\" selected view.\n if (showEmptyView) {\n return (\n <EmptyView\n icon={<SettingsIcon />}\n title={t`Click on the left side list to display team details or create a...`}\n action={\n <Button\n text={t`New Team`}\n icon={<AddIcon />}\n data-testid=\"new-record-button\"\n onClick={() => {\n goToRoute(Routes.Teams.List, { new: true });\n }}\n />\n }\n />\n );\n }\n\n return (\n <Form data={data} onSubmit={onSubmit}>\n {({ data, form }) => {\n return (\n <SimpleForm>\n {loading && <OverlayLoader />}\n <SimpleFormHeader title={data.name ? data.name : \"Untitled\"} />\n <SimpleFormContent>\n <FormContent\n pluginTeam={pluginTeam}\n systemTeam={systemTeam}\n canModifyTeam={canModifyTeam}\n newEntry={newEntry}\n />\n </SimpleFormContent>\n <SimpleFormFooter>\n <Button\n variant={\"secondary\"}\n text={t`Cancel`}\n onClick={() => {\n goToRoute(Routes.Teams.List);\n }}\n />\n {canModifyTeam && (\n <Button\n text={t`Save`}\n data-testid=\"admin.am.team.new.save\"\n onClick={ev => {\n form.submit(ev);\n }}\n />\n )}\n </SimpleFormFooter>\n </SimpleForm>\n );\n }}\n </Form>\n );\n};\n\ninterface FormContentProps {\n systemTeam: boolean;\n pluginTeam: boolean;\n canModifyTeam: boolean;\n newEntry: boolean;\n}\n\nconst FormContent = (props: FormContentProps) => {\n const { newEntry, pluginTeam, systemTeam, canModifyTeam } = props;\n\n const form = useForm();\n const { generateSlug } = useGenerateSlug(form, \"name\", \"slug\");\n\n return (\n <Grid>\n <>\n {systemTeam && (\n <Grid.Column span={12}>\n <Alert type={\"info\"} title={\"Permissions are locked\"}>\n This is a protected system team and you can't modify its\n permissions.\n </Alert>\n </Grid.Column>\n )}\n {pluginTeam && (\n <Grid.Column span={12}>\n <Alert type={\"info\"} title={\"Important\"}>\n This team is registered via an extension, and cannot be modified.\n </Alert>\n </Grid.Column>\n )}\n </>\n <Grid.Column span={6}>\n <Bind name=\"name\" validators={validation.create(\"required,minLength:1\")}>\n <Input\n required\n onBlur={generateSlug}\n disabled={!canModifyTeam}\n label={t`Name`}\n data-testid=\"admin.am.team.new.name\"\n />\n </Bind>\n </Grid.Column>\n <Grid.Column span={6}>\n <Bind name=\"slug\" validators={validation.create(\"required,minLength:1\")}>\n <Input\n required\n disabled={!canModifyTeam || !newEntry}\n label={t`Slug`}\n data-testid=\"admin.am.team.new.slug\"\n />\n </Bind>\n </Grid.Column>\n <Grid.Column span={12}>\n <Bind\n name=\"description\"\n validators={validation.create(\"maxLength:500\")}\n defaultValue={\"\"}\n >\n <Textarea\n disabled={!canModifyTeam}\n label={t`Description`}\n rows={3}\n data-testid=\"admin.am.team.new.description\"\n />\n </Bind>\n </Grid.Column>\n <Grid.Column span={12}>\n <Bind name=\"roles\" validators={validation.create(\"required\")}>\n <RolesMultiAutocomplete\n disabled={!canModifyTeam}\n label={t`Roles`}\n data-testid=\"admin.am.team.new.roles\"\n />\n </Bind>\n </Grid.Column>\n </Grid>\n );\n};\n"],"names":["t","i18n","TeamsForm","newEntry","id","goToRoute","useRouter","showSnackbar","useSnackbar","getQuery","useQuery","READ_TEAM","data","error","Routes","create","createMutation","useMutation","CREATE_TEAM","LIST_TEAMS","update","updateMutation","UPDATE_TEAM","loading","item","onSubmit","useCallback","formData","isUpdate","operation","args","pick","response","team","get","systemTeam","pluginTeam","canModifyTeam","showEmptyView","isEmpty","EmptyView","SettingsIcon","Button","AddIcon","Form","form","SimpleForm","OverlayLoader","SimpleFormHeader","SimpleFormContent","FormContent","SimpleFormFooter","ev","props","useForm","generateSlug","useGenerateSlug","Grid","Alert","Bind","validation","Input","Textarea","RolesMultiAutocomplete"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Team } from "../../../types.js";
|
|
2
|
+
export interface ListTeamsResponse {
|
|
3
|
+
security: {
|
|
4
|
+
teams: {
|
|
5
|
+
data: Team[];
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare const LIST_TEAMS: import("graphql").DocumentNode;
|
|
10
|
+
export declare const READ_TEAM: import("graphql").DocumentNode;
|
|
11
|
+
export declare const CREATE_TEAM: import("graphql").DocumentNode;
|
|
12
|
+
export declare const UPDATE_TEAM: import("graphql").DocumentNode;
|
|
13
|
+
export declare const DELETE_TEAM: import("graphql").DocumentNode;
|