Skip to content

feat(database): open Grist api key modal #1027

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

Open
wants to merge 97 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
e96f495
🚧 create block
Jun 2, 2025
d349a51
💄 text and icons
Jun 2, 2025
ff1d0e6
💄
Jun 2, 2025
2c2e34f
✨ base style option for database in WIP
Clemsazert Jun 2, 2025
ae0502e
🌐 translate database
Jun 2, 2025
4b42fc0
🌐 subtitle
Jun 2, 2025
3abdb87
✨ add database suggestion in advanced group
Clemsazert Jun 2, 2025
0f9d487
Merge pull request #1 from Theodo-GovTech/feat-create-database-block
anaisberg Jun 2, 2025
67e29ff
✨ useGristTable hook
Clemsazert Jun 2, 2025
822e9ad
✨ connection to existing table
Clemsazert Jun 2, 2025
a2399da
♻️ null args handling in grist hooks
Clemsazert Jun 2, 2025
6f61fe0
Merge pull request #3 from Theodo-GovTech/feat-grist-connector
anaisberg Jun 2, 2025
2accc71
📦 install ag-grid
Jun 2, 2025
b5324fd
✨ display hardcoded grid
Jun 2, 2025
8d16170
✨ sort columns
Jun 2, 2025
376dad2
✨ filter columns
Jun 2, 2025
6448241
✨ edit cells
Jun 2, 2025
b81d4b7
💄 automatic height
Jun 2, 2025
5389982
✨ always show unsort icon
Jun 2, 2025
46f27b1
✨ add column button
Jun 2, 2025
09132a4
♻️ extract add column button component
Jun 2, 2025
33379c4
♻️ extract grid component
Jun 2, 2025
bd2d1b7
✨ add column to table
Jun 2, 2025
8529e19
🐛 fix add second column
Jun 2, 2025
a55efd0
🐛 close dropdown when adding a column
Jun 2, 2025
c76ac2a
🔧 add env variable
Jun 2, 2025
e00ba5a
♻️ move table data inside grid component
Jun 2, 2025
ff18d4b
✨ format grist data for grid
Jun 2, 2025
e4582a8
♻️ fix ag-grid package registry
Clemsazert Jun 3, 2025
34b760a
♻️ remove logs in datagrid component
Clemsazert Jun 3, 2025
d176099
🎨 remoev default grist api key in .env.dev
Clemsazert Jun 3, 2025
e42eee8
Merge pull request #2 from Theodo-GovTech/feat-display-grid-table-ag-…
Clemsazert Jun 3, 2025
f19b216
:sparkles:(frontend) embed-block: added url embed block
ThomasMetzger Jun 2, 2025
f903bc1
:construction:(frontend) embed-bloc: added bloc resizing
ThomasMetzger Jun 2, 2025
b7969c0
:lipstick:(frontend) embed-block: add aspect ratio constraint to resize
ThomasMetzger Jun 2, 2025
7bfd411
:bug:(frontend) embed-block: fixed drag-and-drop over iframe
ThomasMetzger Jun 2, 2025
97453b1
:globe_with_meridians:(frontend) embed-block add some fr translations
ThomasMetzger Jun 2, 2025
7ad900f
:recycle:(frontend) cleaned embed-bloc component
ThomasMetzger Jun 3, 2025
ca710a2
Merge pull request #4 from Theodo-GovTech/feat-added-embed-bloc
ThomasMetzger Jun 3, 2025
6f1c7fd
:sparkles: (frontend) Add an empty chart block type
matts2cant Jun 2, 2025
ec6bca0
:construction: claude makes a chartjs configurator
ThomasMetzger Jun 2, 2025
d7b3a95
:lipstick: (chart-block) tailwind.css -> styled-components
ThomasMetzger Jun 2, 2025
b26f406
:lipstick: (chart-block) make editor collapsable
ThomasMetzger Jun 2, 2025
b5ec1be
:lipstick: (chart-block) add collapsable sections to editor
ThomasMetzger Jun 2, 2025
f85db4d
Extract DatabaseSelector
matts2cant Jun 3, 2025
c365a18
Remove useless component
matts2cant Jun 3, 2025
93c1790
Add database selector
matts2cant Jun 3, 2025
f20d9ad
Merge pull request #6 from Theodo-GovTech/feat-chart-block
matts2cant Jun 3, 2025
6a48b3f
:sparkles: Add database selector before charts block
matts2cant Jun 3, 2025
22d3de8
✨ useGristCrudRecords hook
Clemsazert Jun 3, 2025
bb878b5
✨ create & delete columns
Clemsazert Jun 3, 2025
490a09c
✨ create column propagation in grist
Clemsazert Jun 3, 2025
ed9353c
:sparkles: Persist chart options at block level
matts2cant Jun 3, 2025
57e7c2d
✨ create doc & table hook
Clemsazert Jun 3, 2025
3969875
✨ create table when instanciating db block
Clemsazert Jun 3, 2025
6b41e8a
🎨 lint database block file
Clemsazert Jun 3, 2025
2054a06
Merge pull request #5 from Theodo-GovTech/feat-crud-records
Clemsazert Jun 3, 2025
16b37b9
✨ add new row row
Jun 3, 2025
9ea2ab0
✨ new row button
Jun 3, 2025
cd7cbbb
💄 add button style
Jun 3, 2025
a941159
♻️ create new row util
Jun 3, 2025
609b7c6
♻️ add hooks
Jun 3, 2025
bac7565
🐛 add row after creating columns
Jun 3, 2025
e159a21
♻️ extract cell renderer
Jun 3, 2025
ad51949
✨ click on add row without editing cell
Jun 3, 2025
d7b15bc
✨ add row to table
Jun 3, 2025
623ee8c
💄 remove background color
Jun 3, 2025
07f7563
Merge pull request #7 from Theodo-GovTech/feat-add-row
anaisberg Jun 3, 2025
88a4366
💄 min width on columns
Jun 3, 2025
a4003eb
🏷️ type row
Jun 3, 2025
c6b57bc
🐛 handle prev undefined case
Jun 3, 2025
c0eba3a
🏷️ type database row
Jun 3, 2025
884ef68
🐛 create new row with undefined values
Jun 3, 2025
de14755
:bug:(frontend) embed-bloc: fixed initial size is undefined
ThomasMetzger Jun 3, 2025
e46f319
Merge pull request #8 from Theodo-GovTech/fix-embed-bloc-init-size
ThomasMetzger Jun 3, 2025
12430f1
🐛 add column button outside table
Jun 3, 2025
7f25215
♻️ extract add row cal span compute
Jun 3, 2025
76c6f65
♻️ extract get columns names
Jun 3, 2025
2f17952
🐛 remove add row magic string
Jun 3, 2025
5cc9214
Merge pull request #9 from Theodo-GovTech/fix-improve-table-style
anaisberg Jun 3, 2025
8439439
🐛 make add new row span new column
Jun 3, 2025
a9f7b4e
Merge pull request #10 from Theodo-GovTech/fix-improve-table-style
anaisberg Jun 3, 2025
8893314
♻️ extract default col def
Jun 3, 2025
e0c0d6a
✨ create row in grist
Jun 3, 2025
dc86b0d
♻️ use object to type function
Jun 3, 2025
d0fd7e2
✨ hide id table
Jun 3, 2025
33d4af9
Merge pull request #11 from Theodo-GovTech/feat-push-new-row-to-grist
anaisberg Jun 3, 2025
a71b33f
✨ edit cell in grist
Jun 3, 2025
3dd3f3a
Merge pull request #12 from Theodo-GovTech/feat-edit-cell-in-grist
anaisberg Jun 3, 2025
68e9291
✨ check if grist api key exists
Jun 2, 2025
887950e
✨ open modal to inpu dans save api key
Jun 2, 2025
5c7c83d
♻️ extract api key modal component
Jun 3, 2025
0f73409
🌐 add modal translations
Jun 3, 2025
2c407e3
💄 style api key modal
Jun 3, 2025
a3f956c
🐛 adk for api at the beginning of block
Jun 3, 2025
ecfa3af
✨ use local grist api key
Jun 3, 2025
9d6a885
✨ condition
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to
- ✨(backend) allow setting session cookie age via env var #977
- ✨(backend) allow theme customnization using a configuration file #948
- ✨(frontend) Add a custom callout block to the editor #892
- ✨(frontend) Add a custom database block to the editor #892
- 🚩(frontend) version MIT only #911
- ✨(backend) integrate maleware_detection from django-lasuite #936
- 🏗️(frontend) Footer configurable #959
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/apps/impress/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
NEXT_PUBLIC_API_ORIGIN=
NEXT_PUBLIC_SW_DEACTIVATED=
NEXT_PUBLIC_PUBLISH_AS_MIT=true
NEXT_PUBLIC_PUBLISH_AS_MIT=true
2 changes: 1 addition & 1 deletion src/frontend/apps/impress/.env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
NEXT_PUBLIC_API_ORIGIN=http://localhost:8071
NEXT_PUBLIC_PUBLISH_AS_MIT=false
NEXT_PUBLIC_SW_DEACTIVATED=true
NEXT_PUBLIC_SW_DEACTIVATED=true
9 changes: 9 additions & 0 deletions src/frontend/apps/impress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
"@react-pdf/renderer": "4.3.0",
"@sentry/nextjs": "9.22.0",
"@tanstack/react-query": "5.77.1",
"ag-grid-react": "^33.3.1",
"canvg": "4.0.3",
"chart.js": "^4.4.9",
"clsx": "2.1.1",
"cmdk": "1.1.1",
"crisp-sdk-web": "1.0.25",
Expand All @@ -44,15 +46,22 @@
"lodash": "4.17.21",
"luxon": "3.6.1",
"next": "15.3.2",
"plotly": "^1.0.6",
"plotly.js": "^3.0.1",
"posthog-js": "1.246.0",
"react": "*",
"react-aria-components": "1.9.0",
"react-chart-editor": "^0.46.1",
"react-chartjs-2": "^5.3.0",
"react-dom": "*",
"react-i18next": "15.5.2",
"react-intersection-observer": "9.16.0",
"react-select": "5.10.1",
"styled-components": "6.1.18",
"use-debounce": "10.0.4",
"vega": "^6.1.2",
"vega-embed": "^7.0.2",
"vega-lite": "^6.1.0",
"y-protocols": "1.0.6",
"yjs": "*",
"zustand": "5.0.5"
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/';
17 changes: 17 additions & 0 deletions src/frontend/apps/impress/src/api/gristApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { gristApiUrl } from './config';

