From 432151163189d2ee7529e39a72514b4d489591a1 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 6 Sep 2024 18:03:19 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=9A(frontend)=20change=20visibility=20?= =?UTF-8?q?in=20share=20modal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We stop to propose to make the document public from the doc creation modal. We now propose to change the visibility of the document from the share modal. --- CHANGELOG.md | 4 + .../apps/e2e/__tests__/app-impress/common.ts | 13 +++- .../__tests__/app-impress/doc-create.spec.ts | 18 +---- .../__tests__/app-impress/doc-header.spec.ts | 17 +---- .../__tests__/app-impress/doc-routing.spec.ts | 32 +------- .../app-impress/doc-visibility.spec.ts | 74 +++++++++++++++++++ src/frontend/apps/impress/cunningham.ts | 4 + .../src/cunningham/cunningham-style.css | 5 ++ .../src/cunningham/cunningham-tokens.css | 4 + .../src/cunningham/cunningham-tokens.ts | 4 + .../docs/doc-management/api/useCreateDoc.tsx | 8 +- .../components/DocVisibility.tsx | 65 ++++++++++++++++ .../components/ModalCreateUpdateDoc.tsx | 21 +----- .../doc-management/components/ModalShare.tsx | 3 + 14 files changed, 184 insertions(+), 88 deletions(-) create mode 100644 src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts create mode 100644 src/frontend/apps/impress/src/features/docs/doc-management/components/DocVisibility.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d88eab1..3c853688 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to - 🛂(frontend) access public docs without being logged #235 +## Changed + +- 🚚(frontend) change visibility in share modal #235 + ## [1.3.0] - 2024-09-05 diff --git a/src/frontend/apps/e2e/__tests__/app-impress/common.ts b/src/frontend/apps/e2e/__tests__/app-impress/common.ts index 84ce892f..1c6a7005 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/common.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/common.ts @@ -55,14 +55,19 @@ export const createDoc = async ( }) .fill(randomDocs[i]); - if (isPublic) { - await page.getByText('Is it public ?').click(); - } - await expect(buttonCreate).toBeEnabled(); await buttonCreate.click(); await expect(page.locator('h2').getByText(randomDocs[i])).toBeVisible(); + + if (isPublic) { + await page.getByRole('button', { name: 'Share' }).click(); + await page.getByText('Doc private').click(); + + await page.locator('.c__modal__backdrop').click({ + position: { x: 0, y: 0 }, + }); + } } return randomDocs; diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-create.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-create.spec.ts index c478484b..6fab7777 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-create.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-create.spec.ts @@ -21,8 +21,6 @@ test.describe('Doc Create', () => { ).toBeVisible(); await expect(card.getByLabel('Document name')).toBeVisible(); - await expect(card.getByText('Is it public ?')).toBeVisible(); - await expect( card.getByRole('button', { name: 'Create the document', @@ -46,14 +44,8 @@ test.describe('Doc Create', () => { await expect(buttonCreateHomepage).toBeVisible(); }); - test('create a new public doc', async ({ page, browserName }) => { - const [docTitle] = await createDoc( - page, - 'My new doc', - browserName, - 1, - true, - ); + test('it creates a doc', async ({ page, browserName }) => { + const [docTitle] = await createDoc(page, 'My new doc', browserName, 1); expect(await page.locator('title').textContent()).toMatch( /My new doc - Docs/, @@ -69,11 +61,5 @@ test.describe('Doc Create', () => { await expect(datagrid.getByLabel('Loading data')).toBeHidden(); await expect(datagrid.getByText(docTitle)).toBeVisible(); - - const row = datagrid.getByRole('row').filter({ - hasText: docTitle, - }); - - await expect(row.getByRole('cell').nth(0)).toHaveText('Public'); }); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts index 839d6cd1..e19403bb 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts @@ -65,13 +65,7 @@ test.describe('Doc Header', () => { }); test('it updates the doc', async ({ page, browserName }) => { - const [randomDoc] = await createDoc( - page, - 'doc-update', - browserName, - 1, - true, - ); + const [randomDoc] = await createDoc(page, 'doc-update', browserName, 1); await expect(page.locator('h2').getByText(randomDoc)).toBeVisible(); await page.getByLabel('Open the document options').click(); @@ -85,12 +79,7 @@ test.describe('Doc Header', () => { page.locator('h2').getByText(`Update document "${randomDoc}"`), ).toBeVisible(); - await expect( - page.getByRole('checkbox', { name: 'Is it public ?' }), - ).toBeChecked(); - await page.getByText('Document name').fill(`${randomDoc}-updated`); - await page.getByText('Is it public ?').click(); await page .getByRole('button', { @@ -116,8 +105,8 @@ test.describe('Doc Header', () => { .click(); await expect( - page.getByRole('checkbox', { name: 'Is it public ?' }), - ).not.toBeChecked(); + page.getByRole('textbox', { name: 'Document name' }), + ).toHaveValue(`${randomDoc}-updated`); }); test('it deletes the doc', async ({ page, browserName }) => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-routing.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-routing.spec.ts index e7d2f51d..18599cec 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-routing.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-routing.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from '@playwright/test'; -import { createDoc, keyCloakSignIn } from './common'; +import { keyCloakSignIn } from './common'; test.describe('Doc Routing', () => { test.beforeEach(async ({ page }) => { @@ -56,34 +56,4 @@ test.describe('Doc Routing: Not loggued', () => { }), ).toBeVisible(); }); - - test('A public doc is accessible even when not authentified.', async ({ - page, - browserName, - }) => { - await page.goto('/'); - await keyCloakSignIn(page, browserName); - - const [docTitle] = await createDoc( - page, - 'My new doc', - browserName, - 1, - true, - ); - - const urlDoc = page.url(); - - await page - .getByRole('button', { - name: 'Logout', - }) - .click(); - - await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible(); - - await page.goto(urlDoc); - - await expect(page.locator('h2').getByText(docTitle)).toBeVisible(); - }); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts new file mode 100644 index 00000000..b0fc109f --- /dev/null +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts @@ -0,0 +1,74 @@ +import { expect, test } from '@playwright/test'; + +import { createDoc, keyCloakSignIn } from './common'; + +test.describe('Doc Visibility', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/'); + }); + + test('Make a public doc', async ({ page, browserName }) => { + const [docTitle] = await createDoc( + page, + 'My new doc', + browserName, + 1, + true, + ); + + const header = page.locator('header').first(); + await header.locator('h2').getByText('Docs').click(); + + const datagrid = page + .getByLabel('Datagrid of the documents page 1') + .getByRole('table'); + + await expect(datagrid.getByLabel('Loading data')).toBeHidden(); + + await expect(datagrid.getByText(docTitle)).toBeVisible(); + + const row = datagrid.getByRole('row').filter({ + hasText: docTitle, + }); + + await expect(row.getByRole('cell').nth(0)).toHaveText('Public'); + }); +}); + +test.describe('Doc Visibility: Not loggued', () => { + test.use({ storageState: { cookies: [], origins: [] } }); + + test('A public doc is accessible even when not authentified.', async ({ + page, + browserName, + }) => { + await page.goto('/'); + await keyCloakSignIn(page, browserName); + + const [docTitle] = await createDoc( + page, + 'My new doc', + browserName, + 1, + true, + ); + + await expect( + page.getByText('The document visiblitity has been updated.'), + ).toBeVisible(); + + const urlDoc = page.url(); + + await page + .getByRole('button', { + name: 'Logout', + }) + .click(); + + await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible(); + + await page.goto(urlDoc); + + await expect(page.locator('h2').getByText(docTitle)).toBeVisible(); + }); +}); diff --git a/src/frontend/apps/impress/cunningham.ts b/src/frontend/apps/impress/cunningham.ts index e632565d..6b158a6d 100644 --- a/src/frontend/apps/impress/cunningham.ts +++ b/src/frontend/apps/impress/cunningham.ts @@ -340,6 +340,10 @@ const config = { 'forms-checkbox': { 'border-radius': '0', color: 'var(--c--theme--colors--primary-text)', + text: { + color: 'var(--c--theme--colors--greyscale-text)', + size: 'var(--c--theme--font--sizes--t)', + }, }, 'forms-datepicker': { 'border-radius': '0', diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-style.css b/src/frontend/apps/impress/src/cunningham/cunningham-style.css index a14505d3..fd12415f 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-style.css +++ b/src/frontend/apps/impress/src/cunningham/cunningham-style.css @@ -308,6 +308,11 @@ input:-webkit-autofill:focus { transition: all 0.8s ease-in-out; } +.c__checkbox .c__field__text { + color: var(--c--components--forms-checkbox--text--color); + font-size: var(--c--components--forms-checkbox--text--size); +} + /** * Button */ diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css index 986f476a..45dfd511 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css +++ b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css @@ -463,6 +463,10 @@ ); --c--components--forms-checkbox--border-radius: 0; --c--components--forms-checkbox--color: var(--c--theme--colors--primary-text); + --c--components--forms-checkbox--text--color: var( + --c--theme--colors--greyscale-text + ); + --c--components--forms-checkbox--text--size: var(--c--theme--font--sizes--t); --c--components--forms-datepicker--border-radius: 0; --c--components--forms-fileuploader--border-radius: 0; --c--components--forms-field--color: var(--c--theme--colors--primary-text); diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts index f501547b..ae7fd4f5 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts +++ b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts @@ -469,6 +469,10 @@ export const tokens = { 'forms-checkbox': { 'border-radius': '0', color: 'var(--c--theme--colors--primary-text)', + text: { + color: 'var(--c--theme--colors--greyscale-text)', + size: 'var(--c--theme--font--sizes--t)', + }, }, 'forms-datepicker': { 'border-radius': '0' }, 'forms-fileuploader': { 'border-radius': '0' }, diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/api/useCreateDoc.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/api/useCreateDoc.tsx index 0e52174d..78abddbe 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/api/useCreateDoc.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/api/useCreateDoc.tsx @@ -6,17 +6,13 @@ import { Doc } from '../types'; import { KEY_LIST_DOC } from './useDocs'; -export type CreateDocParam = Pick; +export type CreateDocParam = Pick; -export const createDoc = async ({ - title, - is_public, -}: CreateDocParam): Promise => { +export const createDoc = async ({ title }: CreateDocParam): Promise => { const response = await fetchAPI(`documents/`, { method: 'POST', body: JSON.stringify({ title, - is_public, }), }); diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/components/DocVisibility.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/components/DocVisibility.tsx new file mode 100644 index 00000000..043dbc3e --- /dev/null +++ b/src/frontend/apps/impress/src/features/docs/doc-management/components/DocVisibility.tsx @@ -0,0 +1,65 @@ +import { + Switch, + VariantType, + useToastProvider, +} from '@openfun/cunningham-react'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { Box, Card, IconBG } from '@/components'; + +import { KEY_DOC, KEY_LIST_DOC, useUpdateDoc } from '../api'; +import { Doc } from '../types'; + +interface DocVisibilityProps { + doc: Doc; +} + +export const DocVisibility = ({ doc }: DocVisibilityProps) => { + const { t } = useTranslation(); + const [docPublic, setDocPublic] = useState(doc.is_public); + const { toast } = useToastProvider(); + const api = useUpdateDoc({ + onSuccess: () => { + toast( + t('The document visiblitity has been updated.'), + VariantType.SUCCESS, + { + duration: 4000, + }, + ); + }, + listInvalideQueries: [KEY_LIST_DOC], + }); + + return ( + + + + { + api.mutate({ + id: doc.id, + is_public: !docPublic, + }); + setDocPublic(!docPublic); + }} + text={t( + docPublic + ? 'Anyone on the internet with the link can view' + : 'Only for people with access', + )} + /> + + + ); +}; diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalCreateUpdateDoc.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalCreateUpdateDoc.tsx index e08d8b46..9bf692a8 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalCreateUpdateDoc.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalCreateUpdateDoc.tsx @@ -3,7 +3,6 @@ import { Button, Modal, ModalSize, - Switch, VariantType, useToastProvider, } from '@openfun/cunningham-react'; @@ -44,9 +43,8 @@ export const ModalCreateDoc = ({ onClose }: ModalCreateDocProps) => { onClose, isPublic: false, titleModal: t('Create a new document'), - validate: (title, is_public) => + validate: (title) => api.mutate({ - is_public, title, }), ...api, @@ -85,9 +83,8 @@ export const ModalUpdateDoc = ({ onClose, doc }: ModalUpdateDocProps) => { titleModal: t('Update document "{{documentTitle}}"', { documentTitle: doc.title, }), - validate: (title, is_public) => + validate: (title) => api.mutate({ - is_public, title, id: doc.id, }), @@ -99,10 +96,9 @@ export const ModalUpdateDoc = ({ onClose, doc }: ModalUpdateDocProps) => { type ModalDoc = { buttonText: string; - isPublic: boolean; onClose: () => void; titleModal: string; - validate: (title: string, is_public: boolean) => void; + validate: (title: string) => void; initialTitle?: string; infoText?: string; } & UseMutationResult, T, unknown>; @@ -111,7 +107,6 @@ const ModalDoc = ({ buttonText, infoText, initialTitle, - isPublic, onClose, titleModal, validate, @@ -121,8 +116,6 @@ const ModalDoc = ({ const { t } = useTranslation(); const [title, setTitle] = useState(initialTitle || ''); - const [docPublic, setDocPublic] = useState(isPublic); - return ( ({ aria-label={buttonText} color="primary" fullWidth - onClick={() => validate(title, docPublic)} + onClick={() => validate(title)} > {buttonText} @@ -177,12 +170,6 @@ const ModalDoc = ({ setDocName: setTitle, }} /> - setDocPublic(!docPublic)} - /> diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx index 25f68c83..0f11a6a9 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/components/ModalShare.tsx @@ -10,6 +10,8 @@ import { MemberList } from '@/features/docs/members/members-list'; import { Doc } from '../types'; import { currentDocRole } from '../utils'; +import { DocVisibility } from './DocVisibility'; + const ModalShareStyle = createGlobalStyle` & .c__modal__scroller{ background: #FAFAFA; @@ -66,6 +68,7 @@ export const ModalShare = ({ onClose, doc }: ModalShareProps) => { } > +