Skip to content

Integrate grist databases into docs (Panographix - HackDays 2025) #1082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 57 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
018fff4
🚧 create block
Jun 2, 2025
afa452b
💄 text and icons
Jun 2, 2025
5ffff53
✨ add database suggestion in advanced group
Clemsazert Jun 2, 2025
6402062
✨ useGristTable hook
Clemsazert Jun 2, 2025
4028af4
✨ connection to existing table
Clemsazert Jun 2, 2025
6f7adea
♻️ null args handling in grist hooks
Clemsazert Jun 2, 2025
f10d172
📦 install ag-grid
Jun 2, 2025
7352047
✨ display hardcoded grid
Jun 2, 2025
05f4798
✨ sort columns
Jun 2, 2025
b1276c7
✨ filter columns
Jun 2, 2025
7171163
✨ edit cells
Jun 2, 2025
8d7021c
💄 automatic height
Jun 2, 2025
11ce57e
✨ always show unsort icon
Jun 2, 2025
58f50ea
✨ add column button
Jun 2, 2025
028f599
♻️ extract add column button component
Jun 2, 2025
e6bf515
♻️ extract grid component
Jun 2, 2025
51fa439
✨ add column to table
Jun 2, 2025
d07b8d6
🐛 fix add second column
Jun 2, 2025
ad3b72d
🐛 close dropdown when adding a column
Jun 2, 2025
3dade6b
♻️ move table data inside grid component
Jun 2, 2025
2fa73e4
✨ format grist data for grid
Jun 2, 2025
2241ebe
✨ Extract DatabaseSelector
matts2cant Jun 3, 2025
cbd9850
✨ Add database selector before charts block
matts2cant Jun 3, 2025
3b42cba
✨ useGristCrudRecords hook
Clemsazert Jun 3, 2025
5a84830
✨ create & delete columns
Clemsazert Jun 3, 2025
a4c57ad
✨ create column propagation in grist
Clemsazert Jun 3, 2025
c9315c2
✨ create doc & table hook
Clemsazert Jun 3, 2025
ac70399
✨ create table when instanciating db block
Clemsazert Jun 3, 2025
08f6674
✨ add new row
Jun 3, 2025
8e5368e
✨ new row button
Jun 3, 2025
bb6fefc
💄 add button style
Jun 3, 2025
f3f033b
♻️ create new row util
Jun 3, 2025
d08e902
♻️ add hooks
Jun 3, 2025
35dbaaf
🐛 add row after creating columns
Jun 3, 2025
2f45cb5
♻️ extract cell renderer
Jun 3, 2025
16f81d7
✨ click on add row without editing cell
Jun 3, 2025
a8dd1a2
✨ add row to table
Jun 3, 2025
ebac06e
💄 min width on columns
Jun 3, 2025
7e31e6c
🏷️ type row
Jun 3, 2025
cbb1282
🏷️ type database row
Jun 3, 2025
fc912a1
🐛 create new row with undefined values
Jun 3, 2025
6e8f360
🐛 add column button outside table
Jun 3, 2025
dc2ec81
♻️ extract add row cal span compute
Jun 3, 2025
2669585
♻️ extract get columns names
Jun 3, 2025
2304a12
🐛 remove add row magic string
Jun 3, 2025
c35de2a
🐛 make add new row span new column
Jun 3, 2025
0b64be6
♻️ extract default col def
Jun 3, 2025
a4ac8e0
✨ create row in grist
Jun 3, 2025
0e7859a
♻️ use object to type function
Jun 3, 2025
64fe874
✨ hide id table
Jun 3, 2025
f689e38
✨ edit cell in grist
Jun 3, 2025
def6058
♻️ useQuery in listGristTable
Clemsazert Jun 3, 2025
aa30f9b
💄 revamp db source selector
Clemsazert Jun 3, 2025
1012ea0
🐛 set db block to non editable
Clemsazert Jun 3, 2025
29f9b0e
✨ allow hiding create db option
Clemsazert Jun 3, 2025
1fc3715
🐛 pin add row to bottom
Jun 3, 2025
757b776
✨ add grist keyword for database
Jun 3, 2025
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
17 changes: 6 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to
- ✨(frontend) add customization for translations #857
- 📝(project) add troubleshoot doc #1066
- 📝(project) add system-requirement doc #1066
- ✨(frontend) Add a custom database block to the editor #1053

### Changed

Expand All @@ -28,7 +29,6 @@ and this project adheres to
-🐛(frontend) fix meta title #1017
-🔧(git) set LF line endings for all text files #1032


## [3.3.0] - 2025-05-06

### Added
Expand All @@ -54,21 +54,20 @@ and this project adheres to
- ⬆️(docker) upgrade node images to alpine 3.21 #973

### Fixed

- 🐛(y-provider) increase JSON size limits for transcription conversion #989

### Removed

- 🔥(back) remove footer endpoint #948


## [3.2.1] - 2025-05-06

## Fixed

- 🐛(frontend) fix list copy paste #943
- 📝(doc) update contributing policy (commit signatures are now mandatory) #895


