From 9c06bc9893558ce4d99589ed9e5a46e6fc32c611 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Fri, 3 May 2024 14:31:08 -0700 Subject: [PATCH] add team manager role --- .../teams/[teamId]/members/TeamMemberEditForm.tsx | 4 ++++ .../teams/[teamId]/members/TeamMembersPage.tsx | 6 ++++-- .../teams/[teamId]/members/TeamMembersTable.tsx | 1 + .../settings/teams/[teamId]/team/TeamDetails.tsx | 12 +++++++++--- src/components/messages.ts | 2 ++ src/components/metrics/PagesTable.tsx | 6 +++++- src/lib/constants.ts | 7 +++++++ src/pages/api/teams/[teamId]/users/[userId].ts | 2 +- src/pages/api/teams/[teamId]/users/index.ts | 2 +- 9 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/app/(main)/settings/teams/[teamId]/members/TeamMemberEditForm.tsx b/src/app/(main)/settings/teams/[teamId]/members/TeamMemberEditForm.tsx index 0c22ac76c5..4018398961 100644 --- a/src/app/(main)/settings/teams/[teamId]/members/TeamMemberEditForm.tsx +++ b/src/app/(main)/settings/teams/[teamId]/members/TeamMemberEditForm.tsx @@ -40,6 +40,9 @@ export function TeamMemberEditForm({ }; const renderValue = (value: string) => { + if (value === ROLES.teamManager) { + return formatMessage(labels.manager); + } if (value === ROLES.teamMember) { return formatMessage(labels.member); } @@ -58,6 +61,7 @@ export function TeamMemberEditForm({ minWidth: '250px', }} > + {formatMessage(labels.manager)} {formatMessage(labels.member)} {formatMessage(labels.viewOnly)} diff --git a/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx b/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx index 3c16682607..de0c4c0a2e 100644 --- a/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx +++ b/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx @@ -12,8 +12,10 @@ export function TeamMembersPage({ teamId }: { teamId: string }) { const { formatMessage, labels } = useMessages(); const canEdit = - team?.teamUser?.find(({ userId, role }) => role === ROLES.teamOwner && userId === user.id) && - user.role !== ROLES.viewOnly; + team?.teamUser?.find( + ({ userId, role }) => + (role === ROLES.teamOwner || role === ROLES.teamManager) && userId === user.id, + ) && user.role !== ROLES.viewOnly; return ( <> diff --git a/src/app/(main)/settings/teams/[teamId]/members/TeamMembersTable.tsx b/src/app/(main)/settings/teams/[teamId]/members/TeamMembersTable.tsx index e72973b495..7d1efbf2dd 100644 --- a/src/app/(main)/settings/teams/[teamId]/members/TeamMembersTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/members/TeamMembersTable.tsx @@ -19,6 +19,7 @@ export function TeamMembersTable({ const roles = { [ROLES.teamOwner]: formatMessage(labels.teamOwner), + [ROLES.teamManager]: formatMessage(labels.teamManager), [ROLES.teamMember]: formatMessage(labels.teamMember), [ROLES.teamViewOnly]: formatMessage(labels.viewOnly), }; diff --git a/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx b/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx index 9d8ea52970..0c5fe991ea 100644 --- a/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx +++ b/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx @@ -15,18 +15,24 @@ export function TeamDetails({ teamId }: { teamId: string }) { const { user } = useLogin(); const [tab, setTab] = useState('details'); - const canEdit = + const isTeamOwner = !!team?.teamUser?.find(({ userId, role }) => role === ROLES.teamOwner && userId === user.id) && user.role !== ROLES.viewOnly; + const canEdit = + !!team?.teamUser?.find( + ({ userId, role }) => + (role === ROLES.teamOwner || role === ROLES.teamManager) && userId === user.id, + ) && user.role !== ROLES.viewOnly; + return ( }> - {!canEdit && } + {!isTeamOwner && } setTab(value)} style={{ marginBottom: 30 }}> {formatMessage(labels.details)} - {canEdit && {formatMessage(labels.manage)}} + {isTeamOwner && {formatMessage(labels.manage)}} {tab === 'details' && } {tab === 'manage' && } diff --git a/src/components/messages.ts b/src/components/messages.ts index 79a6b92ca1..7a11aa8993 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -29,6 +29,7 @@ export const labels = defineMessages({ createdBy: { id: 'label.created-by', defaultMessage: 'Created By' }, edit: { id: 'label.edit', defaultMessage: 'Edit' }, name: { id: 'label.name', defaultMessage: 'Name' }, + manager: { id: 'label.manager', defaultMessage: 'Manager' }, member: { id: 'label.member', defaultMessage: 'Member' }, members: { id: 'label.members', defaultMessage: 'Members' }, accessCode: { id: 'label.access-code', defaultMessage: 'Access code' }, @@ -43,6 +44,7 @@ export const labels = defineMessages({ settings: { id: 'label.settings', defaultMessage: 'Settings' }, owner: { id: 'label.owner', defaultMessage: 'Owner' }, teamOwner: { id: 'label.team-owner', defaultMessage: 'Team owner' }, + teamManager: { id: 'label.team-manager', defaultMessage: 'Team manager' }, teamMember: { id: 'label.team-member', defaultMessage: 'Team member' }, teamViewOnly: { id: 'label.team-view-only', defaultMessage: 'Team view only' }, enableShareUrl: { id: 'label.enable-share-url', defaultMessage: 'Enable share URL' }, diff --git a/src/components/metrics/PagesTable.tsx b/src/components/metrics/PagesTable.tsx index 4bc5c46126..b0da808066 100644 --- a/src/components/metrics/PagesTable.tsx +++ b/src/components/metrics/PagesTable.tsx @@ -38,7 +38,11 @@ export function PagesTable({ allowFilter, domainName, ...props }: PagesTableProp id={view} value={x} label={!x && formatMessage(labels.none)} - externalUrl={`${domainName.startsWith('http') ? domainName : `https://${domainName}`}${x}`} + externalUrl={ + view === 'url' + ? `${domainName.startsWith('http') ? domainName : `https://${domainName}`}${x}` + : null + } /> ); }; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index ac9c2e8ddc..0b6f7d264f 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -132,6 +132,7 @@ export const ROLES = { user: 'user', viewOnly: 'view-only', teamOwner: 'team-owner', + teamManager: 'team-manager', teamMember: 'team-member', teamViewOnly: 'team-view-only', } as const; @@ -162,6 +163,12 @@ export const ROLE_PERMISSIONS = { PERMISSIONS.websiteUpdate, PERMISSIONS.websiteDelete, ], + [ROLES.teamManager]: [ + PERMISSIONS.teamUpdate, + PERMISSIONS.websiteCreate, + PERMISSIONS.websiteUpdate, + PERMISSIONS.websiteDelete, + ], [ROLES.teamMember]: [ PERMISSIONS.websiteCreate, PERMISSIONS.websiteUpdate, diff --git a/src/pages/api/teams/[teamId]/users/[userId].ts b/src/pages/api/teams/[teamId]/users/[userId].ts index 4b52fe3ee7..c1e80b1a38 100644 --- a/src/pages/api/teams/[teamId]/users/[userId].ts +++ b/src/pages/api/teams/[teamId]/users/[userId].ts @@ -23,7 +23,7 @@ const schema = { POST: yup.object().shape({ role: yup .string() - .matches(/team-member|team-view-only/i) + .matches(/team-member|team-view-only|team-manager/i) .required(), }), }; diff --git a/src/pages/api/teams/[teamId]/users/index.ts b/src/pages/api/teams/[teamId]/users/index.ts index ccbf423af1..f25b99dae5 100644 --- a/src/pages/api/teams/[teamId]/users/index.ts +++ b/src/pages/api/teams/[teamId]/users/index.ts @@ -25,7 +25,7 @@ const schema = { userId: yup.string().uuid().required(), role: yup .string() - .matches(/team-member|team-view-only/i) + .matches(/team-member|team-view-only|team-manager/i) .required(), }), };