✨(frontend) increase doc visibility options
We now have 3 visibility options for docs: - public - restricted - authenticated We also have 2 editability options: - readonly - editable The editability options are only available for public and authenticated docs.
This commit is contained in:
@@ -13,6 +13,7 @@ and this project adheres to
|
|||||||
|
|
||||||
- 📝Contributing.md #352
|
- 📝Contributing.md #352
|
||||||
- 🌐(frontend) add localization to editor #268
|
- 🌐(frontend) add localization to editor #268
|
||||||
|
- ✨Public and restricted doc editable #357
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ export const keyCloakSignIn = async (page: Page, browserName: string) => {
|
|||||||
const login = `user-e2e-${browserName}`;
|
const login = `user-e2e-${browserName}`;
|
||||||
const password = `password-e2e-${browserName}`;
|
const password = `password-e2e-${browserName}`;
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.locator('.login-pf-page-header').getByText('impress'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
if (await page.getByLabel('Restart login').isVisible()) {
|
if (await page.getByLabel('Restart login').isVisible()) {
|
||||||
await page.getByRole('textbox', { name: 'password' }).fill(password);
|
await page.getByLabel('Restart login').click();
|
||||||
|
|
||||||
await page.click('input[type="submit"]', { force: true });
|
|
||||||
} else {
|
|
||||||
await page.getByRole('textbox', { name: 'username' }).fill(login);
|
|
||||||
|
|
||||||
await page.getByRole('textbox', { name: 'password' }).fill(password);
|
|
||||||
|
|
||||||
await page.click('input[type="submit"]', { force: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await page.getByRole('textbox', { name: 'username' }).fill(login);
|
||||||
|
await page.getByRole('textbox', { name: 'password' }).fill(password);
|
||||||
|
await page.click('input[type="submit"]', { force: true });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const randomName = (name: string, browserName: string, length: number) =>
|
export const randomName = (name: string, browserName: string, length: number) =>
|
||||||
@@ -27,7 +27,6 @@ export const createDoc = async (
|
|||||||
docName: string,
|
docName: string,
|
||||||
browserName: string,
|
browserName: string,
|
||||||
length: number,
|
length: number,
|
||||||
isPublic: boolean = false,
|
|
||||||
) => {
|
) => {
|
||||||
const randomDocs = randomName(docName, browserName, length);
|
const randomDocs = randomName(docName, browserName, length);
|
||||||
|
|
||||||
@@ -44,22 +43,6 @@ export const createDoc = async (
|
|||||||
await page.getByRole('heading', { name: 'Untitled document' }).click();
|
await page.getByRole('heading', { name: 'Untitled document' }).click();
|
||||||
await page.keyboard.type(randomDocs[i]);
|
await page.keyboard.type(randomDocs[i]);
|
||||||
await page.getByText('Created at ').click();
|
await page.getByText('Created at ').click();
|
||||||
|
|
||||||
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 },
|
|
||||||
force: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page
|
|
||||||
.getByLabel('It is the card information about the document.')
|
|
||||||
.getByText('Public'),
|
|
||||||
).toBeVisible();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomDocs;
|
return randomDocs;
|
||||||
|
|||||||
@@ -211,7 +211,11 @@ test.describe('Doc Header', () => {
|
|||||||
|
|
||||||
const shareModal = page.getByLabel('Share modal');
|
const shareModal = page.getByLabel('Share modal');
|
||||||
|
|
||||||
await expect(shareModal.getByLabel('Doc private')).toBeEnabled();
|
await expect(
|
||||||
|
shareModal.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
}),
|
||||||
|
).not.toHaveAttribute('disabled');
|
||||||
await expect(shareModal.getByText('Search by email')).toBeVisible();
|
await expect(shareModal.getByText('Search by email')).toBeVisible();
|
||||||
|
|
||||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||||
@@ -284,7 +288,11 @@ test.describe('Doc Header', () => {
|
|||||||
|
|
||||||
const shareModal = page.getByLabel('Share modal');
|
const shareModal = page.getByLabel('Share modal');
|
||||||
|
|
||||||
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
|
await expect(
|
||||||
|
shareModal.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
}),
|
||||||
|
).toHaveAttribute('disabled');
|
||||||
await expect(shareModal.getByText('Search by email')).toBeHidden();
|
await expect(shareModal.getByText('Search by email')).toBeHidden();
|
||||||
|
|
||||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||||
@@ -357,7 +365,11 @@ test.describe('Doc Header', () => {
|
|||||||
|
|
||||||
const shareModal = page.getByLabel('Share modal');
|
const shareModal = page.getByLabel('Share modal');
|
||||||
|
|
||||||
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
|
await expect(
|
||||||
|
shareModal.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
}),
|
||||||
|
).toHaveAttribute('disabled');
|
||||||
await expect(shareModal.getByText('Search by email')).toBeHidden();
|
await expect(shareModal.getByText('Search by email')).toBeHidden();
|
||||||
|
|
||||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||||
|
|||||||
@@ -164,14 +164,22 @@ test.describe('Document list members', () => {
|
|||||||
const shareModal = page.getByLabel('Share modal');
|
const shareModal = page.getByLabel('Share modal');
|
||||||
|
|
||||||
// Admin still have the right to share
|
// Admin still have the right to share
|
||||||
await expect(shareModal.getByLabel('Doc private')).toBeEnabled();
|
await expect(
|
||||||
|
shareModal.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
}),
|
||||||
|
).not.toHaveAttribute('disabled');
|
||||||
|
|
||||||
await SelectRoleCurrentUser.click();
|
await SelectRoleCurrentUser.click();
|
||||||
await page.getByRole('option', { name: 'Reader' }).click();
|
await page.getByRole('option', { name: 'Reader' }).click();
|
||||||
await expect(page.getByText('The role has been updated')).toBeVisible();
|
await expect(page.getByText('The role has been updated')).toBeVisible();
|
||||||
|
|
||||||
// Reader does not have the right to share
|
// Reader does not have the right to share
|
||||||
await expect(shareModal.getByLabel('Doc private')).toBeDisabled();
|
await expect(
|
||||||
|
shareModal.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
}),
|
||||||
|
).toHaveAttribute('disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('it checks the delete members', async ({ page, browserName }) => {
|
test('it checks the delete members', async ({ page, browserName }) => {
|
||||||
|
|||||||
@@ -2,39 +2,13 @@ import { expect, test } from '@playwright/test';
|
|||||||
|
|
||||||
import { createDoc, keyCloakSignIn } from './common';
|
import { createDoc, keyCloakSignIn } from './common';
|
||||||
|
|
||||||
|
const browsersName = ['chromium', 'webkit', 'firefox'];
|
||||||
|
|
||||||
test.describe('Doc Visibility', () => {
|
test.describe('Doc Visibility', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await page.goto('/');
|
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');
|
|
||||||
const datagridTable = datagrid.getByRole('table');
|
|
||||||
|
|
||||||
await expect(datagrid.getByLabel('Loading data')).toBeHidden({
|
|
||||||
timeout: 10000,
|
|
||||||
});
|
|
||||||
|
|
||||||
await expect(datagridTable.getByText(docTitle)).toBeVisible();
|
|
||||||
|
|
||||||
const row = datagridTable.getByRole('row').filter({
|
|
||||||
hasText: docTitle,
|
|
||||||
});
|
|
||||||
|
|
||||||
await expect(row.getByRole('cell').nth(0)).toHaveText('Public');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('It checks the copy link button', async ({ page, browserName }) => {
|
test('It checks the copy link button', async ({ page, browserName }) => {
|
||||||
// eslint-disable-next-line playwright/no-skipped-test
|
// eslint-disable-next-line playwright/no-skipped-test
|
||||||
test.skip(
|
test.skip(
|
||||||
@@ -56,12 +30,48 @@ test.describe('Doc Visibility', () => {
|
|||||||
|
|
||||||
expect(clipboardContent).toMatch(page.url());
|
expect(clipboardContent).toMatch(page.url());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('It checks the link role options', async ({ page, browserName }) => {
|
||||||
|
await createDoc(page, 'Doc role options', browserName, 1);
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
|
||||||
|
const selectVisibility = page.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(selectVisibility.getByText('Authenticated')).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByLabel('Read only')).toBeVisible();
|
||||||
|
await expect(page.getByLabel('Can read and edit')).toBeVisible();
|
||||||
|
|
||||||
|
await selectVisibility.click();
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Restricted',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByLabel('Read only')).toBeHidden();
|
||||||
|
await expect(page.getByLabel('Can read and edit')).toBeHidden();
|
||||||
|
|
||||||
|
await selectVisibility.click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Public',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(page.getByLabel('Read only')).toBeVisible();
|
||||||
|
await expect(page.getByLabel('Can read and edit')).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Doc Visibility: Not loggued', () => {
|
test.describe('Doc Visibility: Restricted', () => {
|
||||||
test.use({ storageState: { cookies: [], origins: [] } });
|
test.use({ storageState: { cookies: [], origins: [] } });
|
||||||
|
|
||||||
test('A public doc is accessible even when not authentified.', async ({
|
test('A doc is not accessible when not authentified.', async ({
|
||||||
page,
|
page,
|
||||||
browserName,
|
browserName,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -70,14 +80,211 @@ test.describe('Doc Visibility: Not loggued', () => {
|
|||||||
|
|
||||||
const [docTitle] = await createDoc(
|
const [docTitle] = await createDoc(
|
||||||
page,
|
page,
|
||||||
'My new doc',
|
'Restricted no auth',
|
||||||
browserName,
|
browserName,
|
||||||
1,
|
1,
|
||||||
true,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
await page
|
||||||
|
.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Restricted',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText('The document visiblitity has been updated.'),
|
page.getByText('The document visibility has been updated.'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.c__modal__backdrop').click({
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
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.getByRole('textbox', { name: 'password' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('A doc is not accessible when authentified but not member.', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
|
const [docTitle] = await createDoc(page, 'Restricted auth', browserName, 1);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
await page
|
||||||
|
.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Restricted',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.c__modal__backdrop').click({
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const urlDoc = page.url();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Logout',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||||
|
|
||||||
|
await keyCloakSignIn(page, otherBrowser!);
|
||||||
|
|
||||||
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('You do not have permission to perform this action.'),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('A doc is accessible when member.', async ({ page, browserName }) => {
|
||||||
|
test.slow();
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
|
const [docTitle] = await createDoc(page, 'Restricted auth', browserName, 1);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
await page
|
||||||
|
.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Restricted',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
const inputSearch = page.getByLabel(/Find a member to add to the document/);
|
||||||
|
|
||||||
|
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||||
|
const username = `user@${otherBrowser}.e2e`;
|
||||||
|
await inputSearch.fill(username);
|
||||||
|
await page.getByRole('option', { name: username }).click();
|
||||||
|
|
||||||
|
// Choose a role
|
||||||
|
await page.getByRole('combobox', { name: /Choose a role/ }).click();
|
||||||
|
await page.getByRole('option', { name: 'Administrator' }).click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Validate' }).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText(`User ${username} added to the document.`),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.c__modal__backdrop').click({
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const urlDoc = page.url();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Logout',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await keyCloakSignIn(page, otherBrowser!);
|
||||||
|
|
||||||
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
|
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Doc Visibility: Public', () => {
|
||||||
|
test.use({ storageState: { cookies: [], origins: [] } });
|
||||||
|
|
||||||
|
test('It checks a public doc in read only mode', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
|
const [docTitle] = await createDoc(
|
||||||
|
page,
|
||||||
|
'Public read only',
|
||||||
|
browserName,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
await page
|
||||||
|
.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Public',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByLabel('Read only').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.').first(),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.c__modal__backdrop').click({
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('It is the card information about the document.')
|
||||||
|
.getByText('Public', { exact: true }),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
|
|
||||||
const urlDoc = page.url();
|
const urlDoc = page.url();
|
||||||
@@ -94,19 +301,54 @@ test.describe('Doc Visibility: Not loggued', () => {
|
|||||||
|
|
||||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||||
await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();
|
await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();
|
||||||
|
await expect(
|
||||||
|
page.getByText('Read only, you cannot edit this document'),
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('A private doc redirect to the OIDC when not authentified.', async ({
|
test('It checks a public doc in editable mode', async ({
|
||||||
page,
|
page,
|
||||||
browserName,
|
browserName,
|
||||||
}) => {
|
}) => {
|
||||||
test.slow();
|
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await keyCloakSignIn(page, browserName);
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
const [docTitle] = await createDoc(page, 'My private doc', browserName, 1);
|
const [docTitle] = await createDoc(page, 'Public editable', browserName, 1);
|
||||||
|
|
||||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
await page
|
||||||
|
.getByRole('combobox', {
|
||||||
|
name: 'Visibility',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('option', {
|
||||||
|
name: 'Public',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.'),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByLabel('Can read and edit').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.').first(),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.c__modal__backdrop').click({
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page
|
||||||
|
.getByLabel('It is the card information about the document.')
|
||||||
|
.getByText('Public', { exact: true }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
const urlDoc = page.url();
|
const urlDoc = page.url();
|
||||||
|
|
||||||
@@ -116,10 +358,134 @@ test.describe('Doc Visibility: Not loggued', () => {
|
|||||||
})
|
})
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
await expect(page.getByRole('button', { name: 'Sign in' })).toBeVisible();
|
||||||
|
|
||||||
await page.goto(urlDoc);
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Share' })).toBeHidden();
|
||||||
|
await expect(
|
||||||
|
page.getByText('Read only, you cannot edit this document'),
|
||||||
|
).toBeHidden();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Doc Visibility: Authenticated', () => {
|
||||||
|
test.use({ storageState: { cookies: [], origins: [] } });
|
||||||
|
|
||||||
|
test('A doc is not accessible when unauthentified.', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
|
const [docTitle] = await createDoc(
|
||||||
|
page,
|
||||||
|
'Authenticated unauthentified',
|
||||||
|
browserName,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).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)).toBeHidden();
|
||||||
|
await expect(page.getByRole('textbox', { name: 'password' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('It checks a authenticated doc in read only mode', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
|
const [docTitle] = await createDoc(
|
||||||
|
page,
|
||||||
|
'Authenticated read only',
|
||||||
|
browserName,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
const urlDoc = page.url();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Logout',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||||
|
await keyCloakSignIn(page, otherBrowser!);
|
||||||
|
|
||||||
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
|
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText('Read only, you cannot edit this document'),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('It checks a authenticated doc in editable mode', async ({
|
||||||
|
page,
|
||||||
|
browserName,
|
||||||
|
}) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await keyCloakSignIn(page, browserName);
|
||||||
|
|
||||||
|
const [docTitle] = await createDoc(
|
||||||
|
page,
|
||||||
|
'Authenticated editable',
|
||||||
|
browserName,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: docTitle })).toBeVisible();
|
||||||
|
|
||||||
|
const urlDoc = page.url();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Share' }).click();
|
||||||
|
|
||||||
|
await page.getByLabel('Can read and edit').click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText('The document visibility has been updated.').first(),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await page.locator('.c__modal__backdrop').click({
|
||||||
|
position: { x: 0, y: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('button', {
|
||||||
|
name: 'Logout',
|
||||||
|
})
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const otherBrowser = browsersName.find((b) => b !== browserName);
|
||||||
|
await keyCloakSignIn(page, otherBrowser!);
|
||||||
|
|
||||||
|
await page.goto(urlDoc);
|
||||||
|
|
||||||
|
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||||
|
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||||
|
await expect(
|
||||||
|
page.getByText('Read only, you cannot edit this document'),
|
||||||
|
).toBeHidden();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -358,6 +358,8 @@ const config = {
|
|||||||
},
|
},
|
||||||
'forms-field': {
|
'forms-field': {
|
||||||
color: 'var(--c--theme--colors--primary-text)',
|
color: 'var(--c--theme--colors--primary-text)',
|
||||||
|
'footer-font-size': 'var(--c--theme--font--sizes--t)',
|
||||||
|
'footer-color': 'var(--c--theme--colors--greyscale-text)',
|
||||||
},
|
},
|
||||||
'forms-input': {
|
'forms-input': {
|
||||||
'border-radius': '4px',
|
'border-radius': '4px',
|
||||||
@@ -372,6 +374,9 @@ const config = {
|
|||||||
big: 'var(--c--theme--colors--primary-text)',
|
big: 'var(--c--theme--colors--primary-text)',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'forms-radio': {
|
||||||
|
'accent-color': 'var(--c--theme--colors--primary-600)',
|
||||||
|
},
|
||||||
'forms-select': {
|
'forms-select': {
|
||||||
'item-font-size': '14px',
|
'item-font-size': '14px',
|
||||||
'border-radius': '4px',
|
'border-radius': '4px',
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
line-height: initial;
|
line-height: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c__field .c__field__footer {
|
||||||
|
padding: 2px 0 0;
|
||||||
|
font-size: var(--c--components--forms-field--footer-font-size);
|
||||||
|
color: var(--c--components--forms-field--footer-color);
|
||||||
|
}
|
||||||
|
|
||||||
.labelled-box label {
|
.labelled-box label {
|
||||||
color: var(--c--theme--colors--primary-text);
|
color: var(--c--theme--colors--primary-text);
|
||||||
}
|
}
|
||||||
@@ -328,6 +334,10 @@ input:-webkit-autofill:focus {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c__checkbox.c__checkbox--disabled .c__checkbox__label {
|
||||||
|
color: var(--c--theme--colors--greyscale-400);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button
|
* Button
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -477,6 +477,12 @@
|
|||||||
--c--components--forms-datepicker--border-radius: 0;
|
--c--components--forms-datepicker--border-radius: 0;
|
||||||
--c--components--forms-fileuploader--border-radius: 0;
|
--c--components--forms-fileuploader--border-radius: 0;
|
||||||
--c--components--forms-field--color: var(--c--theme--colors--primary-text);
|
--c--components--forms-field--color: var(--c--theme--colors--primary-text);
|
||||||
|
--c--components--forms-field--footer-font-size: var(
|
||||||
|
--c--theme--font--sizes--t
|
||||||
|
);
|
||||||
|
--c--components--forms-field--footer-color: var(
|
||||||
|
--c--theme--colors--greyscale-text
|
||||||
|
);
|
||||||
--c--components--forms-input--border-radius: 4px;
|
--c--components--forms-input--border-radius: 4px;
|
||||||
--c--components--forms-input--background-color: #fff;
|
--c--components--forms-input--background-color: #fff;
|
||||||
--c--components--forms-input--border-color: var(
|
--c--components--forms-input--border-color: var(
|
||||||
@@ -492,6 +498,9 @@
|
|||||||
--c--components--forms-labelledbox--label-color--big: var(
|
--c--components--forms-labelledbox--label-color--big: var(
|
||||||
--c--theme--colors--primary-text
|
--c--theme--colors--primary-text
|
||||||
);
|
);
|
||||||
|
--c--components--forms-radio--accent-color: var(
|
||||||
|
--c--theme--colors--primary-600
|
||||||
|
);
|
||||||
--c--components--forms-select--item-font-size: 14px;
|
--c--components--forms-select--item-font-size: 14px;
|
||||||
--c--components--forms-select--border-radius: 4px;
|
--c--components--forms-select--border-radius: 4px;
|
||||||
--c--components--forms-select--border-radius-hover: 4px;
|
--c--components--forms-select--border-radius-hover: 4px;
|
||||||
|
|||||||
@@ -479,7 +479,11 @@ export const tokens = {
|
|||||||
},
|
},
|
||||||
'forms-datepicker': { 'border-radius': '0' },
|
'forms-datepicker': { 'border-radius': '0' },
|
||||||
'forms-fileuploader': { 'border-radius': '0' },
|
'forms-fileuploader': { 'border-radius': '0' },
|
||||||
'forms-field': { color: 'var(--c--theme--colors--primary-text)' },
|
'forms-field': {
|
||||||
|
color: 'var(--c--theme--colors--primary-text)',
|
||||||
|
'footer-font-size': 'var(--c--theme--font--sizes--t)',
|
||||||
|
'footer-color': 'var(--c--theme--colors--greyscale-text)',
|
||||||
|
},
|
||||||
'forms-input': {
|
'forms-input': {
|
||||||
'border-radius': '4px',
|
'border-radius': '4px',
|
||||||
'background-color': '#ffffff',
|
'background-color': '#ffffff',
|
||||||
@@ -491,6 +495,9 @@ export const tokens = {
|
|||||||
'forms-labelledbox': {
|
'forms-labelledbox': {
|
||||||
'label-color': { big: 'var(--c--theme--colors--primary-text)' },
|
'label-color': { big: 'var(--c--theme--colors--primary-text)' },
|
||||||
},
|
},
|
||||||
|
'forms-radio': {
|
||||||
|
'accent-color': 'var(--c--theme--colors--primary-600)',
|
||||||
|
},
|
||||||
'forms-select': {
|
'forms-select': {
|
||||||
'item-font-size': '14px',
|
'item-font-size': '14px',
|
||||||
'border-radius': '4px',
|
'border-radius': '4px',
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
Button,
|
Radio,
|
||||||
Switch,
|
RadioGroup,
|
||||||
|
Select,
|
||||||
VariantType,
|
VariantType,
|
||||||
useToastProvider,
|
useToastProvider,
|
||||||
} from '@openfun/cunningham-react';
|
} from '@openfun/cunningham-react';
|
||||||
import { useState } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { Box, Card, IconBG } from '@/components';
|
import { Box, Card, IconBG } from '@/components';
|
||||||
|
import { useCunninghamTheme } from '@/cunningham';
|
||||||
|
|
||||||
import { KEY_DOC, KEY_LIST_DOC, useUpdateDocLink } from '../api';
|
import { KEY_DOC, KEY_LIST_DOC, useUpdateDocLink } from '../api';
|
||||||
import { Doc, LinkReach } from '../types';
|
import { Doc, LinkReach, LinkRole } from '../types';
|
||||||
|
|
||||||
interface DocVisibilityProps {
|
interface DocVisibilityProps {
|
||||||
doc: Doc;
|
doc: Doc;
|
||||||
@@ -18,14 +19,12 @@ interface DocVisibilityProps {
|
|||||||
|
|
||||||
export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [docPublic, setDocPublic] = useState(
|
|
||||||
doc.link_reach === LinkReach.PUBLIC,
|
|
||||||
);
|
|
||||||
const { toast } = useToastProvider();
|
const { toast } = useToastProvider();
|
||||||
|
const { colorsTokens } = useCunninghamTheme();
|
||||||
const api = useUpdateDocLink({
|
const api = useUpdateDocLink({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
toast(
|
toast(
|
||||||
t('The document visiblitity has been updated.'),
|
t('The document visibility has been updated.'),
|
||||||
VariantType.SUCCESS,
|
VariantType.SUCCESS,
|
||||||
{
|
{
|
||||||
duration: 4000,
|
duration: 4000,
|
||||||
@@ -35,6 +34,34 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
|||||||
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
listInvalideQueries: [KEY_LIST_DOC, KEY_DOC],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const transLinkReach = {
|
||||||
|
[LinkReach.RESTRICTED]: {
|
||||||
|
label: t('Restricted'),
|
||||||
|
description: t('Only for people with access'),
|
||||||
|
},
|
||||||
|
[LinkReach.AUTHENTICATED]: {
|
||||||
|
label: t('Authenticated'),
|
||||||
|
description: t('Only for authenticated users'),
|
||||||
|
},
|
||||||
|
[LinkReach.PUBLIC]: {
|
||||||
|
label: t('Public'),
|
||||||
|
description: t('Anyone on the internet with the link can view'),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const linkRoleList = [
|
||||||
|
{
|
||||||
|
label: t('Read only'),
|
||||||
|
value: LinkRole.READER,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Can read and edit'),
|
||||||
|
value: LinkRole.EDITOR,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const showLinkRoleOptions = doc.link_reach !== LinkReach.RESTRICTED;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
$margin="tiny"
|
$margin="tiny"
|
||||||
@@ -44,55 +71,73 @@ export const DocVisibility = ({ doc }: DocVisibilityProps) => {
|
|||||||
$align="center"
|
$align="center"
|
||||||
$justify="space-between"
|
$justify="space-between"
|
||||||
$gap="1rem"
|
$gap="1rem"
|
||||||
|
$wrap="wrap"
|
||||||
>
|
>
|
||||||
<IconBG iconName="public" $margin="none" />
|
<IconBG iconName="public" />
|
||||||
<Box
|
<Box
|
||||||
$width="100%"
|
|
||||||
$wrap="wrap"
|
$wrap="wrap"
|
||||||
$gap="1rem"
|
$gap="1rem"
|
||||||
$justify="space-between"
|
|
||||||
$direction="row"
|
$direction="row"
|
||||||
|
$align="center"
|
||||||
|
$flex="1"
|
||||||
|
$css={`
|
||||||
|
& .c__field__footer .c__field__text {
|
||||||
|
${!doc.abilities.link_configuration && `color: ${colorsTokens()['greyscale-400']};`};
|
||||||
|
}
|
||||||
|
`}
|
||||||
>
|
>
|
||||||
<Box $direction="row" $gap="1rem" $align="center">
|
<Box $shrink="0" $flex="auto" $maxWidth="20rem">
|
||||||
<Switch
|
<Select
|
||||||
label={t(docPublic ? 'Doc public' : 'Doc private')}
|
label={t('Visibility')}
|
||||||
defaultChecked={docPublic}
|
options={Object.values(LinkReach).map((linkReach) => ({
|
||||||
onChange={() => {
|
label: transLinkReach[linkReach].label,
|
||||||
|
value: linkReach,
|
||||||
|
}))}
|
||||||
|
onChange={(evt) =>
|
||||||
api.mutate({
|
api.mutate({
|
||||||
|
link_reach: evt.target.value as LinkReach,
|
||||||
id: doc.id,
|
id: doc.id,
|
||||||
link_reach: docPublic ? LinkReach.RESTRICTED : LinkReach.PUBLIC,
|
})
|
||||||
link_role: 'reader',
|
|
||||||
});
|
|
||||||
setDocPublic(!docPublic);
|
|
||||||
}}
|
|
||||||
disabled={!doc.abilities.link_configuration}
|
|
||||||
text={
|
|
||||||
docPublic
|
|
||||||
? t('Anyone on the internet with the link can view')
|
|
||||||
: t('Only for people with access')
|
|
||||||
}
|
}
|
||||||
|
value={doc.link_reach}
|
||||||
|
clearable={false}
|
||||||
|
text={transLinkReach[doc.link_reach].description}
|
||||||
|
disabled={!doc.abilities.link_configuration}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Button
|
{showLinkRoleOptions && (
|
||||||
onClick={() => {
|
<Box
|
||||||
navigator.clipboard
|
$css={`
|
||||||
.writeText(window.location.href)
|
& .c__checkbox{
|
||||||
.then(() => {
|
padding: 0.15rem 0.25rem;
|
||||||
toast(t('Link Copied !'), VariantType.SUCCESS, {
|
}
|
||||||
duration: 3000,
|
`}
|
||||||
});
|
>
|
||||||
})
|
<RadioGroup
|
||||||
.catch(() => {
|
compact
|
||||||
toast(t('Failed to copy link'), VariantType.ERROR, {
|
style={{
|
||||||
duration: 3000,
|
display: 'flex',
|
||||||
});
|
}}
|
||||||
});
|
text={t('How people can interact with the document')}
|
||||||
}}
|
>
|
||||||
color="primary"
|
{linkRoleList.map((radio) => (
|
||||||
icon={<span className="material-icons">copy</span>}
|
<Radio
|
||||||
>
|
key={radio.value}
|
||||||
{t('Copy link')}
|
label={radio.label}
|
||||||
</Button>
|
value={radio.value}
|
||||||
|
onChange={() =>
|
||||||
|
api.mutate({
|
||||||
|
link_role: radio.value,
|
||||||
|
id: doc.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
checked={doc.link_role === radio.value}
|
||||||
|
disabled={!doc.abilities.link_configuration}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
VariantType,
|
||||||
|
useToastProvider,
|
||||||
|
} from '@openfun/cunningham-react';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { createGlobalStyle } from 'styled-components';
|
import { createGlobalStyle } from 'styled-components';
|
||||||
|
|
||||||
@@ -41,6 +46,7 @@ interface ModalShareProps {
|
|||||||
export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
|
export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
|
||||||
const { isMobile, isSmallMobile } = useResponsiveStore();
|
const { isMobile, isSmallMobile } = useResponsiveStore();
|
||||||
const width = isSmallMobile ? '100vw' : isMobile ? '90vw' : '70vw';
|
const width = isSmallMobile ? '100vw' : isMobile ? '90vw' : '70vw';
|
||||||
|
const { toast } = useToastProvider();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -68,13 +74,44 @@ export const ModalShare = ({ onClose, doc }: ModalShareProps) => {
|
|||||||
iconName="share"
|
iconName="share"
|
||||||
$margin="none"
|
$margin="none"
|
||||||
/>
|
/>
|
||||||
<Box $align="flex-start">
|
<Box
|
||||||
<Text as="h3" $size="26px" $margin="none">
|
$justify="space-between"
|
||||||
{t('Share')}
|
$direction="row"
|
||||||
</Text>
|
$align="center"
|
||||||
<Text $size="small" $weight="normal" $textAlign="left">
|
$width="100%"
|
||||||
{doc.title}
|
$gap="1rem"
|
||||||
</Text>
|
$wrap="wrap"
|
||||||
|
>
|
||||||
|
<Box $align="flex-start">
|
||||||
|
<Text as="h3" $size="26px" $margin="none">
|
||||||
|
{t('Share')}
|
||||||
|
</Text>
|
||||||
|
<Text $size="small" $weight="normal" $textAlign="left">
|
||||||
|
{doc.title}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box $margin={{ right: '1.5rem' }} $shrink="0">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard
|
||||||
|
.writeText(window.location.href)
|
||||||
|
.then(() => {
|
||||||
|
toast(t('Link Copied !'), VariantType.SUCCESS, {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
toast(t('Failed to copy link'), VariantType.ERROR, {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
icon={<span className="material-icons">copy</span>}
|
||||||
|
>
|
||||||
|
{t('Copy link')}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Card>
|
</Card>
|
||||||
<DocVisibility doc={doc} />
|
<DocVisibility doc={doc} />
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ export enum LinkReach {
|
|||||||
AUTHENTICATED = 'authenticated',
|
AUTHENTICATED = 'authenticated',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum LinkRole {
|
||||||
|
READER = 'reader',
|
||||||
|
EDITOR = 'editor',
|
||||||
|
}
|
||||||
|
|
||||||
export type Base64 = string;
|
export type Base64 = string;
|
||||||
|
|
||||||
export interface Doc {
|
export interface Doc {
|
||||||
@@ -34,7 +39,7 @@ export interface Doc {
|
|||||||
title: string;
|
title: string;
|
||||||
content: Base64;
|
content: Base64;
|
||||||
link_reach: LinkReach;
|
link_reach: LinkReach;
|
||||||
link_role: 'reader' | 'editor';
|
link_role: LinkRole;
|
||||||
accesses: Access[];
|
accesses: Access[];
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { WorkboxPlugin } from 'workbox-core';
|
import { WorkboxPlugin } from 'workbox-core';
|
||||||
|
|
||||||
import { Doc, DocsResponse } from '@/features/docs/doc-management';
|
import { Doc, DocsResponse } from '@/features/docs/doc-management';
|
||||||
import { LinkReach, Role } from '@/features/docs/doc-management/types';
|
import {
|
||||||
|
LinkReach,
|
||||||
|
LinkRole,
|
||||||
|
Role,
|
||||||
|
} from '@/features/docs/doc-management/types';
|
||||||
|
|
||||||
import { DBRequest, DocsDB } from './DocsDB';
|
import { DBRequest, DocsDB } from './DocsDB';
|
||||||
import { RequestSerializer } from './RequestSerializer';
|
import { RequestSerializer } from './RequestSerializer';
|
||||||
@@ -220,7 +224,7 @@ export class ApiPlugin implements WorkboxPlugin {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
link_reach: LinkReach.RESTRICTED,
|
link_reach: LinkReach.RESTRICTED,
|
||||||
link_role: 'reader',
|
link_role: LinkRole.READER,
|
||||||
};
|
};
|
||||||
|
|
||||||
await DocsDB.cacheResponse(
|
await DocsDB.cacheResponse(
|
||||||
|
|||||||
Reference in New Issue
Block a user