## [3.2.0] - 2025-05-05

## Added
Expand All @@ -79,7 +78,7 @@ and this project adheres to
- ✨(settings) Allow configuring PKCE for the SSO #886
- 🌐(i18n) activate chinese and spanish languages #884
- 🔧(backend) allow overwriting the data directory #893
- ➕(backend) add `django-lasuite` dependency #839
- ➕(backend) add `django-lasuite` dependency #839
- ✨(frontend) advanced table features #908

## Changed
Expand Down Expand Up @@ -130,7 +129,6 @@ and this project adheres to
- 🐛(backend) compute ancestor_links in get_abilities if needed #725
- 🔒️(back) restrict access to document accesses #801


## [2.6.0] - 2025-03-21

## Added
Expand All @@ -149,7 +147,6 @@ and this project adheres to
- 🔒️(back) throttle user list endpoint #636
- 🔒️(back) remove pagination and limit to 5 for user list endpoint #636


## [2.5.0] - 2025-03-18

## Added
Expand All @@ -172,15 +169,14 @@ and this project adheres to
## Fixed

- 🐛(frontend) SVG export #706
- 🐛(frontend) remove scroll listener table content #688
- 🐛(frontend) remove scroll listener table content #688
- 🔒️(back) restrict access to favorite_list endpoint #690
- 🐛(backend) refactor to fix filtering on children
and descendants views #695
- 🐛(backend) refactor to fix filtering on children
and descendants views #695
- 🐛(action) fix notify-argocd workflow #713
- 🚨(helm) fix helmfile lint #736
- 🚚(frontend) redirect to 401 page when 401 error #759


## [2.4.0] - 2025-03-06

## Added
Expand All @@ -195,7 +191,6 @@ and this project adheres to

- 🐛(frontend) fix collaboration error #684


## [2.3.0] - 2025-03-03

## Added
Expand Down
1 change: 1 addition & 0 deletions src/frontend/apps/impress/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NEXT_PUBLIC_API_ORIGIN=
NEXT_PUBLIC_SW_DEACTIVATED=
NEXT_PUBLIC_PUBLISH_AS_MIT=true
NEXT_PUBLIC_GRIST_API_KEY=
1 change: 1 addition & 0 deletions src/frontend/apps/impress/.env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
NEXT_PUBLIC_API_ORIGIN=http://localhost:8071
NEXT_PUBLIC_PUBLISH_AS_MIT=false
NEXT_PUBLIC_SW_DEACTIVATED=true
NEXT_PUBLIC_GRIST_API_KEY=
1 change: 1 addition & 0 deletions src/frontend/apps/impress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@react-pdf/renderer": "4.3.0",
"@sentry/nextjs": "9.26.0",
"@tanstack/react-query": "5.80.5",
"ag-grid-react": "^33.3.1",
"canvg": "4.0.3",
"clsx": "2.1.1",
"cmdk": "1.1.1",
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/apps/impress/src/api/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ export const backendUrl = () =>
*/
export const baseApiUrl = (apiVersion: string = '1.0') =>
`${backendUrl()}/api/v${apiVersion}/`;

export const gristApiUrl = () => 'http://localhost:8484/api/';
16 changes: 16 additions & 0 deletions src/frontend/apps/impress/src/api/gristApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { gristApiUrl } from './config';

export const gristFetchApi = async (input: string, init?: RequestInit) => {
const apiUrl = `${gristApiUrl()}${input}`;
const bearerToken = `Bearer ${process.env.NEXT_PUBLIC_GRIST_API_KEY}`;

const headers = {
'Content-Type': 'application/json',
Authorization: bearerToken,
};

return await fetch(apiUrl, {
...init,
headers,
});
};
1 change: 1 addition & 0 deletions src/frontend/apps/impress/src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './APIError';
export * from './config';
export * from './fetchApi';
export * from './gristApi';
export * from './helpers';
export * from './types';
export * from './utils';
4 changes: 4 additions & 0 deletions src/frontend/apps/impress/src/components/DropButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
CSSProperties,
PropsWithChildren,
ReactNode,
useEffect,
Expand Down Expand Up @@ -38,6 +39,7 @@ const StyledButton = styled(Button)<StyledButtonProps>`
export interface DropButtonProps {
button: ReactNode;
buttonCss?: BoxProps['$css'];
buttonStyle?: CSSProperties;
isOpen?: boolean;
onOpenChange?: (isOpen: boolean) => void;
label?: string;
Expand All @@ -46,6 +48,7 @@ export interface DropButtonProps {
export const DropButton = ({
button,
buttonCss,
buttonStyle,
isOpen = false,
onOpenChange,
children,
Expand Down Expand Up @@ -77,6 +80,7 @@ export const DropButton = ({
${buttonCss};
`}
className="--docs--drop-button"
style={buttonStyle}
>
{button}
</StyledButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BlockNoteView } from '@blocknote/mantine';
import '@blocknote/mantine/style.css';
import { useCreateBlockNote } from '@blocknote/react';
import { HocuspocusProvider } from '@hocuspocus/provider';
import { AllCommunityModule, ModuleRegistry } from 'ag-grid-community';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import * as Y from 'yjs';
Expand All @@ -27,13 +28,16 @@ import { randomColor } from '../utils';

