diff --git a/CHANGELOG.md b/CHANGELOG.md
index 83c2756d..99ecaa94 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,14 @@ and this project adheres to
## [Unreleased]
+## [2.0.1] - 2025-01-17
+
+## Fixed
+
+-🐛(frontend) share modal is shown when you don't have the abilities #557
+-🐛(frontend) title copy break app #564
+
+
## [2.0.0] - 2025-01-13
## Added
@@ -353,7 +361,8 @@ and this project adheres to
- 🚀 Impress, project to manage your documents easily and collaboratively.
-[unreleased]: https://github.com/numerique-gouv/impress/compare/v2.0.0...main
+[unreleased]: https://github.com/numerique-gouv/impress/compare/v2.0.1...main
+[v2.0.1]: https://github.com/numerique-gouv/impress/releases/v2.0.1
[v2.0.0]: https://github.com/numerique-gouv/impress/releases/v2.0.0
[v1.10.0]: https://github.com/numerique-gouv/impress/releases/v1.10.0
[v1.9.0]: https://github.com/numerique-gouv/impress/releases/v1.9.0
diff --git a/src/backend/pyproject.toml b/src/backend/pyproject.toml
index d73bdc2e..25b5df95 100644
--- a/src/backend/pyproject.toml
+++ b/src/backend/pyproject.toml
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "impress"
-version = "2.0.0"
+version = "2.0.1"
authors = [{ "name" = "DINUM", "email" = "dev@mail.numerique.gouv.fr" }]
classifiers = [
"Development Status :: 5 - Production/Stable",
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 91c66b32..a9be9dac 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
@@ -47,6 +47,7 @@ test.describe('Doc Header', () => {
versions_list: true,
versions_retrieve: true,
accesses_manage: true,
+ accesses_view: true,
update: true,
partial_update: true,
retrieve: true,
@@ -394,7 +395,31 @@ test.describe('Doc Header', () => {
navigator.clipboard.readText(),
);
const clipboardContent = await handle.jsonValue();
- expect(clipboardContent.trim()).toBe(`
Hello World
`);
+ expect(clipboardContent.trim()).toBe(
+ `Hello World
`,
+ );
+ });
+
+ test('it checks the copy link button', async ({ page }) => {
+ await mockedDocument(page, {
+ abilities: {
+ destroy: false, // Means owner
+ link_configuration: true,
+ versions_destroy: true,
+ versions_list: true,
+ versions_retrieve: true,
+ accesses_manage: false,
+ accesses_view: false,
+ update: true,
+ partial_update: true,
+ retrieve: true,
+ },
+ });
+
+ await goToGridDoc(page);
+
+ await page.getByRole('button', { name: 'Copy link' }).click();
+ await expect(page.getByText('Link Copied !')).toBeVisible();
});
});
@@ -405,6 +430,45 @@ test.describe('Documents Header mobile', () => {
await page.goto('/');
});
+ test('it checks the copy link button', async ({ page, browserName }) => {
+ // eslint-disable-next-line playwright/no-skipped-test
+ test.skip(
+ browserName === 'webkit',
+ 'navigator.clipboard is not working with webkit and playwright',
+ );
+ await mockedDocument(page, {
+ abilities: {
+ destroy: false,
+ link_configuration: true,
+ versions_destroy: true,
+ versions_list: true,
+ versions_retrieve: true,
+ accesses_manage: false,
+ accesses_view: false,
+ update: true,
+ partial_update: true,
+ retrieve: true,
+ },
+ });
+
+ await goToGridDoc(page);
+
+ await expect(page.getByRole('button', { name: 'Copy link' })).toBeHidden();
+ await page.getByLabel('Open the document options').click();
+ await page.getByRole('button', { name: 'Copy link' }).click();
+ await expect(page.getByText('Link Copied !')).toBeVisible();
+ // Test that clipboard is in HTML format
+ const handle = await page.evaluateHandle(() =>
+ navigator.clipboard.readText(),
+ );
+ const clipboardContent = await handle.jsonValue();
+
+ const origin = await page.evaluate(() => window.location.origin);
+ expect(clipboardContent.trim()).toMatch(
+ `${origin}/docs/mocked-document-id/`,
+ );
+ });
+
test('it checks the close button on Share modal', async ({ page }) => {
await mockedDocument(page, {
abilities: {
@@ -414,6 +478,7 @@ test.describe('Documents Header mobile', () => {
versions_list: true,
versions_retrieve: true,
accesses_manage: true,
+ accesses_view: true,
update: true,
partial_update: true,
retrieve: true,
diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts
index 04015e9e..f9d306a5 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts
@@ -79,7 +79,7 @@ test.describe('Document create member', () => {
await expect(quickSearchContent.getByText(email).first()).toBeVisible();
// Check user added
- await expect(page.getByText('Share with 3 users')).toBeVisible();
+ await expect(page.getByText('Share with 2 users')).toBeVisible();
await expect(
quickSearchContent.getByText(users[0].full_name).first(),
).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
index f493c8de..612c1a4b 100644
--- a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts
+++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts
@@ -413,14 +413,8 @@ test.describe('Doc Visibility: Authenticated', () => {
await page.goto(urlDoc);
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
- await page.getByRole('button', { name: 'Share' }).click();
-
- await expect(selectVisibility).toBeHidden();
-
- const inputSearch = page.getByRole('combobox', {
- name: 'Quick search input',
- });
- await expect(inputSearch).toBeHidden();
+ await page.getByRole('button', { name: 'Copy link' }).click();
+ await expect(page.getByText('Link Copied !')).toBeVisible();
});
test('It checks a authenticated doc in editable mode', async ({
@@ -474,13 +468,7 @@ test.describe('Doc Visibility: Authenticated', () => {
await page.goto(urlDoc);
await verifyDocName(page, docTitle);
- await page.getByRole('button', { name: 'Share' }).click();
-
- await expect(selectVisibility).toBeHidden();
-
- const inputSearch = page.getByRole('combobox', {
- name: 'Quick search input',
- });
- await expect(inputSearch).toBeHidden();
+ await page.getByRole('button', { name: 'Copy link' }).click();
+ await expect(page.getByText('Link Copied !')).toBeVisible();
});
});
diff --git a/src/frontend/apps/e2e/package.json b/src/frontend/apps/e2e/package.json
index 1d330701..b46958ca 100644
--- a/src/frontend/apps/e2e/package.json
+++ b/src/frontend/apps/e2e/package.json
@@ -1,6 +1,6 @@
{
"name": "app-e2e",
- "version": "2.0.0",
+ "version": "2.0.1",
"private": true,
"scripts": {
"lint": "eslint . --ext .ts",
diff --git a/src/frontend/apps/impress/package.json b/src/frontend/apps/impress/package.json
index 4989309e..658588e5 100644
--- a/src/frontend/apps/impress/package.json
+++ b/src/frontend/apps/impress/package.json
@@ -1,6 +1,6 @@
{
"name": "app-impress",
- "version": "2.0.0",
+ "version": "2.0.1",
"private": true,
"scripts": {
"dev": "next dev",
@@ -15,9 +15,9 @@
"test:watch": "jest --watch"
},
"dependencies": {
- "@blocknote/core": "0.22.0",
- "@blocknote/mantine": "0.22.0",
- "@blocknote/react": "0.22.0",
+ "@blocknote/core": "0.21.0",
+ "@blocknote/mantine": "0.21.0",
+ "@blocknote/react": "0.21.0",
"@gouvfr-lasuite/integration": "1.0.2",
"@hocuspocus/provider": "2.15.0",
"@openfun/cunningham-react": "2.9.4",
diff --git a/src/frontend/apps/impress/src/components/DropdownMenu.tsx b/src/frontend/apps/impress/src/components/DropdownMenu.tsx
index 8c390c73..d7f749b4 100644
--- a/src/frontend/apps/impress/src/components/DropdownMenu.tsx
+++ b/src/frontend/apps/impress/src/components/DropdownMenu.tsx
@@ -54,7 +54,7 @@ export const DropdownMenu = ({
$css={
arrowCss ??
css`
- color: var(--c--theme--colors--primary-600);
+ color: var(--c--theme--colors--primary-700);
`
}
iconName={isOpen ? 'arrow_drop_up' : 'arrow_drop_down'}
diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
index 8886562b..326163dd 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx
@@ -6,6 +6,7 @@ import { useCreateBlockNote } from '@blocknote/react';
import { HocuspocusProvider } from '@hocuspocus/provider';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
+import { css } from 'styled-components';
import * as Y from 'yjs';
import { Box, TextErrors } from '@/components';
@@ -20,17 +21,19 @@ import { randomColor } from '../utils';
import { BlockNoteToolbar } from './BlockNoteToolbar';
-const cssEditor = (readonly: boolean) => `
- &, & > .bn-container, & .ProseMirror {
- height:100%;
-
- .bn-side-menu[data-block-type=heading][data-level="1"] {
- height: 50px;
- }
- .bn-side-menu[data-block-type=heading][data-level="2"] {
- height: 43px;
- }
- .bn-side-menu[data-block-type=heading][data-level="3"] {
+const cssEditor = (readonly: boolean) => css`
+ &,
+ & > .bn-container,
+ & .ProseMirror {
+ height: 100%;
+
+ .bn-side-menu[data-block-type='heading'][data-level='1'] {
+ height: 50px;
+ }
+ .bn-side-menu[data-block-type='heading'][data-level='2'] {
+ height: 43px;
+ }
+ .bn-side-menu[data-block-type='heading'][data-level='3'] {
height: 35px;
}
h1 {
@@ -52,11 +55,11 @@ const cssEditor = (readonly: boolean) => `
border-left: none;
}
}
-
+
.bn-editor {
-
color: var(--c--theme--colors--greyscale-700);
}
+
.bn-block-outer:not(:first-child) {
&:has(h1) {
padding-top: 32px;
@@ -67,25 +70,25 @@ const cssEditor = (readonly: boolean) => `
&:has(h3) {
padding-top: 16px;
}
- };
-
+ }
+
& .bn-inline-content code {
background-color: gainsboro;
padding: 2px;
border-radius: 4px;
}
+
@media screen and (width <= 560px) {
& .bn-editor {
-
${readonly && `padding-left: 10px;`}
- };
- .bn-side-menu[data-block-type=heading][data-level="1"] {
- height: 46px;
}
- .bn-side-menu[data-block-type=heading][data-level="2"] {
+ .bn-side-menu[data-block-type='heading'][data-level='1'] {
+ height: 46px;
+ }
+ .bn-side-menu[data-block-type='heading'][data-level='2'] {
height: 40px;
}
- .bn-side-menu[data-block-type=heading][data-level="3"] {
+ .bn-side-menu[data-block-type='heading'][data-level='3'] {
height: 40px;
}
& .bn-editor h1 {
@@ -97,7 +100,7 @@ const cssEditor = (readonly: boolean) => `
& .bn-editor h3 {
font-size: 1.2rem;
}
- .bn-block-content[data-is-empty-and-focused][data-content-type="paragraph"]
+ .bn-block-content[data-is-empty-and-focused][data-content-type='paragraph']
.bn-inline-content:has(> .ProseMirror-trailingBreak:only-child)::before {
font-size: 14px;
}
@@ -176,7 +179,11 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
}, [setEditor, editor]);
return (
-
+
{errorAttachment && (
{
)}
-
+
{
-
+
>
);
diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx
index adf3ce5c..a940e90c 100644
--- a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx
+++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocToolBox.tsx
@@ -16,10 +16,13 @@ import {
Icon,
IconOptions,
} from '@/components';
-import { useAuthStore } from '@/core';
import { useCunninghamTheme } from '@/cunningham';
import { useEditorStore } from '@/features/docs/doc-editor/';
-import { Doc, ModalRemoveDoc } from '@/features/docs/doc-management';
+import {
+ Doc,
+ ModalRemoveDoc,
+ useCopyDocLink,
+} from '@/features/docs/doc-management';
import { DocShareModal } from '@/features/docs/doc-share';
import {
KEY_LIST_DOC_VERSIONS,
@@ -37,6 +40,9 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
const { t } = useTranslation();
const hasAccesses = doc.nb_accesses > 1;
const queryClient = useQueryClient();
+
+ const copyDocLink = useCopyDocLink(doc.id);
+
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
const spacings = spacingsTokens();
@@ -48,18 +54,24 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
const modalShare = useModal();
const { isSmallMobile, isDesktop } = useResponsiveStore();
- const { authenticated } = useAuthStore();
const { editor } = useEditorStore();
+
const { toast } = useToastProvider();
+ const canViewAccesses = doc.abilities.accesses_view;
const options: DropdownMenuOption[] = [
...(isSmallMobile
? [
{
- label: t('Share'),
- icon: 'upload',
+ label: canViewAccesses ? t('Share') : t('Copy link'),
+ icon: canViewAccesses ? 'group' : 'link',
+
callback: () => {
- modalShare.open();
+ if (canViewAccesses) {
+ modalShare.open();
+ return;
+ }
+ copyDocLink();
},
},
{
@@ -153,7 +165,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
$margin={{ left: 'auto' }}
$gap={spacings['2xs']}
>
- {authenticated && !isSmallMobile && (
+ {canViewAccesses && !isSmallMobile && (
<>
{!hasAccesses && (
)}
>
)}
+ {!canViewAccesses && !isSmallMobile && (
+
+ )}
{!isSmallMobile && (