Skip to content

Commit

Permalink
🛂(frontend) viewers and editors can access share modal
Browse files Browse the repository at this point in the history
Viewers and editors can access the share modal
and see the list of members and their roles.
  • Loading branch information
AntoLC committed Oct 3, 2024
1 parent e642506 commit 5bc9d55
Show file tree
Hide file tree
Showing 16 changed files with 358 additions and 114 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to

- 💄(frontend) error alert closeable on editor #284
- ♻️(backend) Change email content #283
- 🛂(frontend) viewers and editors can access share modal #302

## Fixed

Expand Down
87 changes: 86 additions & 1 deletion src/frontend/apps/e2e/__tests__/app-impress/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,13 @@ export const goToGridDoc = async (
export const mockedDocument = async (page: Page, json: object) => {
await page.route('**/documents/**/', async (route) => {
const request = route.request();
if (request.method().includes('GET') && !request.url().includes('page=')) {
if (
request.method().includes('GET') &&
!request.url().includes('page=') &&
!request.url().includes('versions') &&
!request.url().includes('accesses') &&
!request.url().includes('invitations')
) {
await route.fulfill({
json: {
id: 'mocked-document-id',
Expand Down Expand Up @@ -168,3 +174,82 @@ export const mockedDocument = async (page: Page, json: object) => {
}
});
};

export const mockedInvitations = async (page: Page, json?: object) => {
await page.route('**/invitations/**/', async (route) => {
const request = route.request();
if (
request.method().includes('GET') &&
request.url().includes('invitations') &&
request.url().includes('page=')
) {
await route.fulfill({
json: {
count: 1,
next: null,
previous: null,
results: [
{
id: '120ec765-43af-4602-83eb-7f4e1224548a',
abilities: {
destroy: true,
update: true,
partial_update: true,
retrieve: true,
},
created_at: '2024-10-03T12:19:26.107687Z',
email: '[email protected]',
document: '4888c328-8406-4412-9b0b-c0ba5b9e5fb6',
role: 'editor',
issuer: '7380f42f-02eb-4ad5-b8f0-037a0e66066d',
is_expired: false,
...json,
},
],
},
});
} else {
await route.continue();
}
});
};

export const mockedAccesses = async (page: Page, json?: object) => {
await page.route('**/accesses/**/', async (route) => {
const request = route.request();
if (
request.method().includes('GET') &&
request.url().includes('accesses') &&
request.url().includes('page=')
) {
await route.fulfill({
json: {
count: 1,
next: null,
previous: null,
results: [
{
id: 'bc8bbbc5-a635-4f65-9817-fd1e9ec8ef87',
user: {
id: 'b4a21bb3-722e-426c-9f78-9d190eda641c',
email: '[email protected]',
},
team: '',
role: 'reader',
abilities: {
destroy: true,
update: true,
partial_update: true,
retrieve: true,
set_role_to: ['administrator', 'editor'],
},
...json,
},
],
},
});
} else {
await route.continue();
}
});
};
140 changes: 132 additions & 8 deletions src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { expect, test } from '@playwright/test';

import { createDoc, goToGridDoc, mockedDocument } from './common';
import {
createDoc,
goToGridDoc,
mockedAccesses,
mockedDocument,
mockedInvitations,
} from './common';

test.beforeEach(async ({ page }) => {
await page.goto('/');
Expand Down Expand Up @@ -182,20 +188,55 @@ test.describe('Doc Header', () => {
},
});

await mockedInvitations(page);
await mockedAccesses(page);

await goToGridDoc(page);

await expect(
page.locator('h2').getByText('Mocked document'),
).toHaveAttribute('contenteditable');

await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();

await page.getByLabel('Open the document options').click();

await expect(page.getByRole('button', { name: 'Export' })).toBeVisible();
await expect(
page.getByRole('button', { name: 'Delete document' }),
).toBeHidden();

// Click somewhere else to close the options
await page.click('body', { position: { x: 0, y: 0 } });

await page.getByRole('button', { name: 'Share' }).click();

const shareModal = page.getByLabel('Share modal');

await expect(shareModal.getByLabel('Doc private')).toBeEnabled();
await expect(shareModal.getByText('Search by email')).toBeVisible();

const invitationCard = shareModal.getByLabel('List invitation card');
await expect(
invitationCard.getByText('[email protected]'),
).toBeVisible();
await expect(
invitationCard.getByRole('combobox', { name: 'Role' }),
).toBeEnabled();
await expect(
invitationCard.getByRole('button', {
name: 'delete',
}),
).toBeEnabled();

const memberCard = shareModal.getByLabel('List members card');
await expect(memberCard.getByText('[email protected]')).toBeVisible();
await expect(
memberCard.getByRole('combobox', { name: 'Role' }),
).toBeEnabled();
await expect(
memberCard.getByRole('button', {
name: 'delete',
}),
).toBeEnabled();
});

test('it checks the options available if editor', async ({ page }) => {
Expand All @@ -213,20 +254,62 @@ test.describe('Doc Header', () => {
},
});

await mockedInvitations(page, {
abilities: {
destroy: false,
update: false,
partial_update: false,
retrieve: true,
},
});
await mockedAccesses(page);

await goToGridDoc(page);

await expect(
page.locator('h2').getByText('Mocked document'),
).toHaveAttribute('contenteditable');

await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();

await page.getByLabel('Open the document options').click();

await expect(page.getByRole('button', { name: 'Export' })).toBeVisible();
await expect(
page.getByRole('button', { name: 'Delete document' }),
).toBeHidden();

// Click somewhere else to close the options
await page.click('body', { position: { x: 0, y: 0 } });

await page.getByRole('button', { name: 'Share' }).click();

const shareModal = page.getByLabel('Share modal');

await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
await expect(shareModal.getByText('Search by email')).toBeHidden();

const invitationCard = shareModal.getByLabel('List invitation card');
await expect(
invitationCard.getByText('[email protected]'),
).toBeVisible();
await expect(
invitationCard.getByRole('combobox', { name: 'Role' }),
).toHaveAttribute('disabled');
await expect(
invitationCard.getByRole('button', {
name: 'delete',
}),
).toBeHidden();

const memberCard = shareModal.getByLabel('List members card');
await expect(memberCard.getByText('[email protected]')).toBeVisible();
await expect(
memberCard.getByRole('combobox', { name: 'Role' }),
).toHaveAttribute('disabled');
await expect(
memberCard.getByRole('button', {
name: 'delete',
}),
).toBeHidden();
});

test('it checks the options available if reader', async ({ page }) => {
Expand All @@ -244,20 +327,61 @@ test.describe('Doc Header', () => {
},
});

await mockedInvitations(page, {
abilities: {
destroy: false,
update: false,
partial_update: false,
retrieve: true,
},
});
await mockedAccesses(page);

await goToGridDoc(page);

await expect(
page.locator('h2').getByText('Mocked document'),
).not.toHaveAttribute('contenteditable');

await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();

await page.getByLabel('Open the document options').click();

await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();
await expect(page.getByRole('button', { name: 'Export' })).toBeVisible();
await expect(
page.getByRole('button', { name: 'Delete document' }),
).toBeHidden();

// Click somewhere else to close the options
await page.click('body', { position: { x: 0, y: 0 } });

await page.getByRole('button', { name: 'Share' }).click();

const shareModal = page.getByLabel('Share modal');

await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
await expect(shareModal.getByText('Search by email')).toBeHidden();

const invitationCard = shareModal.getByLabel('List invitation card');
await expect(
invitationCard.getByText('[email protected]'),
).toBeVisible();
await expect(
invitationCard.getByRole('combobox', { name: 'Role' }),
).toHaveAttribute('disabled');
await expect(
invitationCard.getByRole('button', {
name: 'delete',
}),
).toBeHidden();

const memberCard = shareModal.getByLabel('List members card');
await expect(memberCard.getByText('[email protected]')).toBeVisible();
await expect(
memberCard.getByRole('combobox', { name: 'Role' }),
).toHaveAttribute('disabled');
await expect(
memberCard.getByRole('button', {
name: 'delete',
}),
).toBeHidden();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,17 @@ test.describe('Document list members', () => {
await page.getByRole('option', { name: 'Administrator' }).click();
await expect(page.getByText('The role has been updated')).toBeVisible();

const shareModal = page.getByLabel('Share modal');

// Admin still have the right to share
await expect(page.locator('h3').getByText('Share')).toBeVisible();
await expect(shareModal.getByLabel('Doc private')).toBeEnabled();

await SelectRoleCurrentUser.click();
await page.getByRole('option', { name: 'Reader' }).click();
await expect(page.getByText('The role has been updated')).toBeVisible();

// Reader does not have the right to share
await expect(page.locator('h3').getByText('Share')).toBeHidden();
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
});

test('it checks the delete members', async ({ page, browserName }) => {
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/apps/impress/src/components/Box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface BoxProps {
$padding?: MarginPadding;
$position?: CSSProperties['position'];
$radius?: CSSProperties['borderRadius'];
$shrink?: CSSProperties['flexShrink'];
$transition?: CSSProperties['transition'];
$width?: CSSProperties['width'];
$wrap?: CSSProperties['flexWrap'];
Expand Down Expand Up @@ -68,6 +69,7 @@ export const Box = styled('div')<BoxProps>`
${({ $padding }) => $padding && stylesPadding($padding)}
${({ $position }) => $position && `position: ${$position};`}
${({ $radius }) => $radius && `border-radius: ${$radius};`}
${({ $shrink }) => $shrink && `flex-shrink: ${$shrink};`}
${({ $transition }) => $transition && `transition: ${$transition};`}
${({ $width }) => $width && `width: ${$width};`}
${({ $wrap }) => $wrap && `flex-wrap: ${$wrap};`}
Expand Down
14 changes: 14 additions & 0 deletions src/frontend/apps/impress/src/cunningham/cunningham-style.css
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ input:-webkit-autofill:focus {
border-color: var(--c--components--forms-select--border-color-disabled-hover);
}

.c__select--disabled .c__select__wrapper label,
.c__select--disabled .c__select__wrapper input,
.c__select--disabled .c__select__wrapper {
cursor: not-allowed;
}

.c__select__menu__item {
transition: all var(--c--theme--transitions--duration)
var(--c--theme--transitions--ease-out);
Expand Down Expand Up @@ -313,6 +319,14 @@ input:-webkit-autofill:focus {
font-size: var(--c--components--forms-checkbox--text--size);
}

.c__checkbox.c__checkbox--disabled .c__field__text {
color: var(--c--theme--colors--greyscale-600);
}

.c__switch.c__checkbox--disabled .c__switch__rail {
cursor: not-allowed;
}

/**
* Button
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
$align="center"
$gap="1rem"
>
{doc.abilities.manage_accesses && (
<Button
onClick={() => {
setIsModalShareOpen(true);
}}
>
{t('Share')}
</Button>
)}
<Button
onClick={() => {
setIsModalShareOpen(true);
}}
>
{t('Share')}
</Button>
<DropButton
button={
<IconOptions
Expand Down
Loading

0 comments on commit 5bc9d55

Please sign in to comment.