+
+
+
+
+ + Chat on Matrix + - + Documentation + - + Getting started + - + Reach out + +
+ +# La Suite Docs : Collaborative Text Editing +Docs, where your notes can become knowledge through live collaboration. + +
+
+## Why use Docs ❓
+Docs is a collaborative text editor designed to address common challenges in knowledge building and sharing.
+
+It offers a scalable and secure alternative to tools such as Google Docs, Notion (without the dbs), Outline, or Confluence.
+
+### Write
+* 😌 Get simple, accessible online editing for your team.
+* 💅 Create clean documents with beautiful formatting options.
+* 🖌️ Focus on your content using either the in-line editor, or [the Markdown syntax](https://www.markdownguide.org/basic-syntax/).
+* 🧱 Quickly design your page thanks to the many block types, accessible from the `/` slash commands, as well as keyboard shortcuts.
+* 🔌 Write offline! Your edits will be synced once you're back online.
+* ✨ Save time thanks to our AI actions, such as rephrasing, summarizing, fixing typos, translating, etc. You can even turn your selected text into a prompt!
+
+### Work together
+* 🤝 Enjoy live editing! See your team collaborate in real time.
+* 🔒 Keep your information secure thanks to granular access control. Only share with the right people.
+* 📑 Export your content in multiple formats (`.odt`, `.docx`, `.pdf`) with customizable templates.
+* 📚 Turn your team's collaborative work into organized knowledge with Subpages.
+
+### Self-host
+🚀 Docs is easy to install on your own servers
+
+Available methods: Helm chart, Nix package
+
+In the works: Docker Compose, YunoHost
+
+⚠️ For some advanced features (ex: Export as PDF) Docs relies on XL packages from BlockNote. These are licenced under AGPL-3.0 and are not MIT compatible. You can perfectly use Docs without these packages by setting the environment variable `PUBLISH_AS_MIT` to true. That way you'll build an image of the application without the features that are not MIT compatible. Read the [environment variables documentation](/docs/env.md) for more information.
+
+## Getting started 🔧
+
+### Test it
+
+You can test Docs on your browser by visiting this [demo document](https://impress-preprod.beta.numerique.gouv.fr/docs/6ee5aac4-4fb9-457d-95bf-bb56c2467713/)
+
+### Run Docs locally
+
+> ⚠️ The methods described below for running Docs locally is **for testing purposes only**. It is based on building Docs using [Minio](https://min.io/) as an S3-compatible storage solution. Of course you can choose any S3-compatible storage solution.
+
+**Prerequisite**
+
+Make sure you have a recent version of Docker and [Docker Compose](https://docs.docker.com/compose/install) installed on your laptop, then type:
+
+```shellscript
+$ docker -v
+
+Docker version 20.10.2, build 2291f61
+
+$ docker compose version
+
+Docker Compose version v2.32.4
+```
+
+> ⚠️ You may need to run the following commands with `sudo`, but this can be avoided by adding your user to the local `docker` group.
+
+**Project bootstrap**
+
+The easiest way to start working on the project is to use [GNU Make](https://www.gnu.org/software/make/):
+
+```shellscript
+$ make bootstrap FLUSH_ARGS='--no-input'
+```
+
+This command builds the `app` container, installs dependencies, performs database migrations and compiles translations. It's a good idea to use this command each time you are pulling code from the project repository to avoid dependency-related or migration-related issues.
+
+Your Docker services should now be up and running 🎉
+
+You can access to the project by going to
+
+
|
+
+
+
+
+
+
+
+
|
+
+
+
+
+
diff --git a/submissions/devoteam/docs/src/frontend/apps/e2e/__tests__/app-impress/assets/test.svg b/submissions/devoteam/docs/src/frontend/apps/e2e/__tests__/app-impress/assets/test.svg
new file mode 100644
index 00000000..6980c934
--- /dev/null
+++ b/submissions/devoteam/docs/src/frontend/apps/e2e/__tests__/app-impress/assets/test.svg
@@ -0,0 +1,13 @@
+
diff --git a/submissions/devoteam/docs/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts b/submissions/devoteam/docs/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts
new file mode 100644
index 00000000..a6e18985
--- /dev/null
+++ b/submissions/devoteam/docs/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts
@@ -0,0 +1,59 @@
+import { FullConfig, FullProject, chromium, expect } from '@playwright/test';
+
+import { keyCloakSignIn } from './common';
+
+const saveStorageState = async (
+ browserConfig: FullProject= UseQueryOptions; +export type DefinedInitialDataInfiniteOptionsAPI< + Q, + TPageParam = number, +> = DefinedInitialDataInfiniteOptions< + Q, + APIError, + InfiniteData, + QueryKey, + TPageParam +>; + +/** + * Custom React hook that wraps React Query's `useInfiniteQuery` for paginated API requests. + * + * @template T - Type of the request parameters. + * @template Q - Type of the API response, which must include an optional `next` field for pagination. + * + * @param {string} key - Unique key to identify the query in the cache. + * @param {(props: T & { page: number }) => Promise} api - Function that fetches paginated data from the API. It receives the params merged with a page number. + * @param {T} param - Static parameters to send with every API request (excluding the page number). + * @param {DefinedInitialDataInfiniteOptionsAPI} [queryConfig] - Optional configuration passed to `useInfiniteQuery` (e.g., stale time, cache time). + * + * @returns Return value of `useInfiniteQuery`, including data, loading state, fetchNextPage, etc. + */ +export const useAPIInfiniteQuery =['next'] }>( + key: string, + api: (props: T & { page: number }) => Promise , + param: T, + queryConfig?: DefinedInitialDataInfiniteOptionsAPI, +) => { + return useInfiniteQuery, QueryKey, number>({ + initialPageParam: 1, + queryKey: [key, param], + queryFn: ({ pageParam }) => + api({ + ...param, + page: pageParam, + }), + getNextPageParam(lastPage, allPages) { + return lastPage.next ? allPages.length + 1 : undefined; + }, + ...queryConfig, + }); +}; diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/api/index.ts b/submissions/devoteam/docs/src/frontend/apps/impress/src/api/index.ts new file mode 100644 index 00000000..1d742adb --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/api/index.ts @@ -0,0 +1,6 @@ +export * from './APIError'; +export * from './config'; +export * from './fetchApi'; +export * from './helpers'; +export * from './types'; +export * from './utils'; diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/api/types.ts b/submissions/devoteam/docs/src/frontend/apps/impress/src/api/types.ts new file mode 100644 index 00000000..e69a61a5 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/api/types.ts @@ -0,0 +1,20 @@ +/** + * Generic interface representing a paginated API response. + * + * Commonly used for endpoints that return list results with pagination metadata. + * + * @template T - The type of items in the `results` array. + */ +export interface APIList{ + /** Total number of items across all pages */ + count: number; + + /** URL to the next page of results, if available (can be null or undefined) */ + next?: string | null; + + /** URL to the previous page of results, if available (can be null or undefined) */ + previous?: string | null; + + /** The list of items for the current page */ + results: T[]; +} diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/api/utils.ts b/submissions/devoteam/docs/src/frontend/apps/impress/src/api/utils.ts new file mode 100644 index 00000000..82bbe505 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/api/utils.ts @@ -0,0 +1,46 @@ +/** + * Extracts error information from an HTTP `Response` object. + * + * This is typically used to parse structured error responses from an API + * and normalize them into a consistent format with `status`, `cause`, and optional `data`. + * + * @param response - The HTTP response object from `fetch()`. + * @param data - Optional custom data to include with the error output. + * @returns An object containing: + * - `status`: HTTP status code from the response + * - `cause`: A flattened list of error messages, or undefined if no body + * - `data`: The optional data passed in + */ +export const errorCauses = async (response: Response, data?: unknown) => { + const errorsBody = (await response.json()) as Record< + string, + string | string[] + > | null; + + const causes = errorsBody + ? Object.entries(errorsBody) + .map(([, value]) => value) + .flat() + : undefined; + + return { + status: response.status, + cause: causes, + data, + }; +}; + +/** + * Retrieves the CSRF token from the browser's cookies. + * + * Assumes the CSRF token is stored as a cookie named "csrftoken". + * + * @returns The CSRF token string if found, otherwise `undefined`. + */ +export function getCSRFToken() { + return document.cookie + .split(';') + .filter((cookie) => cookie.trim().startsWith('csrftoken=')) + .map((cookie) => cookie.split('=')[1]) + .pop(); +} diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-401.png b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-401.png new file mode 100644 index 00000000..02c7c84d Binary files /dev/null and b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-401.png differ diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-403.png b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-403.png new file mode 100644 index 00000000..480944f3 Binary files /dev/null and b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-403.png differ diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-404.svg b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-404.svg new file mode 100644 index 00000000..fe705719 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-404.svg @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-docs.svg b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-docs.svg new file mode 100644 index 00000000..882e92ef --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-docs.svg @@ -0,0 +1,12 @@ + diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-group.svg b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-group.svg new file mode 100644 index 00000000..c2a7d3c3 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-group.svg @@ -0,0 +1,13 @@ + diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-group2.svg b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-group2.svg new file mode 100644 index 00000000..845da482 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-group2.svg @@ -0,0 +1,29 @@ + diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-user.svg b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-user.svg new file mode 100644 index 00000000..ff518b51 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/assets/icons/icon-user.svg @@ -0,0 +1,6 @@ + diff --git a/submissions/devoteam/docs/src/frontend/apps/impress/src/components/Box.tsx b/submissions/devoteam/docs/src/frontend/apps/impress/src/components/Box.tsx new file mode 100644 index 00000000..84e32057 --- /dev/null +++ b/submissions/devoteam/docs/src/frontend/apps/impress/src/components/Box.tsx @@ -0,0 +1,99 @@ +import { ComponentPropsWithRef, HTMLElementType } from 'react'; +import styled from 'styled-components'; +import { CSSProperties, RuleSet } from 'styled-components/dist/types'; + +import { + MarginPadding, + stylesMargin, + stylesPadding, +} from '@/utils/styleBuilder'; + +import { hideEffect, showEffect } from './Effect'; + +export interface BoxProps { + as?: HTMLElementType; + $align?: CSSProperties['alignItems']; + $background?: CSSProperties['background']; + $color?: CSSProperties['color']; + $css?: string | RuleSet