Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…portal into ajy-UID2-4005-Change-several-user-routes-to-accept-participantId

# Conflicts:
#	src/web/components/TeamMember/TeamMember.tsx
  • Loading branch information
alex-yau-ttd committed Aug 28, 2024
2 parents 3aa430e + f837f4d commit 19d6656
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ describe('CstgAddDialog', () => {
);
await submitDialogDomains();

expect(screen.getByText('Please specify Root-Level Domains.')).toBeInTheDocument();
expect(screen.getByText('Please specify root-level domains.')).toBeInTheDocument();
});

it('should be able to click save if user types in correct single mobile app ID', async () => {
Expand Down Expand Up @@ -282,6 +282,6 @@ describe('CstgAddDialog', () => {
);
await submitDialogMobileAppIds();

expect(screen.getByText('Please specify Mobile App IDs.')).toBeInTheDocument();
expect(screen.getByText('Please specify mobile app IDs.')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
AddCstgValuesFormProps,
CstgValueType,
extractTopLevelDomain,
formatCstgValueType,
getUniqueCstgValues,
validateAppId,
} from './CstgHelper';
Expand Down Expand Up @@ -57,7 +58,7 @@ function CstgAddDialog({
deleteExistingList
);
if (newCstgValues.length === 0) {
handleError(`The ${cstgValueType}s entered already exist.`);
handleError(`The ${formatCstgValueType(cstgValueType)}s entered already exist.`);
} else if (cstgValueType === CstgValueType.Domain) {
newCstgValues.forEach((newDomain, index) => {
newCstgValues[index] = extractTopLevelDomain(newDomain);
Expand Down Expand Up @@ -109,12 +110,12 @@ function CstgAddDialog({
onClick={onClickCheckbox}
checked={deleteExistingList}
/>
<div className='checkbox-text'>{`Replace all existing ${cstgValueType}s with the new ones.`}</div>
<div className='checkbox-text'>{`Replace all existing ${formatCstgValueType(cstgValueType)}s with the new ones.`}</div>
</div>
<MultilineTextInput
inputName='cstgValues'
label={`${cstgValueType}s`}
rules={{ required: `Please specify ${cstgValueType}s.` }}
rules={{ required: `Please specify ${formatCstgValueType(cstgValueType)}s.` }}
className='cstg-add-input'
/>
<div className='form-footer'>
Expand Down
11 changes: 11 additions & 0 deletions src/web/components/ClientSideTokenGeneration/CstgHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ export enum CstgValueType {
MobileAppId = 'Mobile App ID',
}

export const formatCstgValueType = (valueType: CstgValueType) => {
switch (valueType) {
case CstgValueType.Domain:
return 'root-level domain';
case CstgValueType.MobileAppId:
return 'mobile app ID';
default:
return valueType;
}
};

export const extractTopLevelDomain = (domainName: string) => {
const topLevelDomain = parse(domainName).domain;
if (topLevelDomain && topLevelDomain !== domainName) {
Expand Down
19 changes: 12 additions & 7 deletions src/web/components/ClientSideTokenGeneration/CstgTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import { TableNoDataPlaceholder } from '../Core/Tables/TableNoDataPlaceholder';
import { TriStateCheckbox, TriStateCheckboxState } from '../Input/TriStateCheckbox';
import CstgAddDialog from './CstgAddDialog';
import CstgDeleteDialog from './CstgDeleteDialog';
import { CstgValueType, getPagedValues, UpdateCstgValuesResponse } from './CstgHelper';
import {
CstgValueType,
formatCstgValueType,
getPagedValues,
UpdateCstgValuesResponse,
} from './CstgHelper';
import { CstgItem } from './CstgItem';

import './CstgTable.scss';
Expand Down Expand Up @@ -229,7 +234,7 @@ export function CstgTable({
type='text'
className='cstg-values-search-bar'
onChange={handleSearchCstgValue}
placeholder={`Search ${cstgValueType}s`}
placeholder={`Search ${formatCstgValueType(cstgValueType)}s`}
value={searchText}
/>
<FontAwesomeIcon icon='search' className='cstg-values-search-bar-icon' />
Expand Down Expand Up @@ -273,9 +278,9 @@ export function CstgTable({
))}
</tbody>
</table>
{searchText && !searchedCstgValues.length && (
<TableNoDataPlaceholder title={`No ${cstgValueType}`}>
<span>{`There are no ${cstgValueType}s that match this search.`}</span>
{cstgValues.length !== 0 && searchText && !searchedCstgValues.length && (
<TableNoDataPlaceholder title={`No ${cstgValueType}s`}>
<span>{`There are no ${formatCstgValueType(cstgValueType)}s that match this search.`}</span>
</TableNoDataPlaceholder>
)}
{!!searchedCstgValues.length && (
Expand All @@ -288,8 +293,8 @@ export function CstgTable({
)}

{!cstgValues.length && (
<TableNoDataPlaceholder title={`No ${cstgValueType}`}>
<span>{`There are no ${cstgValueType}s`}</span>
<TableNoDataPlaceholder title={`No ${cstgValueType}s`}>
<span>{`There are no ${formatCstgValueType(cstgValueType)}s.`}</span>
</TableNoDataPlaceholder>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function AddParticipantDialog({
async (formData: AddParticipantForm) => {
const response = await onAddParticipant(formData);
if (response.status === 200) {
SuccessToast('Participant Added.');
SuccessToast('Participant added.');
}
onOpenChange();
},
Expand Down
35 changes: 13 additions & 22 deletions src/web/components/PortalHeader/PortalHeader.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
import { composeStories } from '@storybook/react';
import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';

import * as stories from './PortalHeader.stories';

const { ValidEmailAddress, InvalidEmailAddress, NoEmailAddress } = composeStories(stories);
const { InvalidEmailAddress, NoEmailAddress } = composeStories(stories);

test('when the drop is clicked, a gravatar is displayed', async () => {
const user = userEvent.setup();
render(<ValidEmailAddress />);
const button = screen.getByRole('button');
await user.click(button);
const menu = screen.getByRole('menu');
const avatar = within(menu).getByRole('img');
expect(avatar).toHaveAttribute('src', expect.stringContaining('//www.gravatar.com/avatar/'));
});

test('when an invalid email address is provided, a home link is still displayed', async () => {
render(<InvalidEmailAddress />);
const link = screen.getByRole('link');
expect(link).toHaveAttribute('href', expect.stringContaining('/home'));
});
describe('Portal Header tests', () => {
test('when an invalid email address is provided, a home link is still displayed', async () => {
render(<InvalidEmailAddress />);
const link = screen.getByRole('link');
expect(link).toHaveAttribute('href', expect.stringContaining('/home'));
});

test('when no email is provided, the dropdown text shows that there is no logged in user', async () => {
render(<NoEmailAddress />);
const button = screen.getByRole('button');
expect(button).toHaveTextContent('Not logged in');
test('when no email is provided, the dropdown text shows that there is no logged in user', async () => {
render(<NoEmailAddress />);
const button = screen.getByRole('button');
expect(button).toHaveTextContent('Not logged in');
});
});
13 changes: 1 addition & 12 deletions src/web/components/PortalHeader/PortalHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Avatar } from '@radix-ui/react-avatar';
import {
DropdownMenu,
DropdownMenuArrow,
Expand All @@ -9,7 +8,6 @@ import {
DropdownMenuTrigger,
} from '@radix-ui/react-dropdown-menu';
import * as Switch from '@radix-ui/react-switch';
import MD5 from 'crypto-js/md5';
import { useContext, useEffect, useState } from 'react';
import { Link, useParams } from 'react-router-dom';

Expand All @@ -36,7 +34,6 @@ export function PortalHeader({
}: Readonly<PortalHeaderProps>) {
const { participantId } = useParams();
const { LoggedInUser } = useContext(CurrentUserContext);
const emailMd5 = email ? MD5(email).toString() : null;
const routes = [ParticipantInformationRoute, TeamMembersRoute, EmailContactsRoute];

const [menuOpen, setMenuOpen] = useState(false);
Expand Down Expand Up @@ -71,16 +68,8 @@ export function PortalHeader({
</DropdownMenuTrigger>
<DropdownMenuContent className='profile-dropdown-content' align='end'>
<DropdownMenuArrow className='profile-dropdown-arrow' />
<div className='portal-avatar-container'>
<Avatar className='portal-avatar' asChild>
{!!email && (
<img src={`//www.gravatar.com/avatar/${emailMd5}.jpg`} alt='Profile avatar' />
)}
</Avatar>
</div>
{LoggedInUser?.user && (
<>
<DropdownMenuSeparator className='separator' />
{routes.map((route) => {
return (
<DropdownMenuItem
Expand Down Expand Up @@ -113,7 +102,7 @@ export function PortalHeader({

<DropdownMenuSeparator className='separator' />
<DropdownMenuItem className='dropdown-menu-item' onClick={logout}>
Log out
Log Out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
2 changes: 1 addition & 1 deletion src/web/components/TeamMember/TeamMember.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function TeamMember({
setInviteState(InviteState.inProgress);
try {
await resendInvite(person.id, participant!.id);
SuccessToast('Invitation sent');
SuccessToast('Invitation sent.');
setInviteState(InviteState.sent);
} catch (e) {
setErrorInfo(e as Error);
Expand Down
8 changes: 4 additions & 4 deletions src/web/screens/clientSideIntegration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function ClientSideIntegration() {
try {
await UpdateKeyPair({ name, subscriptionId, disabled }, participant!.id!);
reloader.revalidate();
SuccessToast('Key Pair updated.');
SuccessToast('Key pair updated.');
} catch (e: unknown) {
handleErrorToast(e);
}
Expand Down Expand Up @@ -105,7 +105,7 @@ function ClientSideIntegration() {
domains = invalidDomains;
} else {
reloader.revalidate();
SuccessToast(`Root-Level Domains ${action}.`);
SuccessToast(`Root-level domains ${action}.`);
}
const updatedDomainNamesResponse: UpdateCstgValuesResponse = {
cstgValues: sortStringsAlphabetically(domains),
Expand All @@ -120,7 +120,7 @@ function ClientSideIntegration() {
try {
const appIds = await UpdateAppIds(updatedAppIds, participant!.id);
reloader.revalidate();
SuccessToast(`Mobile App IDs ${action}.`);
SuccessToast(`Mobile app IDs ${action}.`);

const updatedAppIdsResponse: UpdateCstgValuesResponse = {
cstgValues: sortStringsAlphabetically(appIds),
Expand Down Expand Up @@ -200,7 +200,7 @@ function ClientSideIntegration() {
onAddCstgValues={onAddCstgValues}
onUpdateCstgValues={handleUpdateAppIds}
cstgValueType={CstgValueType.MobileAppId}
addInstructions='Please register the Android App ID, iOS/tvOS Bundle ID, and iOS App Store ID.'
addInstructions='Add any mobile app IDs that apply: Android App IDs and/or iOS/tvOS Bundle IDs with corresponding iOS App Store IDs.'
/>
</>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/web/screens/manageParticipants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function ManageParticipants() {
const p = await GetUsersDefaultParticipant();
setParticipant(p);
}
SuccessToast('Participant updated');
SuccessToast('Participant updated.');
reloader.revalidate();
};

Expand Down
26 changes: 17 additions & 9 deletions src/web/screens/sharingPermissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ function SharingPermissions() {
SuccessToast(
`${
selectedTypes.length === 1
? '1 Participant type'
: `${selectedTypes.length} Participant types`
} saved to your Sharing Permissions`
? '1 participant type'
: `${selectedTypes.length} participant types`
} saved to your sharing permissions.`
);
if (!participant?.completedRecommendations) {
const updatedParticipant = await CompleteRecommendations(participant!.id);
Expand All @@ -94,8 +94,8 @@ function SharingPermissions() {
await AddSharingParticipants(participant!.id, selectedSiteIds);
SuccessToast(
`${
selectedSiteIds.length === 1 ? '1 Participant' : `${selectedSiteIds.length} Participants`
} added to your Sharing Permissions`
selectedSiteIds.length === 1 ? '1 participant' : `${selectedSiteIds.length} participants`
} added to your sharing permissions.`
);
reloader.revalidate();
} catch (e) {
Expand All @@ -109,7 +109,7 @@ function SharingPermissions() {
SuccessToast(
`${siteIdsToDelete.length} sharing ${
siteIdsToDelete.length > 1 ? 'permissions' : 'permission'
} deleted`
} deleted.`
);
reloader.revalidate();
} catch (e) {
Expand Down Expand Up @@ -139,7 +139,16 @@ function SharingPermissions() {
<>
<p className='heading-details'>
Adding a sharing permission allows the participant you’re sharing with to
decrypt your UID2 tokens.
decrypt your UID2 tokens. For more information, see{' '}
<a
className='outside-link'
target='_blank'
href='https://unifiedid.com/docs/portal/sharing-permissions'
rel='noreferrer'
>
Sharing Permissions
</a>
.
<br />
<br />
Note: This only enables the sharing permission. No data is sent.
Expand All @@ -150,8 +159,7 @@ function SharingPermissions() {
<span>
As a publisher, you can share with others by granting permission on this
page. However, to allow others to share with you, you must ask your UID2
contact to get the correct permissions added to your account. Note: This
only enables the sharing permission. No data is sent.
contact to get the correct permissions added to your account.
</span>
</>
)}
Expand Down

0 comments on commit 19d6656

Please sign in to comment.