Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/impress-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,28 @@ jobs:
- name: Install Playwright Browsers
run: cd src/frontend/apps/e2e && yarn install-playwright chromium

# Tool to wait for a service to be ready
- name: Install Dockerize
run: |
curl -sSL https://github.com/jwilder/dockerize/releases/download/v0.8.0/dockerize-linux-amd64-v0.8.0.tar.gz | sudo tar -C /usr/local/bin -xzv

- name: Wait for services to be ready
run: |
printf "Minio check...\n"
dockerize -wait tcp://localhost:9000 -timeout 20s
printf "Keyclock check...\n"
dockerize -wait tcp://localhost:8080 -timeout 20s
printf "Server collaboration check...\n"
dockerize -wait tcp://localhost:4444 -timeout 20s
printf "Ngnix check...\n"
dockerize -wait tcp://localhost:8083 -timeout 20s
printf "DRF check...\n"
dockerize -wait tcp://localhost:8071 -timeout 20s
printf "Postgres Keyclock check...\n"
dockerize -wait tcp://localhost:5433 -timeout 20s
printf "Postgres back check...\n"
dockerize -wait tcp://localhost:15432 -timeout 20s

- name: Run e2e tests
run: cd src/frontend/ && yarn e2e:test --project='chromium'

Expand Down
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,18 @@ and this project adheres to

## [Unreleased]

## Added

- ✨(backend) annotate number of accesses on documents in list view #411
- ✨(backend) allow users to mark/unmark documents as favorite #411

## Changed

- 🔨(frontend) encapsulated title to its own component #474
- 🐛(frontend) Fix hidden menu on Firefox #468
- ⚡️(backend) optimize number of queries on document list view #411
- ♻️(frontend) stop to use provider with version #480
- 🚚(collaboration) change the websocket key name #480


## [1.8.2] - 2024-11-28
Expand All @@ -32,8 +41,6 @@ and this project adheres to

## Added

- ✨(backend) annotate number of accesses on documents in list view #411
- ✨(backend) allow users to mark/unmark documents as favorite #411
- 🌐(backend) add German translation #259
- 🌐(frontend) add German translation #255
- ✨(frontend) add a broadcast store #387
Expand All @@ -45,7 +52,6 @@ and this project adheres to

## Changed

- ⚡️(backend) optimize number of queries on document list view #411
- 🚸(backend) improve users similarity search and sort results #391
- ♻️(frontend) simplify stores #402
- ✨(frontend) update $css Box props type to add styled components RuleSet #423
Expand Down
2 changes: 1 addition & 1 deletion env.d/development/common.dist
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ AI_API_KEY=password
AI_MODEL=llama

# Collaboration
COLLABORATION_SERVER_URL=ws://localhost:4444
COLLABORATION_WS_URL=ws://localhost:4444

