From c3bc0d8a3edd4e7c31fe6e967249d38c785b9244 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 4 Feb 2025 14:50:53 +0100 Subject: [PATCH 01/12] chore: rename useGraphQL to useGraphQLClient --- front/src/components/ArticleCreate.jsx | 4 ++-- front/src/components/Chapter.jsx | 4 ++-- front/src/components/Corpus.jsx | 4 ++-- front/src/components/Credentials.jsx | 4 ++-- front/src/components/Register.jsx | 4 ++-- front/src/components/TagCreate.jsx | 4 ++-- front/src/components/UserInfos.jsx | 4 ++-- front/src/components/Write/Versions.jsx | 4 ++-- front/src/components/Write/Write.jsx | 4 ++-- front/src/components/Write/bibliographe/ZoteroPanel.jsx | 4 ++-- front/src/components/Write/providers/monaco/DiffEditor.jsx | 4 ++-- front/src/components/corpus/Corpus.jsx | 4 ++-- front/src/components/corpus/CorpusCreate.jsx | 4 ++-- front/src/components/corpus/CorpusItem.jsx | 4 ++-- front/src/components/corpus/CorpusMetadataModal.jsx | 4 ++-- front/src/components/corpus/CorpusSelectItem.jsx | 4 ++-- front/src/components/corpus/CorpusUpdate.jsx | 4 ++-- front/src/components/workspace/WorkspaceSelectItem.jsx | 4 ++-- front/src/components/workspace/Workspaces.jsx | 4 ++-- front/src/helpers/graphQL.js | 2 +- 20 files changed, 39 insertions(+), 39 deletions(-) diff --git a/front/src/components/ArticleCreate.jsx b/front/src/components/ArticleCreate.jsx index 69df170a0..087f62efc 100644 --- a/front/src/components/ArticleCreate.jsx +++ b/front/src/components/ArticleCreate.jsx @@ -3,7 +3,7 @@ import React, { useState, useCallback, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' -import { useGraphQL } from '../helpers/graphQL' +import { useGraphQLClient } from '../helpers/graphQL' import { createArticle } from './Articles.graphql' import Field from './Field.jsx' import { getTags } from './Tag.graphql' @@ -30,7 +30,7 @@ export default function ArticleCreate({ onSubmit, workspaceId = null }) { const { setToast } = useToasts() const [tags, setTags] = useState([]) - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const workspaces = useSelector((state) => state.activeUser.workspaces) useEffect(() => { diff --git a/front/src/components/Chapter.jsx b/front/src/components/Chapter.jsx index 97ce2d2e6..f3b0a6312 100644 --- a/front/src/components/Chapter.jsx +++ b/front/src/components/Chapter.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react' import { Link } from 'react-router-dom' import { Check, Edit3 } from 'react-feather' -import { useGraphQL } from '../helpers/graphQL' +import { useGraphQLClient } from '../helpers/graphQL' import { renameArticle as query } from './Article.graphql' import Button from './Button' import buttonStyles from './button.module.scss' @@ -25,7 +25,7 @@ export default function Chapter({ article }) { const [title, setTitle] = useState(article.title) const [tempTitle, setTempTitle] = useState(article.title) const activeUser = useCurrentUser() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const rename = async (e) => { e.preventDefault() diff --git a/front/src/components/Corpus.jsx b/front/src/components/Corpus.jsx index 97f2053b6..8124b1a4f 100644 --- a/front/src/components/Corpus.jsx +++ b/front/src/components/Corpus.jsx @@ -15,7 +15,7 @@ import Export from './Export.jsx' import Chapter from './Chapter.jsx' import etv from '../helpers/eventTargetValue.js' -import { useGraphQL } from '../helpers/graphQL.js' +import { useGraphQLClient } from '../helpers/graphQL.js' import { updateTag as query } from './Corpus.graphql' import styles from './articles.module.scss' @@ -38,7 +38,7 @@ export default function Book({ name: tagName, _id, updatedAt, articles }) { const [isRenaming, setIsRenaming] = useState(false) const { t } = useTranslation() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const renameBook = useCallback( async (event) => { diff --git a/front/src/components/Credentials.jsx b/front/src/components/Credentials.jsx index bea93b3cc..f39e1ebc3 100644 --- a/front/src/components/Credentials.jsx +++ b/front/src/components/Credentials.jsx @@ -2,7 +2,7 @@ import React, { useMemo, useState } from 'react' import { useSelector } from 'react-redux' import { useTranslation } from 'react-i18next' -import { useGraphQL } from '../helpers/graphQL' +import { useGraphQLClient } from '../helpers/graphQL' import { changePassword as query } from './Credentials.graphql' import styles from './credentials.module.scss' import fieldStyles from './field.module.scss' @@ -19,7 +19,7 @@ export default function Credentials() { const hasExistingPassword = useSelector((state) => state.activeUser.authTypes.includes('local') ) - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const { t } = useTranslation() const canSubmit = useMemo(() => { diff --git a/front/src/components/Register.jsx b/front/src/components/Register.jsx index 239efaf13..5665f336c 100644 --- a/front/src/components/Register.jsx +++ b/front/src/components/Register.jsx @@ -2,7 +2,7 @@ import React, { useCallback, useRef } from 'react' import { useTranslation } from 'react-i18next' import { Link, useHistory } from 'react-router-dom' import { useToasts } from '@geist-ui/core' -import { useGraphQL } from '../helpers/graphQL' +import { useGraphQLClient } from '../helpers/graphQL' import * as queries from './Credentials.graphql' import styles from './login.module.scss' @@ -18,7 +18,7 @@ export default function Register() { const passwordRef = useRef() const passwordConfirmationRef = useRef() const history = useHistory() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const handleFormSubmit = useCallback(async (event) => { event.preventDefault() diff --git a/front/src/components/TagCreate.jsx b/front/src/components/TagCreate.jsx index 73bec1386..1690a3ccf 100644 --- a/front/src/components/TagCreate.jsx +++ b/front/src/components/TagCreate.jsx @@ -3,7 +3,7 @@ import React, { useCallback } from 'react' import { useTranslation } from 'react-i18next' import { randomColor } from '../helpers/colors.js' -import { useGraphQL } from '../helpers/graphQL' +import { useGraphQLClient } from '../helpers/graphQL' import { useMutate } from '../hooks/graphql' import { createTag, getTags } from './Tag.graphql' @@ -20,7 +20,7 @@ export default function TagCreate() { const { state: color, bindings: colorBindings } = useInput(randomColor()) const activeUser = useCurrentUser() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const variables = { user: activeUser._id, diff --git a/front/src/components/UserInfos.jsx b/front/src/components/UserInfos.jsx index 7a1e0a1af..dc5c0fa18 100644 --- a/front/src/components/UserInfos.jsx +++ b/front/src/components/UserInfos.jsx @@ -5,7 +5,7 @@ import { useSelector, useDispatch, shallowEqual } from 'react-redux' import { CopyToClipboard } from 'react-copy-to-clipboard' import { Helmet } from 'react-helmet' -import { useGraphQL } from '../helpers/graphQL' +import { useGraphQLClient } from '../helpers/graphQL' import { updateUser } from './Credentials.graphql' import etv from '../helpers/eventTargetValue' import styles from './credentials.module.scss' @@ -17,7 +17,7 @@ import TimeAgo from './TimeAgo.jsx' export default function UserInfos() { const dispatch = useDispatch() const { t } = useTranslation() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const activeUser = useSelector((state) => state.activeUser, shallowEqual) const zoteroToken = useSelector((state) => state.activeUser.zoteroToken) const sessionToken = useSelector((state) => state.sessionToken) diff --git a/front/src/components/Write/Versions.jsx b/front/src/components/Write/Versions.jsx index c77cc0e10..036208dac 100644 --- a/front/src/components/Write/Versions.jsx +++ b/front/src/components/Write/Versions.jsx @@ -17,7 +17,7 @@ import styles from './versions.module.scss' import menuStyles from './menu.module.scss' import buttonStyles from '../button.module.scss' -import { useGraphQL } from '../../helpers/graphQL' +import { useGraphQLClient } from '../../helpers/graphQL' import { renameVersion } from './Write.graphql' import Modal from '../Modal' @@ -62,7 +62,7 @@ function Version({ articleId, compareTo, readOnly, selectedVersion, v }) { [styles.compareTo]: isComparing && articleVersionId === compareTo, }) - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const [renaming, setRenaming] = useState(false) const [title, setTitle] = useState(v.message) const versionType = v.type || 'userAction' diff --git a/front/src/components/Write/Write.jsx b/front/src/components/Write/Write.jsx index efd5c95fc..0de5bbc7c 100644 --- a/front/src/components/Write/Write.jsx +++ b/front/src/components/Write/Write.jsx @@ -21,7 +21,7 @@ import ErrorMessageCard from '../ErrorMessageCard.jsx' import styles from './write.module.scss' import { useActiveUserId } from '../../hooks/user' -import { useGraphQL } from '../../helpers/graphQL' +import { useGraphQLClient } from '../../helpers/graphQL' import { getEditableArticle as query, stopSoloSession } from './Write.graphql' import ArticleEditorMenu from './ArticleEditorMenu.jsx' @@ -59,7 +59,7 @@ export default function Write() { ) const userId = useActiveUserId() const dispatch = useDispatch() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const routeMatch = useRouteMatch() const [collaborativeSessionActive, setCollaborativeSessionActive] = useState(false) diff --git a/front/src/components/Write/bibliographe/ZoteroPanel.jsx b/front/src/components/Write/bibliographe/ZoteroPanel.jsx index b23a20159..8a9836468 100644 --- a/front/src/components/Write/bibliographe/ZoteroPanel.jsx +++ b/front/src/components/Write/bibliographe/ZoteroPanel.jsx @@ -6,7 +6,7 @@ import { fetchAllCollectionsPerLibrary, fetchBibliographyFromCollectionHref, } from '../../../helpers/zotero' -import { useGraphQL } from '../../../helpers/graphQL' +import { useGraphQLClient } from '../../../helpers/graphQL' import { useProfile } from '../../../helpers/userProfile' import { applicationConfig } from '../../../config.js' import { linkToZotero as query } from '../../Article.graphql' @@ -40,7 +40,7 @@ export default function ZoteroPanel({ const [zoteroCollections, setZoteroCollections] = useState([]) const [isSaving, setSaving] = useState(false) - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const refreshProfile = useProfile() const handleZoteroLinkChange = useCallback( diff --git a/front/src/components/Write/providers/monaco/DiffEditor.jsx b/front/src/components/Write/providers/monaco/DiffEditor.jsx index 0e6af33ad..0ba151d58 100644 --- a/front/src/components/Write/providers/monaco/DiffEditor.jsx +++ b/front/src/components/Write/providers/monaco/DiffEditor.jsx @@ -4,7 +4,7 @@ import CompareSelect from './CompareSelect' import styles from './DiffEditor.module.scss' import * as monaco from 'monaco-editor' import { DiffEditor, loader } from '@monaco-editor/react' -import { useGraphQL } from '../../../../helpers/graphQL' +import { useGraphQLClient } from '../../../../helpers/graphQL' import { compareVersion as query } from '../../Write.graphql' import { defineFlippedDiffTheme } from './support' loader.config({ monaco }) @@ -19,7 +19,7 @@ export default function MonacoDiffEditor({ onTextUpdate, }) { const [modifiedText, setModifiedText] = useState('') - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const handleEditorDidMount = useCallback((editor, monaco) => { defineFlippedDiffTheme(monaco) diff --git a/front/src/components/corpus/Corpus.jsx b/front/src/components/corpus/Corpus.jsx index 4b94b20b2..d72356b30 100644 --- a/front/src/components/corpus/Corpus.jsx +++ b/front/src/components/corpus/Corpus.jsx @@ -10,7 +10,7 @@ import { shallowEqual, useSelector } from 'react-redux' import { Helmet } from 'react-helmet' import { CurrentUserContext } from '../../contexts/CurrentUser' -import { useGraphQL } from '../../helpers/graphQL' +import { useGraphQLClient } from '../../helpers/graphQL' import { useActiveWorkspace } from '../../hooks/workspace.js' import styles from './corpus.module.scss' import CorpusCreate from './CorpusCreate.jsx' @@ -49,7 +49,7 @@ export default function Corpus() { bindings: createCorpusModalBinding, } = useModal() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const handleCreateNewCorpus = useCallback(() => { setCreateCorpusVisible(false) diff --git a/front/src/components/corpus/CorpusCreate.jsx b/front/src/components/corpus/CorpusCreate.jsx index b0f3be444..5d17eb05a 100644 --- a/front/src/components/corpus/CorpusCreate.jsx +++ b/front/src/components/corpus/CorpusCreate.jsx @@ -2,7 +2,7 @@ import { Button, Textarea, useInput, useToasts } from '@geist-ui/core' import React, { useCallback, useEffect, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' import { useActiveWorkspace } from '../../hooks/workspace.js' import Field from '../Field.jsx' @@ -18,7 +18,7 @@ export default function CorpusCreate({ onSubmit }) { const { state: title, bindings: titleBindings } = useInput('') const { state: description, bindings: descriptionBindings } = useInput('') const titleInputRef = useRef() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const activeWorkspace = useActiveWorkspace() const activeWorkspaceId = useMemo( () => activeWorkspace?._id, diff --git a/front/src/components/corpus/CorpusItem.jsx b/front/src/components/corpus/CorpusItem.jsx index 8c1c58f52..7ae6db36a 100644 --- a/front/src/components/corpus/CorpusItem.jsx +++ b/front/src/components/corpus/CorpusItem.jsx @@ -12,7 +12,7 @@ import { import { useTranslation } from 'react-i18next' import { useDispatch } from 'react-redux' import { Link } from 'react-router-dom' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' import Button from '../Button.jsx' import buttonStyles from '../button.module.scss' import Export from '../Export.jsx' @@ -47,7 +47,7 @@ export default function CorpusItem({ corpus }) { bindings: editCorpusBindings, } = useModal() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const corpusId = useMemo(() => corpus._id, [corpus]) const handleCorpusUpdated = useCallback(() => { diff --git a/front/src/components/corpus/CorpusMetadataModal.jsx b/front/src/components/corpus/CorpusMetadataModal.jsx index d8053969f..ffaf83154 100644 --- a/front/src/components/corpus/CorpusMetadataModal.jsx +++ b/front/src/components/corpus/CorpusMetadataModal.jsx @@ -5,7 +5,7 @@ import { useDispatch } from 'react-redux' import { useTranslation } from 'react-i18next' import { updateMetadata } from './Corpus.graphql' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' import MetadataForm from '../metadata/MetadataForm.jsx' import corpusMetadataSchema from '../../schemas/corpus-journal-metadata.schema.json' import corpusUiSchema from '../../schemas/corpus-journal-ui-schema.json' @@ -16,7 +16,7 @@ import Select from '../Select.jsx' export default function CorpusMetadataModal({ corpusId, initialValue }) { const { t } = useTranslation() const dispatch = useDispatch() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const [corpusMetadata, setCorpusMetadata] = useState(initialValue) const { visible: editMetadataVisible, diff --git a/front/src/components/corpus/CorpusSelectItem.jsx b/front/src/components/corpus/CorpusSelectItem.jsx index fe78c7720..c84c02d5c 100644 --- a/front/src/components/corpus/CorpusSelectItem.jsx +++ b/front/src/components/corpus/CorpusSelectItem.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types' import { removeArticleFromCorpus, addArticleToCorpus } from './Corpus.graphql' import styles from './CorpusSelectItem.module.scss' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' export default function CorpusSelectItem({ selected, @@ -13,7 +13,7 @@ export default function CorpusSelectItem({ articleId, onChange, }) { - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const toggleCorpusArticle = useCallback( async (event) => { event.preventDefault() diff --git a/front/src/components/corpus/CorpusUpdate.jsx b/front/src/components/corpus/CorpusUpdate.jsx index 46663068f..cc3cc56ad 100644 --- a/front/src/components/corpus/CorpusUpdate.jsx +++ b/front/src/components/corpus/CorpusUpdate.jsx @@ -1,7 +1,7 @@ import { Button, Textarea, useInput, useToasts } from '@geist-ui/core' import React, { useCallback, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' import Field from '../Field.jsx' @@ -17,7 +17,7 @@ export default function CorpusUpdate({ corpus, onSubmit }) { corpus.description ) const titleInputRef = useRef() - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() useEffect(() => { if (titleInputRef.current !== undefined) { diff --git a/front/src/components/workspace/WorkspaceSelectItem.jsx b/front/src/components/workspace/WorkspaceSelectItem.jsx index 54a825d9d..ac714ad6f 100644 --- a/front/src/components/workspace/WorkspaceSelectItem.jsx +++ b/front/src/components/workspace/WorkspaceSelectItem.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types' import { removeArticle, addArticle } from './Workspaces.graphql' import styles from './WorkspaceSelectItem.module.scss' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' export default function WorkspaceSelectItem({ articleId, @@ -15,7 +15,7 @@ export default function WorkspaceSelectItem({ name, onChange, }) { - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() const activeUser = useSelector((state) => state.activeUser) const toggleWorkspaceArticle = useCallback( async (event) => { diff --git a/front/src/components/workspace/Workspaces.jsx b/front/src/components/workspace/Workspaces.jsx index 4e54247e6..4a24857f0 100644 --- a/front/src/components/workspace/Workspaces.jsx +++ b/front/src/components/workspace/Workspaces.jsx @@ -10,7 +10,7 @@ import Field from '../../components/Field.jsx' import WorkspaceItem from '../../components/workspace/WorkspaceItem.jsx' import { CurrentUserContext } from '../../contexts/CurrentUser' -import { useGraphQL } from '../../helpers/graphQL.js' +import { useGraphQLClient } from '../../helpers/graphQL.js' import { useWorkspaces } from '../../hooks/workspace.js' import Loading from '../Loading.jsx' import CreateWorkspaceModal from './CreateWorkspaceModal.jsx' @@ -30,7 +30,7 @@ export default function Workspaces() { personal: true, members: [], }) - const runQuery = useGraphQL() + const runQuery = useGraphQLClient() useEffect(() => { ;(async () => { diff --git a/front/src/helpers/graphQL.js b/front/src/helpers/graphQL.js index c39b29380..d159bb639 100644 --- a/front/src/helpers/graphQL.js +++ b/front/src/helpers/graphQL.js @@ -60,7 +60,7 @@ export default async function askGraphQL( return json.data } -export function useGraphQL() { +export function useGraphQLClient() { const sessionToken = useSelector((state) => state.sessionToken) return runQuery.bind(null, { sessionToken }) } From d466ef7c1f35914c1ba9f0faede1909d5a25d53d Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 4 Feb 2025 15:02:40 +0100 Subject: [PATCH 02/12] wip! renommage --- front/src/helpers/graphQL.js | 23 ++++++++++++++++------- front/src/helpers/userProfile.js | 10 +++++----- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/front/src/helpers/graphQL.js b/front/src/helpers/graphQL.js index d159bb639..304c7ccd4 100644 --- a/front/src/helpers/graphQL.js +++ b/front/src/helpers/graphQL.js @@ -1,5 +1,5 @@ -import { useSelector } from 'react-redux' import { print } from 'graphql/language/printer' +import { useSelector } from 'react-redux' import { applicationConfig } from '../config.js' /** @@ -21,7 +21,7 @@ async function getErrorResponse(response) { } } -export default async function askGraphQL( +async function askGraphQL( payload, action = 'fetching from the server', sessionToken = null @@ -62,16 +62,25 @@ export default async function askGraphQL( export function useGraphQLClient() { const sessionToken = useSelector((state) => state.sessionToken) - return runQuery.bind(null, { sessionToken }) + return { + query: (query, variables) => runQuery({ query, variables, sessionToken }), + } } /** - * @param {string} sessionToken - * @param {DocumentNode|string} queryOrAST - * @param {{[string: key]: value}} variables + * @typedef {Object} QueryParameters + * @property {{ + * sessionToken: string, + * query: DocumentNode|string, + * variables: {[string: key]: value} + * }} + */ + +/** + * @param {QueryParameters} queryParameters * @returns {Promise} */ -export function runQuery({ sessionToken }, { query: queryOrAST, variables }) { +export function runQuery({ sessionToken, query: queryOrAST, variables }) { const query = typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) return askGraphQL({ query, variables }, null, sessionToken) diff --git a/front/src/helpers/userProfile.js b/front/src/helpers/userProfile.js index 22e3268ab..45ac1507c 100644 --- a/front/src/helpers/userProfile.js +++ b/front/src/helpers/userProfile.js @@ -1,6 +1,6 @@ -import { useDispatch, useSelector } from 'react-redux' -import { runQuery } from './graphQL.js' -import { getFullUserProfile as query } from '../components/Credentials.graphql' +import { useDispatch } from 'react-redux' +import { runQuery, useGraphQLClient } from './graphQL.js' +import { getFullUserProfile as getUserProfileQuery } from '../components/Credentials.graphql' export function getUserProfile({ sessionToken }) { return runQuery({ sessionToken }, { query }) @@ -8,10 +8,10 @@ export function getUserProfile({ sessionToken }) { export function useProfile() { const dispatch = useDispatch() - const sessionToken = useSelector((state) => state.sessionToken) + const { query } = useGraphQLClient() return function refreshProfile() { - return getUserProfile({ sessionToken }).then((response) => + return query({ query: getUserProfileQuery }).then((response) => dispatch({ type: 'PROFILE', ...response }) ) } From 082e935c23e0682f42f45c1bfb1d7fa97ea885c0 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 4 Feb 2025 16:18:19 +0100 Subject: [PATCH 03/12] =?UTF-8?q?chore:=20retourne=20un=20client=20permett?= =?UTF-8?q?ant=20d'ex=C3=A9cuter=20des=20requ=C3=AAtes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/components/ArticleCreate.jsx | 6 +-- front/src/components/Chapter.jsx | 4 +- front/src/components/Corpus.jsx | 4 +- front/src/components/Credentials.jsx | 4 +- front/src/components/Register.jsx | 4 +- front/src/components/TagCreate.jsx | 4 +- front/src/components/UserInfos.jsx | 6 +-- front/src/components/Write/Versions.jsx | 4 +- front/src/components/Write/Write.jsx | 4 +- .../Write/bibliographe/ZoteroPanel.jsx | 4 +- .../Write/providers/monaco/DiffEditor.jsx | 4 +- front/src/components/corpus/Corpus.jsx | 4 +- front/src/components/corpus/CorpusCreate.jsx | 4 +- front/src/components/corpus/CorpusItem.jsx | 4 +- .../components/corpus/CorpusMetadataModal.jsx | 6 +-- .../components/corpus/CorpusSelectItem.jsx | 4 +- front/src/components/corpus/CorpusUpdate.jsx | 4 +- .../workspace/WorkspaceSelectItem.jsx | 4 +- front/src/components/workspace/Workspaces.jsx | 4 +- front/src/helpers/graphQL.js | 41 +++++++++---------- front/src/helpers/userProfile.js | 4 +- front/src/hooks/workspace.js | 6 +-- front/src/services/ArticleService.js | 10 ++--- 23 files changed, 71 insertions(+), 72 deletions(-) diff --git a/front/src/components/ArticleCreate.jsx b/front/src/components/ArticleCreate.jsx index 087f62efc..3f3567208 100644 --- a/front/src/components/ArticleCreate.jsx +++ b/front/src/components/ArticleCreate.jsx @@ -30,7 +30,7 @@ export default function ArticleCreate({ onSubmit, workspaceId = null }) { const { setToast } = useToasts() const [tags, setTags] = useState([]) - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const workspaces = useSelector((state) => state.activeUser.workspaces) useEffect(() => { @@ -39,7 +39,7 @@ export default function ArticleCreate({ onSubmit, workspaceId = null }) { try { const { user: { tags }, - } = await runQuery({ query: getTags, variables: {} }) + } = await query({ query: getTags, variables: {} }) setTags(tags) } catch (err) { setToast({ @@ -54,7 +54,7 @@ export default function ArticleCreate({ onSubmit, workspaceId = null }) { try { event.preventDefault() const createArticleInput = fromFormData(event.target) - const { createArticle: createdArticle } = await runQuery({ + const { createArticle: createdArticle } = await query({ query: createArticle, variables: { createArticleInput }, }) diff --git a/front/src/components/Chapter.jsx b/front/src/components/Chapter.jsx index f3b0a6312..d922783fe 100644 --- a/front/src/components/Chapter.jsx +++ b/front/src/components/Chapter.jsx @@ -25,7 +25,7 @@ export default function Chapter({ article }) { const [title, setTitle] = useState(article.title) const [tempTitle, setTempTitle] = useState(article.title) const activeUser = useCurrentUser() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const rename = async (e) => { e.preventDefault() @@ -34,7 +34,7 @@ export default function Chapter({ article }) { article: articleId, title: tempTitle, } - await runQuery({ query, variables }) + await query({ query, variables }) setTitle(tempTitle) setRenaming(false) } diff --git a/front/src/components/Corpus.jsx b/front/src/components/Corpus.jsx index 8124b1a4f..cb20f068c 100644 --- a/front/src/components/Corpus.jsx +++ b/front/src/components/Corpus.jsx @@ -38,7 +38,7 @@ export default function Book({ name: tagName, _id, updatedAt, articles }) { const [isRenaming, setIsRenaming] = useState(false) const { t } = useTranslation() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const renameBook = useCallback( async (event) => { @@ -48,7 +48,7 @@ export default function Book({ name: tagName, _id, updatedAt, articles }) { tag: _id, name: tempName, } - const newTag = await runQuery({ query, variables }) + const newTag = await query({ query, variables }) setName(newTag.updateTag.name) setIsRenaming(false) }, diff --git a/front/src/components/Credentials.jsx b/front/src/components/Credentials.jsx index f39e1ebc3..1d8269c4d 100644 --- a/front/src/components/Credentials.jsx +++ b/front/src/components/Credentials.jsx @@ -19,7 +19,7 @@ export default function Credentials() { const hasExistingPassword = useSelector((state) => state.activeUser.authTypes.includes('local') ) - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const { t } = useTranslation() const canSubmit = useMemo(() => { @@ -39,7 +39,7 @@ export default function Credentials() { new: password, user: userId, } - await runQuery({ query, variables }) + await query({ query, variables }) setPassword('') setPasswordO('') setPasswordC('') diff --git a/front/src/components/Register.jsx b/front/src/components/Register.jsx index 5665f336c..e9a1bf151 100644 --- a/front/src/components/Register.jsx +++ b/front/src/components/Register.jsx @@ -18,14 +18,14 @@ export default function Register() { const passwordRef = useRef() const passwordConfirmationRef = useRef() const history = useHistory() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const handleFormSubmit = useCallback(async (event) => { event.preventDefault() const details = fromFormData(event.target) try { - await runQuery({ query: queries.createUser, variables: { details } }) + await query({ query: queries.createUser, variables: { details } }) // if no error thrown, we can navigate to / setToast({ type: 'default', diff --git a/front/src/components/TagCreate.jsx b/front/src/components/TagCreate.jsx index 1690a3ccf..10ebc1b2d 100644 --- a/front/src/components/TagCreate.jsx +++ b/front/src/components/TagCreate.jsx @@ -20,7 +20,7 @@ export default function TagCreate() { const { state: color, bindings: colorBindings } = useInput(randomColor()) const activeUser = useCurrentUser() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const variables = { user: activeUser._id, @@ -34,7 +34,7 @@ export default function TagCreate() { event.preventDefault() ;(async () => { try { - const result = await runQuery({ + const result = await query({ query: createTag, variables, }) diff --git a/front/src/components/UserInfos.jsx b/front/src/components/UserInfos.jsx index dc5c0fa18..39968c1b3 100644 --- a/front/src/components/UserInfos.jsx +++ b/front/src/components/UserInfos.jsx @@ -17,7 +17,7 @@ import TimeAgo from './TimeAgo.jsx' export default function UserInfos() { const dispatch = useDispatch() const { t } = useTranslation() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const activeUser = useSelector((state) => state.activeUser, shallowEqual) const zoteroToken = useSelector((state) => state.activeUser.zoteroToken) const sessionToken = useSelector((state) => state.sessionToken) @@ -44,7 +44,7 @@ export default function UserInfos() { event.preventDefault() const variables = { user: activeUser._id, details: { zoteroToken: null } } - await runQuery({ query: updateUser, variables }) + await query({ query: updateUser, variables }) clearZoteroToken() setIsSaving(false) }, []) @@ -57,7 +57,7 @@ export default function UserInfos() { user: activeUser._id, details: { displayName, firstName, lastName, institution }, } - const { updateUser: userDetails } = await runQuery({ + const { updateUser: userDetails } = await query({ query: updateUser, variables, }) diff --git a/front/src/components/Write/Versions.jsx b/front/src/components/Write/Versions.jsx index 036208dac..7a86b068e 100644 --- a/front/src/components/Write/Versions.jsx +++ b/front/src/components/Write/Versions.jsx @@ -62,7 +62,7 @@ function Version({ articleId, compareTo, readOnly, selectedVersion, v }) { [styles.compareTo]: isComparing && articleVersionId === compareTo, }) - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const [renaming, setRenaming] = useState(false) const [title, setTitle] = useState(v.message) const versionType = v.type || 'userAction' @@ -80,7 +80,7 @@ function Version({ articleId, compareTo, readOnly, selectedVersion, v }) { async (event) => { event.preventDefault() const variables = { version: articleVersionId, name: title } - await runQuery({ query: renameVersion, variables }) + await query({ query: renameVersion, variables }) setTitle(title) setRenaming(false) }, diff --git a/front/src/components/Write/Write.jsx b/front/src/components/Write/Write.jsx index 0de5bbc7c..7fc50296f 100644 --- a/front/src/components/Write/Write.jsx +++ b/front/src/components/Write/Write.jsx @@ -59,7 +59,7 @@ export default function Write() { ) const userId = useActiveUserId() const dispatch = useDispatch() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const routeMatch = useRouteMatch() const [collaborativeSessionActive, setCollaborativeSessionActive] = useState(false) @@ -226,7 +226,7 @@ export default function Write() { setIsLoading(true) ;(async () => { - const data = await runQuery({ query, variables }).catch((error) => { + const data = await query({ query, variables }).catch((error) => { setGraphQLError(error) return {} }) diff --git a/front/src/components/Write/bibliographe/ZoteroPanel.jsx b/front/src/components/Write/bibliographe/ZoteroPanel.jsx index 8a9836468..80bd33c7f 100644 --- a/front/src/components/Write/bibliographe/ZoteroPanel.jsx +++ b/front/src/components/Write/bibliographe/ZoteroPanel.jsx @@ -40,7 +40,7 @@ export default function ZoteroPanel({ const [zoteroCollections, setZoteroCollections] = useState([]) const [isSaving, setSaving] = useState(false) - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const refreshProfile = useProfile() const handleZoteroLinkChange = useCallback( @@ -79,7 +79,7 @@ export default function ZoteroPanel({ user: userId, article: articleId, } - await runQuery({ query, variables }) + await query({ query, variables }) } catch (err) { alert(err) } diff --git a/front/src/components/Write/providers/monaco/DiffEditor.jsx b/front/src/components/Write/providers/monaco/DiffEditor.jsx index 0ba151d58..8d5520a0e 100644 --- a/front/src/components/Write/providers/monaco/DiffEditor.jsx +++ b/front/src/components/Write/providers/monaco/DiffEditor.jsx @@ -19,7 +19,7 @@ export default function MonacoDiffEditor({ onTextUpdate, }) { const [modifiedText, setModifiedText] = useState('') - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const handleEditorDidMount = useCallback((editor, monaco) => { defineFlippedDiffTheme(monaco) @@ -38,7 +38,7 @@ export default function MonacoDiffEditor({ }, []) useEffect(() => { - runQuery({ + query({ query, variables: { article: articleId, diff --git a/front/src/components/corpus/Corpus.jsx b/front/src/components/corpus/Corpus.jsx index d72356b30..b645b9c4c 100644 --- a/front/src/components/corpus/Corpus.jsx +++ b/front/src/components/corpus/Corpus.jsx @@ -49,7 +49,7 @@ export default function Corpus() { bindings: createCorpusModalBinding, } = useModal() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const handleCreateNewCorpus = useCallback(() => { setCreateCorpusVisible(false) @@ -61,7 +61,7 @@ export default function Corpus() { const variables = activeWorkspaceId ? { filter: { workspaceId: activeWorkspaceId } } : {} - const data = await runQuery({ query: getCorpus, variables }) + const data = await query({ query: getCorpus, variables }) setCorpus(data.corpus) setIsLoading(false) } catch (err) { diff --git a/front/src/components/corpus/CorpusCreate.jsx b/front/src/components/corpus/CorpusCreate.jsx index 5d17eb05a..af7315a54 100644 --- a/front/src/components/corpus/CorpusCreate.jsx +++ b/front/src/components/corpus/CorpusCreate.jsx @@ -18,7 +18,7 @@ export default function CorpusCreate({ onSubmit }) { const { state: title, bindings: titleBindings } = useInput('') const { state: description, bindings: descriptionBindings } = useInput('') const titleInputRef = useRef() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const activeWorkspace = useActiveWorkspace() const activeWorkspaceId = useMemo( () => activeWorkspace?._id, @@ -35,7 +35,7 @@ export default function CorpusCreate({ onSubmit }) { async (event) => { try { event.preventDefault() - const response = await runQuery({ + const response = await query({ query: createCorpus, variables: { createCorpusInput: { diff --git a/front/src/components/corpus/CorpusItem.jsx b/front/src/components/corpus/CorpusItem.jsx index 7ae6db36a..ee05431e1 100644 --- a/front/src/components/corpus/CorpusItem.jsx +++ b/front/src/components/corpus/CorpusItem.jsx @@ -47,7 +47,7 @@ export default function CorpusItem({ corpus }) { bindings: editCorpusBindings, } = useModal() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const corpusId = useMemo(() => corpus._id, [corpus]) const handleCorpusUpdated = useCallback(() => { @@ -60,7 +60,7 @@ export default function CorpusItem({ corpus }) { const handleDeleteCorpus = useCallback(async () => { try { - await runQuery({ query: deleteCorpus, variables: { corpusId } }) + await query({ query: deleteCorpus, variables: { corpusId } }) dispatch({ type: 'SET_LATEST_CORPUS_DELETED', data: { corpusId } }) setToast({ text: t('corpus.delete.toastSuccess'), diff --git a/front/src/components/corpus/CorpusMetadataModal.jsx b/front/src/components/corpus/CorpusMetadataModal.jsx index ffaf83154..acc9da104 100644 --- a/front/src/components/corpus/CorpusMetadataModal.jsx +++ b/front/src/components/corpus/CorpusMetadataModal.jsx @@ -16,7 +16,7 @@ import Select from '../Select.jsx' export default function CorpusMetadataModal({ corpusId, initialValue }) { const { t } = useTranslation() const dispatch = useDispatch() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const [corpusMetadata, setCorpusMetadata] = useState(initialValue) const { visible: editMetadataVisible, @@ -25,7 +25,7 @@ export default function CorpusMetadataModal({ corpusId, initialValue }) { } = useModal() const handleUpdateMetadata = useCallback(async () => { - await runQuery({ + await query({ query: updateMetadata, variables: { corpusId: corpusId, @@ -37,7 +37,7 @@ export default function CorpusMetadataModal({ corpusId, initialValue }) { data: { corpusId, date: new Date() }, }) setEditMetadataVisible(false) - }, [corpusId, dispatch, runQuery, updateMetadata, corpusId, corpusMetadata]) + }, [corpusId, dispatch, query, updateMetadata, corpusId, corpusMetadata]) const handleMetadataUpdated = useCallback( (metadata) => { diff --git a/front/src/components/corpus/CorpusSelectItem.jsx b/front/src/components/corpus/CorpusSelectItem.jsx index c84c02d5c..df517570f 100644 --- a/front/src/components/corpus/CorpusSelectItem.jsx +++ b/front/src/components/corpus/CorpusSelectItem.jsx @@ -13,13 +13,13 @@ export default function CorpusSelectItem({ articleId, onChange, }) { - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const toggleCorpusArticle = useCallback( async (event) => { event.preventDefault() const [corpusId, checked] = [event.target.value, event.target.checked] const query = checked ? addArticleToCorpus : removeArticleFromCorpus - await runQuery({ + await query({ query, variables: { articleId: articleId, corpusId: corpusId }, }) diff --git a/front/src/components/corpus/CorpusUpdate.jsx b/front/src/components/corpus/CorpusUpdate.jsx index cc3cc56ad..220ccb058 100644 --- a/front/src/components/corpus/CorpusUpdate.jsx +++ b/front/src/components/corpus/CorpusUpdate.jsx @@ -17,7 +17,7 @@ export default function CorpusUpdate({ corpus, onSubmit }) { corpus.description ) const titleInputRef = useRef() - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() useEffect(() => { if (titleInputRef.current !== undefined) { @@ -29,7 +29,7 @@ export default function CorpusUpdate({ corpus, onSubmit }) { async (event) => { try { event.preventDefault() - await runQuery({ + await query({ query: updateCorpus, variables: { corpusId: corpus._id, diff --git a/front/src/components/workspace/WorkspaceSelectItem.jsx b/front/src/components/workspace/WorkspaceSelectItem.jsx index ac714ad6f..b8618e5c5 100644 --- a/front/src/components/workspace/WorkspaceSelectItem.jsx +++ b/front/src/components/workspace/WorkspaceSelectItem.jsx @@ -15,14 +15,14 @@ export default function WorkspaceSelectItem({ name, onChange, }) { - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() const activeUser = useSelector((state) => state.activeUser) const toggleWorkspaceArticle = useCallback( async (event) => { event.preventDefault() const [id, checked] = [event.target.value, event.target.checked] const query = checked ? addArticle : removeArticle - await runQuery({ + await query({ query, variables: { articleId: articleId, workspaceId: id }, }) diff --git a/front/src/components/workspace/Workspaces.jsx b/front/src/components/workspace/Workspaces.jsx index 4a24857f0..a0096844e 100644 --- a/front/src/components/workspace/Workspaces.jsx +++ b/front/src/components/workspace/Workspaces.jsx @@ -30,12 +30,12 @@ export default function Workspaces() { personal: true, members: [], }) - const runQuery = useGraphQLClient() + const { query } = useGraphQLClient() useEffect(() => { ;(async () => { try { - const getUserStatsResponse = await runQuery({ query: getUserStats }) + const getUserStatsResponse = await query({ query: getUserStats }) const userStats = getUserStatsResponse.user.stats setPersonalWorkspace({ _id: activeUser._id, diff --git a/front/src/helpers/graphQL.js b/front/src/helpers/graphQL.js index 304c7ccd4..0c908df13 100644 --- a/front/src/helpers/graphQL.js +++ b/front/src/helpers/graphQL.js @@ -21,11 +21,13 @@ async function getErrorResponse(response) { } } -async function askGraphQL( - payload, - action = 'fetching from the server', - sessionToken = null -) { +/** + * @param {string} sessionToken + * @param {string} query + * @param {{[string: key]: value}|undefined} variables + * @returns {Promise} + */ +async function executeRequest({ sessionToken, query, variables }) { const response = await fetch(applicationConfig.graphqlEndpoint, { method: 'POST', mode: 'cors', @@ -36,13 +38,16 @@ async function askGraphQL( // Authorization header is provided only when we have a token ...(sessionToken ? { Authorization: `Bearer ${sessionToken}` } : {}), }, - body: JSON.stringify(payload), + body: JSON.stringify({ + query, + variables, + }), }) if (!response.ok) { const errorResponse = await getErrorResponse(response) console.error( - `Something wrong happened during: ${action} => ${response.status}, ${ + `Something wrong happened during => ${response.status}, ${ response.statusText }: ${JSON.stringify(errorResponse)}` ) @@ -63,25 +68,19 @@ async function askGraphQL( export function useGraphQLClient() { const sessionToken = useSelector((state) => state.sessionToken) return { - query: (query, variables) => runQuery({ query, variables, sessionToken }), + query: (query, variables) => + executeQuery({ query, variables, sessionToken }), } } /** - * @typedef {Object} QueryParameters - * @property {{ - * sessionToken: string, - * query: DocumentNode|string, - * variables: {[string: key]: value} - * }} - */ - -/** - * @param {QueryParameters} queryParameters + * + * @param {string} sessionToken + * @param {DocumentNode|string} queryOrAST + * @param {{[string: key]: value}|undefined} variables * @returns {Promise} */ -export function runQuery({ sessionToken, query: queryOrAST, variables }) { +export function executeQuery({ sessionToken, query: queryOrAST, variables }) { const query = typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) - - return askGraphQL({ query, variables }, null, sessionToken) + return executeRequest({ query, variables, sessionToken }) } diff --git a/front/src/helpers/userProfile.js b/front/src/helpers/userProfile.js index 45ac1507c..3d0e0ea4f 100644 --- a/front/src/helpers/userProfile.js +++ b/front/src/helpers/userProfile.js @@ -1,9 +1,9 @@ import { useDispatch } from 'react-redux' -import { runQuery, useGraphQLClient } from './graphQL.js' +import { executeQuery, useGraphQLClient } from './graphQL.js' import { getFullUserProfile as getUserProfileQuery } from '../components/Credentials.graphql' export function getUserProfile({ sessionToken }) { - return runQuery({ sessionToken }, { query }) + return executeQuery({ sessionToken, query: getUserProfileQuery }) } export function useProfile() { diff --git a/front/src/hooks/workspace.js b/front/src/hooks/workspace.js index 026f40c61..cd13d8ee0 100644 --- a/front/src/hooks/workspace.js +++ b/front/src/hooks/workspace.js @@ -8,7 +8,7 @@ import { create as createMutation, leave as leaveMutation, } from '../components/workspace/Workspaces.graphql' -import { runQuery } from '../helpers/graphQL.js' +import { executeQuery } from '../helpers/graphQL.js' import useGraphQL, { useMutation, useSWRKey } from './graphql.js' export function useActiveWorkspace() { @@ -110,7 +110,7 @@ export function useWorkspaceActions() { const key = useSWRKey()({ query: getWorkspaces }) const sessionToken = useSelector((state) => state.sessionToken) const addWorkspace = async (workspace) => { - await runQuery( + await executeQuery( { sessionToken }, { query: createMutation, @@ -129,7 +129,7 @@ export function useWorkspaceActions() { } const leaveWorkspace = async (workspaceId) => { - await runQuery( + await executeQuery( { sessionToken }, { query: leaveMutation, diff --git a/front/src/services/ArticleService.js b/front/src/services/ArticleService.js index 1fdffd30d..7b34c0f5a 100644 --- a/front/src/services/ArticleService.js +++ b/front/src/services/ArticleService.js @@ -1,4 +1,4 @@ -import { runQuery } from '../helpers/graphQL.js' +import { executeQuery } from '../helpers/graphQL.js' import { updateWorkingVersion, createVersion } from './ArticleService.graphql' @@ -12,7 +12,7 @@ export default class ArticleService { async saveText(md) { const { sessionToken } = this - return runQuery( + return executeQuery( { sessionToken }, { query: updateWorkingVersion, @@ -28,7 +28,7 @@ export default class ArticleService { async saveBibliography(bib) { const { sessionToken } = this - return runQuery( + return executeQuery( { sessionToken }, { query: updateWorkingVersion, @@ -44,7 +44,7 @@ export default class ArticleService { async saveMetadata(metadata) { const { sessionToken } = this - return runQuery( + return executeQuery( { sessionToken }, { query: updateWorkingVersion, @@ -60,7 +60,7 @@ export default class ArticleService { async createNewVersion(major = false, message = '') { const { sessionToken } = this - return await runQuery( + return await executeQuery( { sessionToken }, { query: createVersion, From 09542b3ad8b39a8db4a28c3e81489a42950b2980 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 4 Feb 2025 17:52:03 +0100 Subject: [PATCH 04/12] =?UTF-8?q?wip:=20d=C3=A9but=20de=20suppression=20de?= =?UTF-8?q?=20useMutate,=20runMutation=20et=20useMutation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/components/ArticleContributors.jsx | 39 ++--------- front/src/helpers/graphQL.js | 53 ++++++++++----- front/src/hooks/contributor.js | 45 +++++++++++++ front/src/hooks/graphql.js | 69 ++++++-------------- front/src/hooks/workspace.js | 42 ++++++------ 5 files changed, 127 insertions(+), 121 deletions(-) create mode 100644 front/src/hooks/contributor.js diff --git a/front/src/components/ArticleContributors.jsx b/front/src/components/ArticleContributors.jsx index ec49b55e5..fefe9acbc 100644 --- a/front/src/components/ArticleContributors.jsx +++ b/front/src/components/ArticleContributors.jsx @@ -1,48 +1,32 @@ import React, { useCallback } from 'react' +import { useArticleContributorActions } from '../hooks/contributor.js' import { useMutate, useMutation } from '../hooks/graphql.js' import styles from './articleContributors.module.scss' import ContactSearch from './ContactSearch.jsx' -import { - addContributor, - removeContributor, -} from './ArticleContributors.graphql' + import { getArticleContributors } from './Article.graphql' import { useToasts } from '@geist-ui/core' export default function ArticleContributors({ article, contributors }) { - const mutation = useMutation() const { setToast } = useToasts() const articleId = article._id - const { mutate } = useMutate({ - query: getArticleContributors, - variables: { articleId }, + const { addContributor, removeContributor } = useArticleContributorActions({ + articleId, }) - const handleUserUpdated = useCallback( async ({ user, action }) => { const { _id: userId } = user if (action === 'select') { // add contributor try { - const response = await mutation({ - query: addContributor, - variables: { userId, articleId }, - }) + await addContributor(userId) setToast({ text: `Contributeur ${ user.displayName || user.username } ajouté à l'article.`, type: 'default', }) - await mutate( - { - article: { - contributors: response.article.addContributor.contributors, - }, - }, - { revalidate: false } - ) } catch (err) { setToast({ text: String(err), @@ -51,24 +35,13 @@ export default function ArticleContributors({ article, contributors }) { } } else if (action === 'unselect') { try { - const response = await mutation({ - query: removeContributor, - variables: { userId, articleId }, - }) + await removeContributor(userId) setToast({ text: `Contributeur ${ user.displayName || user.username } supprimé de l'article.`, type: 'warning', }) - await mutate( - { - article: { - contributors: response.article.removeContributor.contributors, - }, - }, - { revalidate: false } - ) } catch (err) { setToast({ text: String(err), diff --git a/front/src/helpers/graphQL.js b/front/src/helpers/graphQL.js index 0c908df13..9f37c9efa 100644 --- a/front/src/helpers/graphQL.js +++ b/front/src/helpers/graphQL.js @@ -22,12 +22,18 @@ async function getErrorResponse(response) { } /** - * @param {string} sessionToken - * @param {string} query - * @param {{[string: key]: value}|undefined} variables + * @param {string} query request query (as string) + * @param {{[string: key]: value}|undefined} variables request variables + * @param {string} sessionToken session token (for authentication) + * @param {'fetch'|'mutate'} [type='fetch'] request type (either fetch or mutate) * @returns {Promise} */ -async function executeRequest({ sessionToken, query, variables }) { +async function executeRequest({ + query, + variables, + sessionToken, + type = 'fetch', +}) { const response = await fetch(applicationConfig.graphqlEndpoint, { method: 'POST', mode: 'cors', @@ -47,7 +53,7 @@ async function executeRequest({ sessionToken, query, variables }) { if (!response.ok) { const errorResponse = await getErrorResponse(response) console.error( - `Something wrong happened during => ${response.status}, ${ + `Something wrong happened during ${type} => ${response.status}, ${ response.statusText }: ${JSON.stringify(errorResponse)}` ) @@ -55,14 +61,22 @@ async function executeRequest({ sessionToken, query, variables }) { errorResponse && errorResponse.errors && errorResponse.errors.length ? errorResponse.errors[0].message : 'Unexpected error!' - throw new Error(errorMessage) + const error = new Error(errorMessage) + error.messages = errorResponse?.errors ?? [errorMessage] + throw error } - const json = await response.json() - if (json.errors) { - throw new Error(json.errors[0].message) + const body = await response.json() + if (body.errors) { + const errorMessage = + type === 'fetch' + ? 'Something wrong happened while fetching data.' + : 'Something wrong happened while mutating data.' + const error = new Error(errorMessage) + error.messages = body.errors + throw error } - return json.data + return body.data } export function useGraphQLClient() { @@ -74,13 +88,20 @@ export function useGraphQLClient() { } /** - * - * @param {string} sessionToken - * @param {DocumentNode|string} queryOrAST - * @param {{[string: key]: value}|undefined} variables + * @param {Object} context query context + * @param {DocumentNode|string} context.query request query (as AST or string) + * @param {{[string: key]: any}|undefined} context.variables request variables + * @param {string} context.sessionToken session token (for authentication) + * @param {'fetch'|'mutate'} [context.type='fetch'] request type (either fetch or mutate) * @returns {Promise} + * @throws Error if something went wrong */ -export function executeQuery({ sessionToken, query: queryOrAST, variables }) { +export function executeQuery({ + query: queryOrAST, + variables, + sessionToken, + type = 'fetch', +}) { const query = typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) - return executeRequest({ query, variables, sessionToken }) + return executeRequest({ query, variables, sessionToken, type }) } diff --git a/front/src/hooks/contributor.js b/front/src/hooks/contributor.js new file mode 100644 index 000000000..87ac0f30d --- /dev/null +++ b/front/src/hooks/contributor.js @@ -0,0 +1,45 @@ +import { useSelector } from 'react-redux' +import { useSWRConfig } from 'swr' +import { executeQuery } from '../helpers/graphQL.js' +import { + addContributor as addContributorQuery, + removeContributor as removeContributorQuery, +} from '../components/ArticleContributors.graphql' +import { getArticleContributors } from '../components/Article.graphql' +import { useSWRKey } from './graphql.js' + +export function useArticleContributorActions({ articleId }) { + const { mutate } = useSWRConfig() + const key = useSWRKey()({ query: getArticleContributors }) + const sessionToken = useSelector((state) => state.sessionToken) + const addContributor = async (contributorId) => { + const response = await executeQuery({ + sessionToken, + query: addContributorQuery, + variables: { userId: contributorId, articleId }, + }) + await mutate(key, async (_) => ({ + article: { + contributors: response.article.addContributor.contributors, + }, + })) + } + + const removeContributor = async (contributorId) => { + const response = await executeQuery({ + sessionToken, + query: removeContributorQuery, + variables: { userId: contributorId, articleId }, + }) + await mutate(key, async (_) => ({ + article: { + contributors: response.article.removeContributor.contributors, + }, + })) + } + + return { + addContributor, + removeContributor, + } +} diff --git a/front/src/hooks/graphql.js b/front/src/hooks/graphql.js index 1030005e5..3be78bee9 100644 --- a/front/src/hooks/graphql.js +++ b/front/src/hooks/graphql.js @@ -1,44 +1,15 @@ -import useSWR, { preload } from 'swr' -import { useSelector } from 'react-redux' import { print } from 'graphql/language/printer' -import { applicationConfig } from '../config.js' - -async function fetcher({ query, variables, sessionToken }) { - return request({ query, variables, sessionToken }) -} +import { useSelector } from 'react-redux' +import useSWR from 'swr' +import { executeQuery } from '../helpers/graphQL.js' -async function request({ query, variables, sessionToken, type = 'fetch' }) { - const errorMessage = - type === 'fetch' - ? 'Something wrong happened while fetching data.' - : 'Something wrong happened while mutating data.' - const response = await fetch(applicationConfig.graphqlEndpoint, { - method: 'POST', - mode: 'cors', - credentials: 'omit', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - // Authorization header is provided only when we have a token - ...(sessionToken ? { Authorization: `Bearer ${sessionToken}` } : {}), - }, - body: JSON.stringify({ query, variables }), +async function fetch({ query, variables, sessionToken }) { + return executeQuery({ + query, + variables, + sessionToken, + type: 'fetch', }) - - if (response.ok) { - const body = await response.json() - if (body.errors) { - const error = new Error(errorMessage) - error.messages = body.errors - throw error - } - return body.data - } - - const error = new Error(errorMessage) - error.info = await response.json().errors - error.status = response.status - throw error } /** @@ -53,22 +24,28 @@ export default function useGraphQL({ query: queryOrAST, variables }, options) { const sessionToken = useSelector((state) => state.sessionToken) const query = typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) - return useSWR({ query, variables, sessionToken }, fetcher, options) + return useSWR({ query, variables, sessionToken }, fetch, options) } +/** + * @deprecated + */ export function useMutation() { const sessionToken = useSelector((state) => state.sessionToken) return runMutation.bind(null, { sessionToken }) } +/** + * @deprecated + */ export function runMutation( { sessionToken }, { query: queryOrAST, variables } ) { const query = typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) - return request({ + return executeQuery({ query, variables, sessionToken, @@ -76,6 +53,9 @@ export function runMutation( }) } +/** + * @deprecated + */ export function useMutate({ query: queryOrAST, variables }) { const sessionToken = useSelector((state) => state.sessionToken) const query = typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) @@ -91,12 +71,3 @@ export function useSWRKey() { return { query, variables, sessionToken } } } - -export function usePreload() { - const sessionToken = useSelector((state) => state.sessionToken) - return ({ query: queryOrAST, variables }) => { - const query = - typeof queryOrAST === 'string' ? queryOrAST : print(queryOrAST) - return preload({ query, variables, sessionToken }, fetcher) - } -} diff --git a/front/src/hooks/workspace.js b/front/src/hooks/workspace.js index cd13d8ee0..5dc62c67f 100644 --- a/front/src/hooks/workspace.js +++ b/front/src/hooks/workspace.js @@ -1,12 +1,12 @@ import { useSelector } from 'react-redux' import { useSWRConfig } from 'swr' import { + create as createMutation, getWorkspaceMembers, getWorkspaces, inviteMember as inviteMemberMutation, - removeMember as removeMemberMutation, - create as createMutation, leave as leaveMutation, + removeMember as removeMemberMutation, } from '../components/workspace/Workspaces.graphql' import { executeQuery } from '../helpers/graphQL.js' import useGraphQL, { useMutation, useSWRKey } from './graphql.js' @@ -110,34 +110,30 @@ export function useWorkspaceActions() { const key = useSWRKey()({ query: getWorkspaces }) const sessionToken = useSelector((state) => state.sessionToken) const addWorkspace = async (workspace) => { - await executeQuery( - { sessionToken }, - { - query: createMutation, - variables: { - data: { - color: workspace.color, - description: workspace.description, - name: workspace.name, - }, + await executeQuery({ + sessionToken, + query: createMutation, + variables: { + data: { + color: workspace.color, + description: workspace.description, + name: workspace.name, }, - } - ) + }, + }) await mutate(key, async (data) => ({ workspaces: [workspace, ...data.workspaces], })) } const leaveWorkspace = async (workspaceId) => { - await executeQuery( - { sessionToken }, - { - query: leaveMutation, - variables: { - workspaceId, - }, - } - ) + await executeQuery({ + sessionToken, + query: leaveMutation, + variables: { + workspaceId, + }, + }) await mutate( key, async (data) => ({ From 5bd2867ccd580b7e7d691c84e6b58c17573a56ac Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 11 Feb 2025 12:08:09 +0100 Subject: [PATCH 05/12] fix: passe les arguments en tant qu'objet --- front/src/components/Credentials.jsx | 4 ++-- front/src/helpers/graphQL.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/front/src/components/Credentials.jsx b/front/src/components/Credentials.jsx index 1d8269c4d..199d23358 100644 --- a/front/src/components/Credentials.jsx +++ b/front/src/components/Credentials.jsx @@ -3,7 +3,7 @@ import { useSelector } from 'react-redux' import { useTranslation } from 'react-i18next' import { useGraphQLClient } from '../helpers/graphQL' -import { changePassword as query } from './Credentials.graphql' +import { changePassword as changePasswordQuery } from './Credentials.graphql' import styles from './credentials.module.scss' import fieldStyles from './field.module.scss' import Button from './Button' @@ -39,7 +39,7 @@ export default function Credentials() { new: password, user: userId, } - await query({ query, variables }) + await query({ query: changePasswordQuery, variables }) setPassword('') setPasswordO('') setPasswordC('') diff --git a/front/src/helpers/graphQL.js b/front/src/helpers/graphQL.js index 9f37c9efa..bd7c449d8 100644 --- a/front/src/helpers/graphQL.js +++ b/front/src/helpers/graphQL.js @@ -82,7 +82,7 @@ async function executeRequest({ export function useGraphQLClient() { const sessionToken = useSelector((state) => state.sessionToken) return { - query: (query, variables) => + query: ({query, variables}) => executeQuery({ query, variables, sessionToken }), } } From b57fb29b9c4d242603c24926cf07dddbd0abc538 Mon Sep 17 00:00:00 2001 From: Thomas Parisot Date: Wed, 26 Feb 2025 12:34:05 +0100 Subject: [PATCH 06/12] chore: utilise des traductions pour les toasts d'ajout d'article MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supprime des imports inutilisés. --- front/src/components/ArticleContributors.jsx | 18 +++++++++--------- front/src/locales/en/translation.json | 2 ++ front/src/locales/fr/translation.json | 2 ++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/front/src/components/ArticleContributors.jsx b/front/src/components/ArticleContributors.jsx index fefe9acbc..502d5d591 100644 --- a/front/src/components/ArticleContributors.jsx +++ b/front/src/components/ArticleContributors.jsx @@ -1,15 +1,15 @@ import React, { useCallback } from 'react' import { useArticleContributorActions } from '../hooks/contributor.js' -import { useMutate, useMutation } from '../hooks/graphql.js' import styles from './articleContributors.module.scss' import ContactSearch from './ContactSearch.jsx' -import { getArticleContributors } from './Article.graphql' import { useToasts } from '@geist-ui/core' +import { useTranslation } from 'react-i18next' export default function ArticleContributors({ article, contributors }) { const { setToast } = useToasts() + const { t } = useTranslation() const articleId = article._id const { addContributor, removeContributor } = useArticleContributorActions({ articleId, @@ -22,9 +22,9 @@ export default function ArticleContributors({ article, contributors }) { try { await addContributor(userId) setToast({ - text: `Contributeur ${ - user.displayName || user.username - } ajouté à l'article.`, + text: t('article.contributors.added', { + name: user.displayName || user.username, + }), type: 'default', }) } catch (err) { @@ -37,10 +37,10 @@ export default function ArticleContributors({ article, contributors }) { try { await removeContributor(userId) setToast({ - text: `Contributeur ${ - user.displayName || user.username - } supprimé de l'article.`, - type: 'warning', + text: t('article.contributors.removed', { + name: user.displayName || user.username, + }), + type: 'default', }) } catch (err) { setToast({ diff --git a/front/src/locales/en/translation.json b/front/src/locales/en/translation.json index 2973957a4..bae2bc82b 100644 --- a/front/src/locales/en/translation.json +++ b/front/src/locales/en/translation.json @@ -54,6 +54,8 @@ "time.fewSecondsAgo": "a few seconds ago", "search.placeholder": "Search", "articles.page.title": "Articles - {{ workspace }}", + "article.contributors.added": "{{ name }} is now a contributor.", + "article.contributors.removed": "{{ name }} has been removed from contributors.", "article.count_zero": "no article", "article.count_one": "{{ count }} article", "article.count_other": "{{ count }} articles", diff --git a/front/src/locales/fr/translation.json b/front/src/locales/fr/translation.json index aad08bce1..43893436b 100644 --- a/front/src/locales/fr/translation.json +++ b/front/src/locales/fr/translation.json @@ -54,6 +54,8 @@ "time.fewSecondsAgo": "à lʼinstant", "search.placeholder": "Recherche", "articles.page.title": "Articles - {{ workspace }}", + "article.contributors.added": "{{ name }} peut désormais contribuer à cet article.", + "article.contributors.removed": "{{ name }} a été retiré·e des contributeur·ices.", "article.count_zero": "aucun article", "article.count_one": "{{ count }} article", "article.count_other": "{{ count }} articles", From 3a448e4352db9491150ccfc083806b576421202c Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 26 Feb 2025 12:54:57 +0100 Subject: [PATCH 07/12] =?UTF-8?q?fix:=20corrige=20l'=C3=A9crasement=20de?= =?UTF-8?q?=20variables=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/components/corpus/CorpusSelectItem.jsx | 6 ++++-- front/src/components/workspace/WorkspaceSelectItem.jsx | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/front/src/components/corpus/CorpusSelectItem.jsx b/front/src/components/corpus/CorpusSelectItem.jsx index df517570f..3c41f6e65 100644 --- a/front/src/components/corpus/CorpusSelectItem.jsx +++ b/front/src/components/corpus/CorpusSelectItem.jsx @@ -18,9 +18,11 @@ export default function CorpusSelectItem({ async (event) => { event.preventDefault() const [corpusId, checked] = [event.target.value, event.target.checked] - const query = checked ? addArticleToCorpus : removeArticleFromCorpus + const graphqlQuery = checked + ? addArticleToCorpus + : removeArticleFromCorpus await query({ - query, + query: graphqlQuery, variables: { articleId: articleId, corpusId: corpusId }, }) onChange({ corpusId }) diff --git a/front/src/components/workspace/WorkspaceSelectItem.jsx b/front/src/components/workspace/WorkspaceSelectItem.jsx index b8618e5c5..4a12f4691 100644 --- a/front/src/components/workspace/WorkspaceSelectItem.jsx +++ b/front/src/components/workspace/WorkspaceSelectItem.jsx @@ -21,9 +21,9 @@ export default function WorkspaceSelectItem({ async (event) => { event.preventDefault() const [id, checked] = [event.target.value, event.target.checked] - const query = checked ? addArticle : removeArticle + const graphqlQuery = checked ? addArticle : removeArticle await query({ - query, + query: graphqlQuery, variables: { articleId: articleId, workspaceId: id }, }) onChange({ workspaceId: id }) From 9b18be16731332c8cca4ae04bb028e9236b9ddf2 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 26 Feb 2025 12:56:34 +0100 Subject: [PATCH 08/12] =?UTF-8?q?fix:=20renomme=20la=20variable=20pour=20?= =?UTF-8?q?=C3=A9viter=20d'=C3=A9craser=20la=20fonction=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/components/Chapter.jsx | 2 +- front/src/components/Write/Write.jsx | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/front/src/components/Chapter.jsx b/front/src/components/Chapter.jsx index d922783fe..a15fbe052 100644 --- a/front/src/components/Chapter.jsx +++ b/front/src/components/Chapter.jsx @@ -66,7 +66,7 @@ export default function Chapter({ article }) {

)} - {renaming && renaming && ( + {renaming && (
rename(e)} diff --git a/front/src/components/Write/Write.jsx b/front/src/components/Write/Write.jsx index 7fc50296f..2ebf0a70b 100644 --- a/front/src/components/Write/Write.jsx +++ b/front/src/components/Write/Write.jsx @@ -22,7 +22,10 @@ import styles from './write.module.scss' import { useActiveUserId } from '../../hooks/user' import { useGraphQLClient } from '../../helpers/graphQL' -import { getEditableArticle as query, stopSoloSession } from './Write.graphql' +import { + getEditableArticle as getEditableArticleQuery, + stopSoloSession, +} from './Write.graphql' import ArticleEditorMenu from './ArticleEditorMenu.jsx' import ArticleEditorMetadata from './ArticleEditorMetadata.jsx' @@ -226,7 +229,10 @@ export default function Write() { setIsLoading(true) ;(async () => { - const data = await query({ query, variables }).catch((error) => { + const data = await query({ + query: getEditableArticleQuery, + variables, + }).catch((error) => { setGraphQLError(error) return {} }) From 48cbd99863b5b1d668d5b80a27ccc7ef389066eb Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 26 Feb 2025 13:00:06 +0100 Subject: [PATCH 09/12] fix: distingue la variable query de la fonction query --- front/src/components/ArticleCreate.jsx | 2 +- front/src/components/Chapter.jsx | 98 ----------- front/src/components/Corpus.jsx | 152 ------------------ front/src/components/Footer.jsx | 1 - .../Write/bibliographe/ZoteroPanel.jsx | 4 +- .../Write/providers/monaco/DiffEditor.jsx | 4 +- .../components/workspace/WorkspaceItem.jsx | 2 +- 7 files changed, 6 insertions(+), 257 deletions(-) delete mode 100644 front/src/components/Chapter.jsx delete mode 100644 front/src/components/Corpus.jsx diff --git a/front/src/components/ArticleCreate.jsx b/front/src/components/ArticleCreate.jsx index 3f3567208..0eec87b0d 100644 --- a/front/src/components/ArticleCreate.jsx +++ b/front/src/components/ArticleCreate.jsx @@ -1,5 +1,5 @@ import { useToasts } from '@geist-ui/core' -import React, { useState, useCallback, useEffect, useRef } from 'react' +import React, { useState, useCallback, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { useSelector } from 'react-redux' diff --git a/front/src/components/Chapter.jsx b/front/src/components/Chapter.jsx deleted file mode 100644 index a15fbe052..000000000 --- a/front/src/components/Chapter.jsx +++ /dev/null @@ -1,98 +0,0 @@ -import React, { useState } from 'react' -import { Link } from 'react-router-dom' -import { Check, Edit3 } from 'react-feather' - -import { useGraphQLClient } from '../helpers/graphQL' -import { renameArticle as query } from './Article.graphql' -import Button from './Button' -import buttonStyles from './button.module.scss' -import styles from './chapter.module.scss' -import fieldStyles from './field.module.scss' -import Field from './Field' -import { useCurrentUser } from '../contexts/CurrentUser' -import clsx from 'clsx' - -export default function Chapter({ article }) { - const articleId = article._id - const latestVersion = article.versions && article.versions[0] - const latestArticleVersion = latestVersion && { - message: latestVersion.message, - major: latestVersion.version, - minor: latestVersion.revision, - } - - const [renaming, setRenaming] = useState(false) - const [title, setTitle] = useState(article.title) - const [tempTitle, setTempTitle] = useState(article.title) - const activeUser = useCurrentUser() - const { query } = useGraphQLClient() - - const rename = async (e) => { - e.preventDefault() - const variables = { - user: activeUser._id, - article: articleId, - title: tempTitle, - } - await query({ query, variables }) - setTitle(tempTitle) - setRenaming(false) - } - const latestArticleVersionLabel = latestArticleVersion - ? latestArticleVersion.message || 'No label' - : '' - const latestVersionVersionNumber = latestArticleVersion - ? `v${latestArticleVersion.major}.${latestArticleVersion.minor}` - : 'latest' - const currentArticleVersionTitle = ` (${[ - latestArticleVersionLabel, - latestVersionVersionNumber, - ] - .filter((item) => item) - .join(' ')})` - return ( - <> - {!renaming && ( -

- - {title} - {currentArticleVersionTitle} - - -

- )} - {renaming && ( - rename(e)} - > - setTempTitle(e.target.value)} - placeholder="Book Title" - /> - - - - )} - - ) -} diff --git a/front/src/components/Corpus.jsx b/front/src/components/Corpus.jsx deleted file mode 100644 index cb20f068c..000000000 --- a/front/src/components/Corpus.jsx +++ /dev/null @@ -1,152 +0,0 @@ -import React, { useCallback, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { Link } from 'react-router-dom' -import { - Check, - ChevronDown, - ChevronRight, - Edit3, - MessageSquare, - Printer, -} from 'react-feather' - -import Modal from './Modal.jsx' -import Export from './Export.jsx' -import Chapter from './Chapter.jsx' - -import etv from '../helpers/eventTargetValue.js' -import { useGraphQLClient } from '../helpers/graphQL.js' -import { updateTag as query } from './Corpus.graphql' - -import styles from './articles.module.scss' -import buttonStyles from './button.module.scss' -import fieldStyles from './field.module.scss' - -import Button from './Button.jsx' -import Field from './Field.jsx' -import { useCurrentUser } from '../contexts/CurrentUser.js' -import clsx from 'clsx' -import TimeAgo from './TimeAgo.jsx' - -export default function Book({ name: tagName, _id, updatedAt, articles }) { - const activeUser = useCurrentUser() - - const [expanded, setExpanded] = useState(false) - const [exporting, setExporting] = useState(false) - const [tempName, setTempName] = useState(tagName) - const [name, setName] = useState(tagName) - const [isRenaming, setIsRenaming] = useState(false) - const { t } = useTranslation() - - const { query } = useGraphQLClient() - - const renameBook = useCallback( - async (event) => { - event.preventDefault() - const variables = { - user: activeUser._id, - tag: _id, - name: tempName, - } - const newTag = await query({ query, variables }) - setName(newTag.updateTag.name) - setIsRenaming(false) - }, - [tempName] - ) - - return ( -
- {exporting && ( - setExporting(false)}> - - - )} - - {!isRenaming && ( -

setExpanded(!expanded)}> - {expanded ? : } - {name} - -

- )} - {isRenaming && ( -
- setTempName(etv(e))} - placeholder="Article Title" - /> - - - - )} - - - -
- {expanded && ( - <> -

Chapters

-
    - {articles.map((article) => { - return ( -
  • - -
  • - ) - })} -
- - )} -
-
- ) -} diff --git a/front/src/components/Footer.jsx b/front/src/components/Footer.jsx index 0693d6b67..657d577dd 100644 --- a/front/src/components/Footer.jsx +++ b/front/src/components/Footer.jsx @@ -4,7 +4,6 @@ import { Switch, Route, Link } from 'react-router-dom' import { useTranslation } from 'react-i18next' import styles from './header.module.scss' -import { HelpCircle } from 'react-feather' function Footer() { const dispatch = useDispatch() diff --git a/front/src/components/Write/bibliographe/ZoteroPanel.jsx b/front/src/components/Write/bibliographe/ZoteroPanel.jsx index 80bd33c7f..5de52a00b 100644 --- a/front/src/components/Write/bibliographe/ZoteroPanel.jsx +++ b/front/src/components/Write/bibliographe/ZoteroPanel.jsx @@ -9,7 +9,7 @@ import { import { useGraphQLClient } from '../../../helpers/graphQL' import { useProfile } from '../../../helpers/userProfile' import { applicationConfig } from '../../../config.js' -import { linkToZotero as query } from '../../Article.graphql' +import { linkToZotero as linkToZoteroQuery } from '../../Article.graphql' import Button from '../../Button' import Field from '../../Field' @@ -79,7 +79,7 @@ export default function ZoteroPanel({ user: userId, article: articleId, } - await query({ query, variables }) + await query({ query: linkToZoteroQuery, variables }) } catch (err) { alert(err) } diff --git a/front/src/components/Write/providers/monaco/DiffEditor.jsx b/front/src/components/Write/providers/monaco/DiffEditor.jsx index 8d5520a0e..ee98b12d1 100644 --- a/front/src/components/Write/providers/monaco/DiffEditor.jsx +++ b/front/src/components/Write/providers/monaco/DiffEditor.jsx @@ -5,7 +5,7 @@ import styles from './DiffEditor.module.scss' import * as monaco from 'monaco-editor' import { DiffEditor, loader } from '@monaco-editor/react' import { useGraphQLClient } from '../../../../helpers/graphQL' -import { compareVersion as query } from '../../Write.graphql' +import { compareVersion as compareVersionQuery } from '../../Write.graphql' import { defineFlippedDiffTheme } from './support' loader.config({ monaco }) @@ -39,7 +39,7 @@ export default function MonacoDiffEditor({ useEffect(() => { query({ - query, + query: compareVersionQuery, variables: { article: articleId, to: compareTo ?? 'working-copy', diff --git a/front/src/components/workspace/WorkspaceItem.jsx b/front/src/components/workspace/WorkspaceItem.jsx index 61fe23784..0f7ae0e54 100644 --- a/front/src/components/workspace/WorkspaceItem.jsx +++ b/front/src/components/workspace/WorkspaceItem.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react' +import React from 'react' import { Slash, Users } from 'react-feather' import { Button, useModal } from '@geist-ui/core' import { useTranslation } from 'react-i18next' From 0ac4f4bace19c71b3886db9f39f7b8547d6da01b Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 26 Feb 2025 13:12:15 +0100 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20corrige=20la=20cl=C3=A9=20SWR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/hooks/contributor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/front/src/hooks/contributor.js b/front/src/hooks/contributor.js index 87ac0f30d..2ccf80562 100644 --- a/front/src/hooks/contributor.js +++ b/front/src/hooks/contributor.js @@ -10,7 +10,10 @@ import { useSWRKey } from './graphql.js' export function useArticleContributorActions({ articleId }) { const { mutate } = useSWRConfig() - const key = useSWRKey()({ query: getArticleContributors }) + const key = useSWRKey()({ + query: getArticleContributors, + variables: { articleId }, + }) const sessionToken = useSelector((state) => state.sessionToken) const addContributor = async (contributorId) => { const response = await executeQuery({ From bf843cdd06df8cea1d349ab13d813e5431df638a Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 26 Feb 2025 14:48:31 +0100 Subject: [PATCH 11/12] fix: ajuste la jsdoc --- front/src/helpers/graphQL.js | 17 +++++++++-------- front/src/hooks/contributor.js | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/front/src/helpers/graphQL.js b/front/src/helpers/graphQL.js index bd7c449d8..f063d0635 100644 --- a/front/src/helpers/graphQL.js +++ b/front/src/helpers/graphQL.js @@ -22,10 +22,11 @@ async function getErrorResponse(response) { } /** - * @param {string} query request query (as string) - * @param {{[string: key]: value}|undefined} variables request variables - * @param {string} sessionToken session token (for authentication) - * @param {'fetch'|'mutate'} [type='fetch'] request type (either fetch or mutate) + * @param {object} config request configuration + * @param {string} config.query request query (as string) + * @param {{[string: key]: value}|undefined} config.variables request variables + * @param {string} config.sessionToken session token (for authentication) + * @param {'fetch'|'mutate'} config.type request type (either fetch or mutate) * @returns {Promise} */ async function executeRequest({ @@ -82,18 +83,18 @@ async function executeRequest({ export function useGraphQLClient() { const sessionToken = useSelector((state) => state.sessionToken) return { - query: ({query, variables}) => + query: ({ query, variables }) => executeQuery({ query, variables, sessionToken }), } } /** - * @param {Object} context query context + * @param {object} context query context * @param {DocumentNode|string} context.query request query (as AST or string) * @param {{[string: key]: any}|undefined} context.variables request variables * @param {string} context.sessionToken session token (for authentication) - * @param {'fetch'|'mutate'} [context.type='fetch'] request type (either fetch or mutate) - * @returns {Promise} + * @param {'fetch'|'mutate'} context.type request type (either fetch or mutate) + * @returns {Promise} * @throws Error if something went wrong */ export function executeQuery({ diff --git a/front/src/hooks/contributor.js b/front/src/hooks/contributor.js index 2ccf80562..4c0712ab4 100644 --- a/front/src/hooks/contributor.js +++ b/front/src/hooks/contributor.js @@ -21,7 +21,7 @@ export function useArticleContributorActions({ articleId }) { query: addContributorQuery, variables: { userId: contributorId, articleId }, }) - await mutate(key, async (_) => ({ + await mutate(key, async () => ({ article: { contributors: response.article.addContributor.contributors, }, @@ -34,7 +34,7 @@ export function useArticleContributorActions({ articleId }) { query: removeContributorQuery, variables: { userId: contributorId, articleId }, }) - await mutate(key, async (_) => ({ + await mutate(key, async () => ({ article: { contributors: response.article.removeContributor.contributors, }, From 33614ea910a54640544cf33ee774c9915c04bffb Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 26 Feb 2025 15:59:20 +0100 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20passe=20les=20arguments=20comme=20?= =?UTF-8?q?objet=20d=C3=A9structur=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/src/services/ArticleService.js | 86 +++++++++++++--------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/front/src/services/ArticleService.js b/front/src/services/ArticleService.js index 7b34c0f5a..53eb57c66 100644 --- a/front/src/services/ArticleService.js +++ b/front/src/services/ArticleService.js @@ -12,65 +12,61 @@ export default class ArticleService { async saveText(md) { const { sessionToken } = this - return executeQuery( - { sessionToken }, - { - query: updateWorkingVersion, - variables: { - userId: this.userId, - articleId: this.articleId, - content: { md }, - }, - } - ) + return executeQuery({ + sessionToken, + query: updateWorkingVersion, + variables: { + userId: this.userId, + articleId: this.articleId, + content: { md }, + }, + type: 'mutate', + }) } async saveBibliography(bib) { const { sessionToken } = this - return executeQuery( - { sessionToken }, - { - query: updateWorkingVersion, - variables: { - userId: this.userId, - articleId: this.articleId, - content: { bib }, - }, - } - ) + return executeQuery({ + sessionToken, + query: updateWorkingVersion, + variables: { + userId: this.userId, + articleId: this.articleId, + content: { bib }, + }, + type: 'mutate', + }) } async saveMetadata(metadata) { const { sessionToken } = this - return executeQuery( - { sessionToken }, - { - query: updateWorkingVersion, - variables: { - userId: this.userId, - articleId: this.articleId, - content: { metadata }, - }, - } - ) + return executeQuery({ + sessionToken, + query: updateWorkingVersion, + variables: { + userId: this.userId, + articleId: this.articleId, + content: { metadata }, + }, + type: 'mutate', + }) } async createNewVersion(major = false, message = '') { const { sessionToken } = this - return await executeQuery( - { sessionToken }, - { - query: createVersion, - variables: { - userId: this.userId, - articleId: this.articleId, - major, - message, - }, - } - ) + return await executeQuery({ + sessionToken, + query: createVersion, + variables: { + userId: this.userId, + articleId: this.articleId, + major, + message, + }, + type: 'mutate', + }) } }