diff --git a/src/components/CancelTask/index.tsx b/src/components/CancelTask/index.tsx index 94dc1b75..383a8a10 100644 --- a/src/components/CancelTask/index.tsx +++ b/src/components/CancelTask/index.tsx @@ -45,7 +45,7 @@ export const CancelTaskButton: FC = ({ beforeText, afterText, }) => { - const [api, contextHolder] = notification.useNotification(); + const [api, contextHolder] = notification.useNotification({ maxCount: 1 }); const openNotificationWithIcon = (errorMessage: string) => { api['error']({ diff --git a/src/components/Organizations/AddUserToGroup/index.js b/src/components/Organizations/AddUserToGroup/index.js index 9181a8c1..75c84373 100644 --- a/src/components/Organizations/AddUserToGroup/index.js +++ b/src/components/Organizations/AddUserToGroup/index.js @@ -10,7 +10,7 @@ import gql from 'graphql-tag'; import { Footer } from '../SharedStyles'; import { NewMember, RoleSelect } from './Styles'; -const ADD_GROUP_MEMBER_MUTATION = gql` +export const ADD_GROUP_MEMBER_MUTATION = gql` mutation addUserToGroup($email: String!, $group: String!, $role: GroupRole!) { addUserToGroup(input: { user: { email: $email }, group: { name: $group }, role: $role }) { name @@ -18,7 +18,7 @@ const ADD_GROUP_MEMBER_MUTATION = gql` } `; -let options = [ +export const options = [ { label: 'Guest', value: 'GUEST', @@ -69,6 +69,7 @@ export const AddUserToGroup = ({ }); } return ( +

{userAlreadyExists ? 'Update User' : 'Add User'}

diff --git a/src/components/Organizations/AddUserToOrganization/index.js b/src/components/Organizations/AddUserToOrganization/index.js index ee8a85c4..be5a6bc3 100644 --- a/src/components/Organizations/AddUserToOrganization/index.js +++ b/src/components/Organizations/AddUserToOrganization/index.js @@ -8,9 +8,9 @@ import withLogic from 'components/Organizations/AddUserToOrganization/logic'; import gql from 'graphql-tag'; import { Footer } from '../SharedStyles'; -import { NewUser, OrganizationSelect } from './Styles'; +import { NewUser } from './Styles'; -const ADD_USER_MUTATION = gql` +export const ADD_USER_MUTATION = gql` mutation AddUserToOrganization($email: String!, $organization: Int!, $owner: Boolean) { addUserToOrganization(input: { user: { email: $email }, organization: $organization, owner: $owner }) { id @@ -19,7 +19,7 @@ const ADD_USER_MUTATION = gql` `; /** - * Confirms the deletion of the specified name and type. + * Adds/edits user to an organization */ export const AddUserToOrganization = ({ organization, diff --git a/src/components/Organizations/GroupMembers/index.js b/src/components/Organizations/GroupMembers/index.js index 92a5472f..e3eaedda 100644 --- a/src/components/Organizations/GroupMembers/index.js +++ b/src/components/Organizations/GroupMembers/index.js @@ -4,19 +4,21 @@ import ReactSelect from 'react-select'; import Link from 'next/link'; -import { DisconnectOutlined, EyeOutlined } from '@ant-design/icons'; +import { DisconnectOutlined, EditOutlined, EyeOutlined } from '@ant-design/icons'; +import { useMutation } from '@apollo/react-hooks'; import Button from 'components/Button'; import Modal from 'components/Modal'; import RemoveUserConfirm from 'components/Organizations/RemoveUserConfirm'; import ProjectGroupLink from 'components/link/Organizations/ProjectGroup'; import gql from 'graphql-tag'; -import AddUserToGroup from '../AddUserToGroup'; +import AddUserToGroup, { ADD_GROUP_MEMBER_MUTATION, options } from '../AddUserToGroup'; import { RoleSelect } from '../AddUserToGroup/Styles'; import PaginatedTable from '../PaginatedTable/PaginatedTable'; import { AddButtonContent, Footer, + ModalChildren, RemoveModalHeader, RemoveModalParagraph, TableActions, @@ -77,6 +79,19 @@ const GroupMembers = ({ const [deleteUserModalOpen, setDeleteUserModalOpen] = useState(false); const [addProjectModalOpen, setAddProjectModalOpen] = useState(false); + const [updatePending, setUpdatePending] = useState(false); + + const [modalState, setModalState] = useState({ + open: false, + current: '', + }); + + const [updateUser] = useMutation(ADD_GROUP_MEMBER_MUTATION); + + const closeModal = () => { + setModalState({ open: false, current: '' }); + }; + const closeAddProjectModal = () => { setSelectedProject(''); setAddProjectModalOpen(false); @@ -96,7 +111,7 @@ const GroupMembers = ({ if (isDefaultUser) return
; - return firstName ?
{firstName}
: <> - ; + return firstName ?
{firstName}
: <> - ; }, }, { @@ -144,6 +159,21 @@ const GroupMembers = ({ const linkData = getLinkData(user.email, organizationId, organizationName); return ( + + setModalState({ + open: true, + current: { + email: user.email, + role: user.role, + }, + }) + } + > + + + @@ -403,6 +433,74 @@ const GroupMembers = ({ + + + +
+ +
+ +
+ +
+ + + +
+
); }; diff --git a/src/components/Organizations/Manage/index.js b/src/components/Organizations/Manage/index.js index 4462ed18..cf23bcf9 100644 --- a/src/components/Organizations/Manage/index.js +++ b/src/components/Organizations/Manage/index.js @@ -3,14 +3,15 @@ import { Mutation } from 'react-apollo'; import Link from 'next/link'; -import { DeleteOutlined } from '@ant-design/icons'; +import { DeleteOutlined, EditOutlined } from '@ant-design/icons'; import Button from 'components/Button'; import Modal from 'components/Modal'; import withLogic from 'components/Organizations/Users/logic'; import gql from 'graphql-tag'; import useSortableData from '../../../lib/withSortedItems'; -import AddUserToOrganization from '../AddUserToOrganization'; +import AddUserToOrganization, { ADD_USER_MUTATION } from '../AddUserToOrganization'; +import { NewUser } from '../AddUserToOrganization/Styles'; import PaginatedTable from '../PaginatedTable/PaginatedTable'; import { AddButtonContent, Footer, RemoveModalHeader, RemoveModalParagraph, TableActions, Tag } from '../SharedStyles'; import { StyledUsers } from '../Users/Styles'; @@ -41,12 +42,19 @@ const Manage = ({ users = [], organization, organizationId, organizationName, re const [deleteUserModalOpen, setDeleteUserModalOpen] = useState(false); const [dynamicUsers, setDynamicUsers] = useState(users); + const [editModalOpen, setEditModalOpen] = useState(false); + const [selectedUserOwner, setSelectedUserOwner] = useState(false); const closeUserModal = () => { setSelectedUser(''); setUserModalOpen(false); }; + const closeEditModal = () => { + setSelectedUser(''); + setEditModalOpen(false); + }; + useEffect(() => { setDynamicUsers(users); }, [users]); @@ -120,6 +128,79 @@ const Manage = ({ users = [], organization, organizationId, organizationName, re render: ({ ...user }) => { return ( + { + setSelectedUser(user?.id); + setEditModalOpen(true); + setSelectedUserOwner(user.owner); + }} + > + + + + + console.error(err)}> + {(addUser, { called, error, data }) => { + if (error) { + return
{error.message}
; + } + if (data) { + setSelectedUser(''); + refetch().then(closeEditModal); + } + return ( + +

Update user

+
+ +
+ + +
+
+ + +
+
+
+ ); + }} +
+
+ { @@ -127,6 +208,7 @@ const Manage = ({ users = [], organization, organizationId, organizationName, re setDeleteUserModalOpen(true); }} /> + Are you sure? diff --git a/src/components/Organizations/Notifications/AddNotifications.tsx b/src/components/Organizations/Notifications/AddNotifications.tsx index c8590136..7c5095d8 100644 --- a/src/components/Organizations/Notifications/AddNotifications.tsx +++ b/src/components/Organizations/Notifications/AddNotifications.tsx @@ -95,6 +95,7 @@ const AddNotification: FC = ({ modalOpen, organizationId, onNotificationA const [addTeams] = useMutation(ADD_MICROSOFTTEAMS_NOTIFICATION); const [addWebhook] = useMutation(ADD_WEBHOOK_NOTIFICATION); + const [loading, setLoading] = useState(false); const resetState = () => { setNotificationName(''); setEmail(''); @@ -278,16 +279,23 @@ const AddNotification: FC = ({ modalOpen, organizationId, onNotificationA action={() => { const cb = getAction(); - cb && + if (cb) { + setLoading(true); cb() - .then(onNotificationAdded) + .then(() => { + void onNotificationAdded(); + }) .then(() => { resetState(); closeModal(); }) - .catch(err => console.error(err)); + .catch(err => console.error(err)) + .finally(() => setLoading(false)); + } }} variant="primary" + loading={loading} + disabled={loading} > Add diff --git a/src/components/Organizations/Organization/index.js b/src/components/Organizations/Organization/index.js index 057576e4..82f8646f 100644 --- a/src/components/Organizations/Organization/index.js +++ b/src/components/Organizations/Organization/index.js @@ -11,7 +11,7 @@ import gql from 'graphql-tag'; import OrgHeader from '../Orgheader'; import { Footer, ModalChildren, Tag } from '../SharedStyles'; -import { LinkBtn, StyledOrganization, StyledOverview, ManageBtn } from './Styles'; +import { LinkBtn, ManageBtn, StyledOrganization, StyledOverview } from './Styles'; const UPDATE_ORGANIZATION_FRIENDLY_NAME = gql` mutation updateOrganizationFriendlyName($id: Int!, $friendlyName: String!) { @@ -53,7 +53,7 @@ const Organization = ({ organization, refetch }) => { const [descModalOpen, setDescModalOpen] = useState(false); const [description, setDescription] = useState(''); - const quotaDisplay = (quota, quotaNumber, quotaLimit) => { + const quotaDisplay = (quota, quotaNumber, quotaLimit, showLink = true) => { const pluralName = quota + 's'; const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1); @@ -69,14 +69,16 @@ const Organization = ({ organization, refetch }) => {
{pluralName.toUpperCase()} - {capitalize(quota)} quota: {quotaNumber} of {quotaLimit} + {capitalize(quota)} quota: {quotaNumber} of {quotaLimit == '-1' ? 'unlimited' : quotaLimit} - - - {capitalize(pluralName)} - - + {showLink && ( + + + {capitalize(pluralName)} + + + )}
); }; @@ -120,7 +122,7 @@ const Organization = ({ organization, refetch }) => {
console.error(e)}> - {(updateOrgFriendlyName, { error, data }) => { + {(updateOrgFriendlyName, { error, data, called }) => { if (error) { return
{error.message}
; } @@ -133,6 +135,8 @@ const Organization = ({ organization, refetch }) => { return (