From feb87b5717752706c292bc1b4026752af6c2b6d5 Mon Sep 17 00:00:00 2001 From: ragxorus Date: Tue, 9 Jun 2026 18:00:17 +0200 Subject: [PATCH 1/3] SCENARIO: Create a document as a glose of multiple documents (see#404). Co-authored-by: Flavien VIDAL --- frontend/scenarios/create_document.feature | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontend/scenarios/create_document.feature b/frontend/scenarios/create_document.feature index 4ec68252..26a635d3 100644 --- a/frontend/scenarios/create_document.feature +++ b/frontend/scenarios/create_document.feature @@ -107,3 +107,11 @@ Scénario: en gardant certaines des métadonnées du document source """ dc_isPartOf: Archéologie préventive (IF14) """ +Scénario: En tant qu'hexaple par sélection de plusieurs documents + Soit la liste des documents affichée + Et ayant sélectionné les documents "Rencontrons un président (Christophe Lejeune)" et "Note rire Buster Keaton (Antoine-Valentin Charpentier)" + Et une session active avec mon compte + Quand j'essaie de créer une glose de type "Quotation" à partir de la bibliothèque + Et je me focalise sur "…" + Alors la colonne 1 contient "Origine, d'où ?" + Et la colonne 2 contient "Ce qui m'a fait rire :" From 4b21e10b94b13f9e101ad2b54d74a89a716eb7f6 Mon Sep 17 00:00:00 2001 From: Mathys-Lemort <113189272+Mathys-Lemort@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:04:40 +0200 Subject: [PATCH 2/3] TEST: Create a document as a glose of multiple documents (see#404). Co-authored-by: Flavien VIDAL Co-authored-by: Arthur DE PETIGNY <151913121+ragxorus@users.noreply.github.com> --- frontend/tests/context.js | 11 +++++++++++ frontend/tests/event.js | 4 ++++ frontend/tests/outcome.js | 6 ++++++ 3 files changed, 21 insertions(+) diff --git a/frontend/tests/context.js b/frontend/tests/context.js index b1a04f6b..bf00bd0c 100644 --- a/frontend/tests/context.js +++ b/frontend/tests/context.js @@ -228,3 +228,14 @@ Soit("{string} le nom de la licence du document principal", (license) => { cy.get('.license').eq(0).should('contain', license); }); +Soit("ayant sélectionné les documents {string} et {string}", (doc1, doc2) => { + cy.get('#display-list').check({ force: true }); + cy.contains('span.work', doc1) + .parents('.card-body') + .find('input[type="checkbox"]') + .check(); + cy.contains('span.work', doc2) + .parents('.card-body') + .find('input[type="checkbox"]') + .check(); +}); \ No newline at end of file diff --git a/frontend/tests/event.js b/frontend/tests/event.js index c2fd36a5..faaa0322 100644 --- a/frontend/tests/event.js +++ b/frontend/tests/event.js @@ -10,6 +10,10 @@ Quand("j'essaie de créer une glose de type {string}", (option) => { cy.click_on_create(); }); +Quand("j'essaie de créer une glose de type {string} à partir de la bibliothèque", (option) => { + cy.get('#btn-create-quotation').click(); +}); + Quand("je me focalise sur {string}", (title) => { cy.contains('span', title).parent().prevAll('a.focus').first().click(); }); diff --git a/frontend/tests/outcome.js b/frontend/tests/outcome.js index d90bdcc5..cd28eda7 100644 --- a/frontend/tests/outcome.js +++ b/frontend/tests/outcome.js @@ -212,3 +212,9 @@ Alors("{string} est à la ligne {int} du passage", (text, line) => { }); }); +Alors("le document ouvert contient les références à {string}", (title) => { + cy.get('.card .card-body') + .should('be.visible') + .find('.work') + .should('contain', title) +}); \ No newline at end of file From 8bb4228453c710776f8a5d4167ef067f97bff1fc Mon Sep 17 00:00:00 2001 From: panchotf Date: Tue, 2 Jun 2026 14:43:57 +0200 Subject: [PATCH 3/3] IMPROVEMENT: Create a document as a glose of multiple documents (see #404). Co-authored-by: Mathys LEMORT --- frontend/src/components/DocumentsCards.jsx | 42 ++++++++++++--- frontend/src/routes/Bookshelf.jsx | 63 ++++++++++++++++++++-- 2 files changed, 94 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/DocumentsCards.jsx b/frontend/src/components/DocumentsCards.jsx index 3fb31c44..21b0fe42 100644 --- a/frontend/src/components/DocumentsCards.jsx +++ b/frontend/src/components/DocumentsCards.jsx @@ -1,17 +1,24 @@ import Card from 'react-bootstrap/Card'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; +import Form from 'react-bootstrap/Form'; import Metadata from './Metadata'; import BrowseTools from './BrowseTools'; import FutureDocument from './FutureDocument'; import { TypeBadge } from './Type'; -function DocumentsCards({docs, expandable, byRow, createOn, setLastUpdate, backend, user}) { +function DocumentsCards({docs, expandable, byRow, createOn, setLastUpdate, backend, user, selectedDocs, setSelectedDocs, showCheckboxes}) { return ( {docs.map(x => x?._id && x?.dc_title && - + )} {createOn && @@ -27,11 +34,34 @@ function DocumentsCards({docs, expandable, byRow, createOn, setLastUpdate, backe ); } -function DocumentCard({doc, expandable}) { +function DocumentCard({doc, expandable, selectedDocs, setSelectedDocs, showCheckboxes}) { + const handleCheck = (e) => { + if (e.target.checked) { + setSelectedDocs(prev => [...prev, doc._id]); + } else { + setSelectedDocs(prev => prev.filter(id => id !== doc._id)); + } + }; + return ( - + - +
+ {/* La checkbox s'affiche uniquement si showCheckboxes est vrai */} + {showCheckboxes && ( + + )} +
+ +
+
@@ -39,4 +69,4 @@ function DocumentCard({doc, expandable}) { ); } -export default DocumentsCards; +export default DocumentsCards; \ No newline at end of file diff --git a/frontend/src/routes/Bookshelf.jsx b/frontend/src/routes/Bookshelf.jsx index 40213c78..01423425 100644 --- a/frontend/src/routes/Bookshelf.jsx +++ b/frontend/src/routes/Bookshelf.jsx @@ -1,25 +1,31 @@ import '../styles/Bookshelf.css'; import { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router'; import Container from 'react-bootstrap/Container'; import ButtonGroup from 'react-bootstrap/ButtonGroup'; import ToggleButton from 'react-bootstrap/ToggleButton'; +import Button from 'react-bootstrap/Button'; import FutureDocument from '../components/FutureDocument.jsx'; import DocumentsCards from '../components/DocumentsCards.jsx'; import Graph from '../components/Graph.jsx'; import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; +import { v4 as uuid } from 'uuid'; function Bookshelf({ backend, user }) { const [documents, setDocuments] = useState([]); const [lastUpdate, setLastUpdate] = useState(); const [displayMode, setDisplayMode] = useState(localStorage.getItem('displayMode') || 'graph'); + const [selectedDocs, setSelectedDocs] = useState([]); + const navigate = useNavigate(); const displayModesList = ['graph', 'list']; useEffect(() => { backend.getAllDocuments(user) .then(setDocuments); }, [lastUpdate, user, backend]); + const docs = [ ...new Map( documents?.filter(x => !!x) @@ -28,6 +34,34 @@ function Bookshelf({ backend, user }) { ]; const displayedDocs = docs?.flatMap(d => d[0]); + const handleCreateQuotation = async () => { + const _id = uuid().replace(/-/g, ''); + const doc = { + _id, + editors: [user], + dc_creator: '…', + dc_title: '…', + dc_issued: new Date(), + dc_isPartOf: null, + dc_license: null, + dc_translator: null, + dc_language: null, + dc_publisher: null, + dc_spatial: null, + text: '', + links: selectedDocs.map((object) => ({ verb: 'includes', object })) + }; + + try { + await backend.putDocument(doc); + setLastUpdate(_id); + navigate(`/${selectedDocs[0]}#${_id}`); + setSelectedDocs([]); + } catch (error) { + console.error(error); + } + }; + function DisplayDocuments() { switch (displayMode) { case 'graph': @@ -42,9 +76,29 @@ function Bookshelf({ backend, user }) {
); case 'list': - return ; + return ( + <> + {selectedDocs.length > 0 && ( +
+
Create a new quotation with the {selectedDocs.length} selected document(s)
+ +
+ )} + + + ); + default: + return null; } } @@ -75,5 +129,4 @@ function Bookshelf({ backend, user }) { ); } -export default Bookshelf; - +export default Bookshelf; \ No newline at end of file