import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
import { CalloutBlock, DividerBlock } from './custom-blocks';
import { CalloutBlock, DatabaseBlock, DividerBlock } from './custom-blocks';

ModuleRegistry.registerModules([AllCommunityModule]);

export const blockNoteSchema = withPageBreak(
BlockNoteSchema.create({
blockSpecs: {
...defaultBlockSpecs,
callout: CalloutBlock,
database: DatabaseBlock,
divider: DividerBlock,
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import { DocsBlockSchema } from '../types';

import {
getCalloutReactSlashMenuItems,
getDatabaseReactSlashMenuItems,
getDividerReactSlashMenuItems,
} from './custom-blocks';

export const BlockNoteSuggestionMenu = () => {
const editor = useBlockNoteEditor<DocsBlockSchema>();
const { t } = useTranslation();
const basicBlocksName = useDictionary().slash_menu.page_break.group;
const advancedBlocksName = useDictionary().slash_menu.table.group;

const getSlashMenuItems = useMemo(() => {
return async (query: string) =>
Expand All @@ -29,12 +31,13 @@ export const BlockNoteSuggestionMenu = () => {
getDefaultReactSlashMenuItems(editor),
getPageBreakReactSlashMenuItems(editor),
getCalloutReactSlashMenuItems(editor, t, basicBlocksName),
getDatabaseReactSlashMenuItems(editor, t, advancedBlocksName),
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
),
query,
),
);
}, [basicBlocksName, editor, t]);
}, [basicBlocksName, advancedBlocksName, editor, t]);

return (
<SuggestionMenuController
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { Button } from '@openfun/cunningham-react';
import React from 'react';
import styled from 'styled-components';

import { Box, Icon, Text } from '@/components';
import { DatabaseSourceSelector } from '@/docs/doc-editor/components/DatabaseSourceSelector';
import { useGristCreateDocAndTable } from '@/features/grist/useGristCreateTable';

import { useDocStore } from '../../doc-management';

type DatabaseSelectorProps = {
onDatabaseSelected: (args: { documentId: string; tableId: string }) => void;
allowCreateSource?: boolean;
};

export const DatabaseSelector = ({
onDatabaseSelected,
allowCreateSource = false,
}: DatabaseSelectorProps) => {
const { createTable } = useGristCreateDocAndTable();
const { currentDoc } = useDocStore();

const handleCreateNewDatabase = () => {
if (!currentDoc) {
console.error('No current document found to create a new database.');
return;
}
createTable(currentDoc.title ?? currentDoc.id)
.then(({ documentId, tableId }) => {
onDatabaseSelected({ documentId, tableId });
})
.catch((error) => {
console.error('Error creating new database:', error);
});
};

return (
<Wrapper>
<Box
style={{
width: 40,
height: 40,
borderRadius: 20,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'rgb(133, 184, 255)',
}}
>
<Icon iconName="storage" color="rgb(62, 152, 255)" />
</Box>
<Title>Source de données</Title>
{allowCreateSource && (
<Description>Choisissez votre méthode de création</Description>
)}
<OptionsWrapper>
{allowCreateSource && (
<>
<Option>
<Box
style={{
flexDirection: 'row',
justifyContent: 'space-between',
}}
>
<Box>
<OptionTitle>
Créer une nouvelle base de données vide
</OptionTitle>
<Description>
Partir d&apos;une base de données vierge
</Description>
</Box>
<Button
onClick={handleCreateNewDatabase}
icon={<Icon iconName="add" $color="white" />}
></Button>
</Box>
</Option>
<Text style={{ fontWeight: 600, fontSize: 14 }}>ou</Text>
</>
)}
<Option>
<Box style={{ marginBottom: 10 }}>
<OptionTitle>
Sélectionner une base de données existante
</OptionTitle>
<Description>
Connecter une base de données Grist déjà créée
</Description>
</Box>
<DatabaseSourceSelector onSourceSelected={onDatabaseSelected} />
</Option>
</OptionsWrapper>
</Wrapper>
);
};

const Wrapper = styled(Box)`
border: 2px solid rgb(160, 207, 255);
background-color: rgb(230, 243, 255);
border-radius: 4px;
width: 100%;
padding: 16px;
align-items: center;
gap: 10px;
`;

const Title = styled(Text)`
font-weight: 800;
font-size: 18px;
`;

const Description = styled(Text)`
color: rgb(110, 110, 110);
font-size: 14px;
`;

const OptionTitle = styled(Text)`
font-weight: 600;
font-size: 14px;
`;

const Option = styled(Box)`
width: 100%;
border: 1px solid rgb(180, 180, 180);
border-radius: 4px;
padding: 8px 16px;
`;

const OptionsWrapper = styled(Box)`
width: 100%;
gap: 5px;
align-items: center;
`;
Loading