Skip to content

feat(grist): open api key modal #15

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 8 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 1 addition & 2 deletions src/frontend/apps/impress/.env
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
NEXT_PUBLIC_API_ORIGIN=
NEXT_PUBLIC_SW_DEACTIVATED=
NEXT_PUBLIC_PUBLISH_AS_MIT=true
NEXT_PUBLIC_GRIST_API_KEY=
NEXT_PUBLIC_PUBLISH_AS_MIT=true
3 changes: 1 addition & 2 deletions src/frontend/apps/impress/.env.development
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
NEXT_PUBLIC_API_ORIGIN=http://localhost:8071
NEXT_PUBLIC_PUBLISH_AS_MIT=false
NEXT_PUBLIC_SW_DEACTIVATED=true
NEXT_PUBLIC_GRIST_API_KEY=
NEXT_PUBLIC_SW_DEACTIVATED=true
3 changes: 2 additions & 1 deletion src/frontend/apps/impress/src/api/gristApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ 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 apiKey = localStorage.getItem('grist_api_key');
const bearerToken = `Bearer ${apiKey}`;

const headers = {
'Content-Type': 'application/json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import { insertOrUpdateBlock } from '@blocknote/core';
import { BlockTypeSelectItem, createReactBlockSpec } from '@blocknote/react';
import { TFunction } from 'i18next';
import React from 'react';
import { useState } from 'react';

import { Box, Icon } from '@/components';

import { DocsBlockNoteEditor } from '../../types';
import { DatabaseSelector } from '../DatabaseSelector';

import { DatabaseGrid } from './DatabaseBlock/DatabaseGrid';
import { GristApiKeyModal } from './DatabaseBlock/GristApiKeyModal';

export const DatabaseBlock = createReactBlockSpec(
{
Expand All @@ -28,6 +29,28 @@ export const DatabaseBlock = createReactBlockSpec(
},
{
render: ({ block, editor }) => {
const getGristApiKey = (): string | null => {
return localStorage.getItem('grist_api_key');
};

const [gristApiKey, setGristApiKey] = useState<string | null>(
getGristApiKey,
);
const [openGristApiKeyModal, setOpenGristApiKeyModal] = useState<boolean>(
gristApiKey === null,
);

if (openGristApiKeyModal) {
return (
<GristApiKeyModal
isOpen={openGristApiKeyModal}
setOpen={setOpenGristApiKeyModal}
gristApiKey={gristApiKey}
setGristApiKey={setGristApiKey}
/>
);
}

return (
<Box
style={{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Button, Input, Modal, ModalSize } from '@openfun/cunningham-react';
import { useTranslation } from 'react-i18next';

import { Box, Text } from '@/components';
export const GristApiKeyModal = ({
isOpen,
setOpen,
gristApiKey,
setGristApiKey,
}: {
isOpen: boolean;
setOpen: (open: boolean) => void;
gristApiKey: string | null;
setGristApiKey: (key: string) => void;
}) => {
const { t: translation } = useTranslation();

const validateGristApiKey = (): void => {
if (gristApiKey !== null) {
localStorage.setItem('grist_api_key', gristApiKey);
}
setOpen(false);
};

return (
<Modal
isOpen={isOpen}
closeOnClickOutside
data-testid="doc-share-modal"
aria-label={translation('Configure Grist API Key')}
size={ModalSize.SMALL}
onClose={() => setOpen(false)}
title={<Box $align="flex-start">{translation('Grist API Key')}</Box>}
>
<Box>
<Text style={{ marginBottom: '16px' }}>
{translation(
'To sync your data with Grist, you need to provide an API Key',
)}
</Text>
<Text style={{ fontWeight: 'bold', marginBottom: '8px' }}>
{translation('How to find you API Key')}:
</Text>
<Text>1. {translation('Connect to your Grist account')}</Text>
<Text>2. {translation('Go to Profile settings > API > API Key')}</Text>
<Text style={{ marginBottom: '16px' }}>
3. {translation('Create a new API Key and copy it')}
</Text>
<Input
label={translation('Grist API Key')}
onChange={(event) => {
const value = event.target.value;
setGristApiKey(value);
}}
/>
<Button
onClick={validateGristApiKey}
style={{ alignSelf: 'end', width: 'fit-content', marginTop: '16px' }}
>
{translation('Validate API Key')}
</Button>
</Box>
</Modal>
);
};
7 changes: 7 additions & 0 deletions src/frontend/apps/impress/src/i18n/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@
"Collaborative writing, Simplified.": "L'écriture collaborative simplifiée.",
"Confirm deletion": "Confirmer la suppression",
"Connected": "Connecté",
"Connect to your Grist account": "Connectez-vous à votre compte Grist",
"Content modal to delete document": "Contenu modal pour supprimer le document",
"Content modal to explain why the user cannot edit": "Contenu modal pour expliquer pourquoi l'utilisateur ne peut pas modifier",
"Content modal to export the document": "Contenu modal pour exporter le document",
Expand All @@ -456,6 +457,7 @@
"Copy as {{format}}": "Copier en {{format}}",
"Copy link": "Copier le lien",
"Correct": "Corriger",
"Create a new API Key and copy it": "Créez une nouvelle clé et copiez-la",
"Delete": "Supprimer",
"Delete a doc": "Supprimer un doc",
"Delete document": "Supprimer le document",
Expand Down Expand Up @@ -492,9 +494,12 @@
"Failed to create the invitation for {{email}}.": "Impossible de créer l'invitation pour {{email}}.",
"Flexible export.": "Un export flexible.",
"Format": "Format",
"Grist API Key": "Clé API Grist",
"Go to Profile settings > API > API Key": "Allez dans Paramètres du compte > API > Clé API",
"Govs ❤️ Open Source.": "Gouvernements ❤️ Open Source.",
"History": "Historique",
"Home": "Accueil",
"How to find you API Key": "Comment obtenir votre clé API ",
"If a member is editing, his works can be lost.": "Si un membre est en train d'éditer, ses travaux peuvent être perdus.",
"Illustration": "Image",
"Image 401": "Image 401",
Expand Down Expand Up @@ -580,6 +585,7 @@
"The export failed": "L’exportation a échoué",
"The network configuration of your workstation or internet connection does not allow editing shared documents.": "La configuration réseau de votre poste de travail ou de votre connexion internet ne permet pas d’éditer des documents partagés.",
"This file is flagged as unsafe.": "Ce fichier est marqué comme non sûr.",
"To sync your data with Grist, you need to provide an API Key": "Pour synchroniser vos données avec Grist, vous devez fournir une clé API.",
"To facilitate the circulation of documents, Docs allows you to export your content to the most common formats: PDF, Word or OpenDocument.": "Pour faciliter la circulation des documents, Docs permet d'exporter vos contenus vers les formats les plus courants : PDF, Word ou OpenDocument.",
"Too many requests. Please wait 60 seconds.": "Trop de demandes. Veuillez patienter 60 secondes.",
"Type a name or email": "Tapez un nom ou un email",
Expand All @@ -588,6 +594,7 @@
"Untitled document": "Document sans titre",
"Updated at": "Mise à jour le",
"Use as prompt": "Utiliser comme un prompt",
"Validate API Key": "Valider la clé API",
"Version history": "Historique des versions",
"Version restored successfully": "Version restaurée avec succès",
"Visibility": "Visibilité",
Expand Down