export const gristFetchApi = async (input: string, init?: RequestInit) => {
const apiUrl = `${gristApiUrl()}${input}`;
const apiKey = localStorage.getItem('grist_api_key');
const bearerToken = `Bearer ${apiKey}`;

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,14 +28,26 @@ import { randomColor } from '../utils';

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

import {
CalloutBlock,
DatabaseBlock,
DividerBlock,
ReactEmbedBlock,
GristChartBlock,
} from './custom-blocks';

ModuleRegistry.registerModules([AllCommunityModule]);

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

import {
getCalloutReactSlashMenuItems,
getDatabaseReactSlashMenuItems,
getDividerReactSlashMenuItems,
getEmbedReactSlashMenuItems,
getGristChartReactSlashMenuItems,
} 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 +33,15 @@ export const BlockNoteSuggestionMenu = () => {
getDefaultReactSlashMenuItems(editor),
getPageBreakReactSlashMenuItems(editor),
getCalloutReactSlashMenuItems(editor, t, basicBlocksName),
getDatabaseReactSlashMenuItems(editor, t, advancedBlocksName),
getDividerReactSlashMenuItems(editor, t, basicBlocksName),
getEmbedReactSlashMenuItems(editor, t, advancedBlocksName),
getGristChartReactSlashMenuItems(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,50 @@
import { Button } from '@openfun/cunningham-react';
import React from 'react';

import { Box, 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: (params: { documentId: string; tableId: string }) => void;
};

export const DatabaseSelector = ({
onDatabaseSelected,
}: 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 (
<Box
style={{
flexDirection: 'column',
gap: 10,
alignItems: 'center',
justifyContent: 'center',
width: '100%',
}}
>
<Button onClick={handleCreateNewDatabase}>
Créer une nouvelle base de données vide
</Button>
<Text>ou</Text>
<DatabaseSourceSelector onSourceSelected={onDatabaseSelected} />
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useState } from 'react';

import { Box, DropdownMenu, Text } from '@/components';
import { useListGristTables } from '@/features/grist';
import { Doc, useListGristDocs } from '@/features/grist/useListGristDocs';

type DatabaseSourceSelectorProps = {
onSourceSelected: (args: { documentId: number; tableId: string }) => void;
};

const TableSelector = ({
documentId,
onSourceSelected,
}: { documentId: number } & DatabaseSourceSelectorProps) => {
const { tables } = useListGristTables(documentId);
return tables ? (
<DropdownMenu
options={tables.map(({ id }) => ({
label: id,
value: id,
callback: () => onSourceSelected({ documentId, tableId: id }),
}))}
showArrow
>
<Text>Sélectionner une table Grist existante</Text>
</DropdownMenu>
) : (
<Box>
<Text>No tables available</Text>
</Box>
);
};

export const DatabaseSourceSelector = ({
onSourceSelected,
}: DatabaseSourceSelectorProps) => {
const [selectedDoc, setSelectedDoc] = useState<Doc>();
const { docs } = useListGristDocs();

return (
<Box>
<DropdownMenu
options={docs.map((doc) => ({
label: doc.name,
value: doc.id,
callback: () => setSelectedDoc(doc),
}))}
showArrow
>
<Text>{selectedDoc?.name ?? 'Sélectionner un document Grist'}</Text>
</DropdownMenu>
{selectedDoc && (
<TableSelector
documentId={selectedDoc.id}
onSourceSelected={onSourceSelected}
/>
)}
</Box>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useGristTableData } from '@/features/grist/useGristTableData';

export const DatabaseTableDisplay = ({
documentId,
tableId,
}: {
documentId: string;
tableId: string;
}) => {
const { tableData } = useGristTableData({
documentId,
tableId,
});

return JSON.stringify(tableData, null, 2);
};
Loading