# Frontend
FRONTEND_THEME=dsfr
2 changes: 1 addition & 1 deletion src/backend/core/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ def get(self, request):
Return a dictionary of public settings.
"""
array_settings = [
"COLLABORATION_SERVER_URL",
"COLLABORATION_WS_URL",
"CRISP_WEBSITE_ID",
"ENVIRONMENT",
"FRONTEND_THEME",
Expand Down
4 changes: 2 additions & 2 deletions src/backend/core/tests/test_api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


@override_settings(
COLLABORATION_SERVER_URL="http://testcollab/",
COLLABORATION_WS_URL="http://testcollab/",
CRISP_WEBSITE_ID="123",
FRONTEND_THEME="test-theme",
MEDIA_BASE_URL="http://testserver/",
Expand All @@ -34,7 +34,7 @@ def test_api_config(is_authenticated):
response = client.get("/api/v1.0/config/")
assert response.status_code == HTTP_200_OK
assert response.json() == {
"COLLABORATION_SERVER_URL": "http://testcollab/",
"COLLABORATION_WS_URL": "http://testcollab/",
"CRISP_WEBSITE_ID": "123",
"ENVIRONMENT": "test",
"FRONTEND_THEME": "test-theme",
Expand Down
4 changes: 2 additions & 2 deletions src/backend/impress/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,8 +372,8 @@ class Base(Configuration):
SENTRY_DSN = values.Value(None, environ_name="SENTRY_DSN", environ_prefix=None)

# Collaboration
COLLABORATION_SERVER_URL = values.Value(
None, environ_name="COLLABORATION_SERVER_URL", environ_prefix=None
COLLABORATION_WS_URL = values.Value(
None, environ_name="COLLABORATION_WS_URL", environ_prefix=None
)

# Frontend
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/apps/e2e/__tests__/app-impress/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createDoc } from './common';

const config = {
CRISP_WEBSITE_ID: null,
COLLABORATION_SERVER_URL: 'ws://localhost:4444',
COLLABORATION_WS_URL: 'ws://localhost:4444',
ENVIRONMENT: 'development',
FRONTEND_THEME: 'dsfr',
MEDIA_BASE_URL: 'http://localhost:8083',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface ConfigResponse {
LANGUAGES: [string, string][];
LANGUAGE_CODE: string;
ENVIRONMENT: string;
COLLABORATION_SERVER_URL?: string;
COLLABORATION_WS_URL?: string;
CRISP_WEBSITE_ID?: string;
FRONTEND_THEME?: Theme;
MEDIA_BASE_URL?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ export const useCollaborationUrl = (room?: string) => {
}

const base =
conf?.COLLABORATION_SERVER_URL ||
(typeof window !== 'undefined' ? `wss://${window.location.host}/ws` : '');
conf?.COLLABORATION_WS_URL ||
(typeof window !== 'undefined'
? `wss://${window.location.host}/collaboration/ws/`
: '');

return `${base}/${room}`;
return `${base}?room=${room}`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import { useCreateBlockNote } from '@blocknote/react';
import { HocuspocusProvider } from '@hocuspocus/provider';
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs';

import { Box, TextErrors } from '@/components';
import { useAuthStore } from '@/core/auth';
import { Doc } from '@/features/docs/doc-management';

import { useUploadFile } from '../hook';
import { useHeadings } from '../hook/useHeadings';
import useSaveDoc from '../hook/useSaveDoc';
import { useEditorStore, useHeadingStore } from '../stores';
import { useEditorStore } from '../stores';
import { randomColor } from '../utils';

import { BlockNoteToolbar } from './BlockNoteToolbar';
Expand Down Expand Up @@ -65,21 +67,15 @@ const cssEditor = (readonly: boolean) => `
interface BlockNoteEditorProps {
doc: Doc;
provider: HocuspocusProvider;
storeId: string;
}

export const BlockNoteEditor = ({
doc,
provider,
storeId,
}: BlockNoteEditorProps) => {
const isVersion = doc.id !== storeId;
export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
const { userData } = useAuthStore();
const { setEditor } = useEditorStore();
const { t } = useTranslation();
const readOnly = !doc.abilities.partial_update || isVersion;

const readOnly = !doc.abilities.partial_update;
useSaveDoc(doc.id, provider.document, !readOnly);
const { setHeadings, resetHeadings } = useHeadingStore();
const { i18n } = useTranslation();
const lang = i18n.language;

Expand Down Expand Up @@ -130,6 +126,7 @@ export const BlockNoteEditor = ({
},
[collabName, lang, provider, uploadFile],
);
useHeadings(editor);

useEffect(() => {
setEditor(editor);
Expand All @@ -139,18 +136,6 @@ export const BlockNoteEditor = ({
};
}, [setEditor, editor]);

useEffect(() => {
setHeadings(editor);

editor?.onEditorContentChange(() => {
setHeadings(editor);
});

return () => {
resetHeadings();
};
}, [editor, resetHeadings, setHeadings]);

return (
<Box $css={cssEditor(readOnly)}>
{errorAttachment && (
Expand All @@ -174,3 +159,42 @@ export const BlockNoteEditor = ({
</Box>
);
};

interface BlockNoteEditorVersionProps {
initialContent: Y.XmlFragment;
}

export const BlockNoteEditorVersion = ({
initialContent,
}: BlockNoteEditorVersionProps) => {
const readOnly = true;
const { setEditor } = useEditorStore();
const editor = useCreateBlockNote(
{
collaboration: {
fragment: initialContent,
user: {
name: '',
color: '',
},
provider: undefined,
},
},
[initialContent],
);
useHeadings(editor);

useEffect(() => {
setEditor(editor);

return () => {
setEditor(undefined);
};
}, [setEditor, editor]);

return (
<Box $css={cssEditor(readOnly)}>
<BlockNoteView editor={editor} editable={!readOnly} theme="light" />
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { Alert, Loader, VariantType } from '@openfun/cunningham-react';
import { useRouter } from 'next/router';
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs';

import { Box, Card, Text, TextErrors } from '@/components';
import { useCollaborationUrl } from '@/core';
import { useCunninghamTheme } from '@/cunningham';
import { DocHeader } from '@/features/docs/doc-header';
import { Doc, useDocStore } from '@/features/docs/doc-management';
import {
Doc,
base64ToBlocknoteXmlFragment,
useDocStore,
} from '@/features/docs/doc-management';
import { Versions, useDocVersion } from '@/features/docs/doc-versioning/';
import { useResponsiveStore } from '@/stores';

import { useHeadingStore } from '../stores';

import { BlockNoteEditor } from './BlockNoteEditor';
import { BlockNoteEditor, BlockNoteEditorVersion } from './BlockNoteEditor';
import { IconOpenPanelEditor, PanelEditor } from './PanelEditor';

interface DocEditorProps {
Expand All @@ -25,7 +27,6 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
query: { versionId },
} = useRouter();
const { t } = useTranslation();
const { headings } = useHeadingStore();
const { isMobile } = useResponsiveStore();

const isVersion = versionId && typeof versionId === 'string';
Expand All @@ -41,7 +42,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => {

return (
<>
<DocHeader doc={doc} versionId={versionId as Versions['version_id']} />
<DocHeader doc={doc} />
{!doc.abilities.partial_update && (
<Box $margin={{ all: 'small', top: 'none' }}>
<Alert type={VariantType.WARNING}>
Expand Down Expand Up @@ -71,48 +72,47 @@ export const DocEditor = ({ doc }: DocEditorProps) => {
$position="relative"
>
{isVersion ? (
<DocVersionEditor doc={doc} versionId={versionId} />
<DocVersionEditor docId={doc.id} versionId={versionId} />
) : (
<BlockNoteEditor doc={doc} storeId={doc.id} provider={provider} />
<BlockNoteEditor doc={doc} provider={provider} />
)}
{!isMobile && <IconOpenPanelEditor headings={headings} />}
{!isMobile && <IconOpenPanelEditor />}
</Card>
<PanelEditor doc={doc} headings={headings} />
<PanelEditor doc={doc} />
</Box>
</>
);
};

interface DocVersionEditorProps {
doc: Doc;
docId: Doc['id'];
versionId: Versions['version_id'];
}

export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => {
export const DocVersionEditor = ({
docId,
versionId,
}: DocVersionEditorProps) => {
const {
data: version,
isLoading,
isError,
error,
} = useDocVersion({
docId: doc.id,
docId,
versionId,
});
const { createProvider, providers } = useDocStore();
const collaborationUrl = useCollaborationUrl(versionId);

const { replace } = useRouter();
const [initialContent, setInitialContent] = useState<Y.XmlFragment>();

useEffect(() => {
if (!version?.id || !collaborationUrl) {
if (!version?.content) {
return;
}

const provider = providers?.[version.id];
if (!provider || provider.document.guid !== version.id) {
createProvider(collaborationUrl, version.id, version.content);
}
}, [createProvider, providers, version, collaborationUrl]);
setInitialContent(base64ToBlocknoteXmlFragment(version.content));
}, [version?.content]);

if (isError && error) {
if (error.status === 404) {
Expand All @@ -136,19 +136,13 @@ export const DocVersionEditor = ({ doc, versionId }: DocVersionEditorProps) => {
);
}

if (isLoading || !version) {
if (isLoading || !version || !initialContent) {
return (
<Box $align="center" $justify="center" $height="100%">
<Loader />
</Box>
);
}

const provider = providers?.[version.id];

if (!provider) {
return null;
}

return <BlockNoteEditor doc={doc} storeId={version.id} provider={provider} />;
return <BlockNoteEditorVersion initialContent={initialContent} />;
};
Loading
Loading