• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

EcrituresNumeriques / stylo / 15066626824

16 May 2025 10:41AM UTC coverage: 37.574% (-0.02%) from 37.594%
15066626824

Pull #1517

github

web-flow
Merge e05a1c169 into 607ffe7f9
Pull Request #1517: Mise à jour vers react-router@7

549 of 776 branches covered (70.75%)

Branch coverage included in aggregate %.

13 of 373 new or added lines in 28 files covered. (3.49%)

5 existing lines in 4 files now uncovered.

5319 of 14841 relevant lines covered (35.84%)

2.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/front/src/components/corpus/CorpusItem.jsx
1
import { useToasts } from '@geist-ui/core'
×
2
import React, { useCallback, useMemo, useState } from 'react'
×
3
import {
×
4
  ChevronDown,
5
  ChevronRight,
6
  Eye,
7
  Printer,
8
  Settings,
9
  Trash,
10
} from 'lucide-react'
11
import { useTranslation } from 'react-i18next'
×
NEW
12
import { Link } from 'react-router'
×
13

14
import { useCorpusActions } from '../../hooks/corpus.js'
×
15
import { useModal } from '../../hooks/modal.js'
×
16

17
import Button from '../Button.jsx'
×
18
import Export from '../Export.jsx'
×
19
import Modal from '../Modal.jsx'
×
20
import FormActions from '../molecules/FormActions.jsx'
×
21
import TimeAgo from '../TimeAgo.jsx'
×
22
import CorpusArticles from './CorpusArticles.jsx'
×
23
import CorpusForm from './CorpusForm.jsx'
×
24
import CorpusMetadataModal from './CorpusMetadataModal.jsx'
×
25

26
import buttonStyles from '../button.module.scss'
×
27
import styles from './corpusItem.module.scss'
×
28

29
/**
30
 * @typedef Article
31
 * @type {object}
32
 * @property {string} _id
33
 * @property {string} title
34
 */
35

36
/**
37
 * @typedef Corpus
38
 * @type {object}
39
 * @property {string} _id
40
 * @property {string} name
41
 * @property {string} description
42
 * @property {any} metadata
43
 * @property {object} creator
44
 * @property {string} creator.displayName
45
 * @property {string} creator.username
46
 * @property {Article[]} articles
47
 * @property {string} updatedAt
48
 * @property {string} createdAt
49
 */
50

51
/**
52
 * @param {Corpus} corpus
53
 * @return {Element}
54
 */
55
export default function CorpusItem({ corpus }) {
×
56
  const { t } = useTranslation()
×
57
  const { setToast } = useToasts()
×
58

59
  const deleteCorpusModal = useModal()
×
60
  const exportCorpusModal = useModal()
×
61
  const editCorpusModal = useModal()
×
62

63
  const { deleteCorpus } = useCorpusActions()
×
64
  const corpusId = useMemo(() => corpus._id, [corpus])
×
65

66
  const handleDeleteCorpus = useCallback(async () => {
×
67
    try {
×
68
      await deleteCorpus(corpusId)
×
69
      setToast({
×
70
        text: t('corpus.delete.toastSuccess'),
×
71
        type: 'default',
×
72
      })
×
73
    } catch (err) {
×
74
      setToast({
×
75
        text: `Unable to delete corpus ${corpus.name}: ${err}`,
×
76
        type: 'error',
×
77
      })
×
78
    }
×
79
  }, [corpusId])
×
80

81
  const [expanded, setExpanded] = useState(false)
×
82
  const toggleExpansion = useCallback(
×
83
    (event) => {
×
84
      if (!event.key || [' ', 'Enter'].includes(event.key)) {
×
85
        setExpanded(!expanded)
×
86
      }
×
87
    },
×
88
    [expanded]
×
89
  )
×
90

91
  return (
×
92
    <div className={styles.container}>
×
93
      <div className={styles.header}>
×
94
        <div className={styles.heading} onClick={toggleExpansion}>
×
95
          <h4 className={styles.title}>
×
96
            <span
×
97
              tabIndex={0}
×
98
              onKeyUp={toggleExpansion}
×
99
              className={styles.icon}
×
100
            >
101
              {expanded ? <ChevronDown /> : <ChevronRight />}
×
102
            </span>
×
103
            {corpus.name}
×
104
          </h4>
×
105
          <p className={styles.metadata}>
×
106
            <span className={styles.by}>{t('corpus.by.text')}</span>
×
107
            <span className={styles.creator}>
×
108
              {corpus.creator.displayName || corpus.creator.username}
×
109
            </span>
×
110
            <TimeAgo date={corpus.updatedAt} className={styles.updatedAt} />
×
111
          </p>
×
112
        </div>
×
113
        <aside className={styles.actionButtons}>
×
114
          <Button
×
115
            title={t('corpus.edit.buttonTitle')}
×
116
            icon={true}
×
117
            onClick={() => editCorpusModal.show()}
×
118
          >
119
            <Settings />
×
120
          </Button>
×
121

122
          <CorpusMetadataModal
×
123
            corpusId={corpusId}
×
124
            initialValue={corpus.metadata}
×
125
          />
×
126

127
          <Button
×
128
            title={t('corpus.delete.buttonTitle')}
×
129
            icon={true}
×
130
            onClick={(event) => {
×
131
              event.preventDefault()
×
132
              deleteCorpusModal.show()
×
133
            }}
×
134
          >
135
            <Trash />
×
136
          </Button>
×
137
          <Button
×
138
            title={t('corpus.export.buttonTitle')}
×
139
            icon={true}
×
140
            onClick={() => exportCorpusModal.show()}
×
141
          >
142
            <Printer />
×
143
          </Button>
×
144

145
          <Link
×
146
            title={t('corpus.preview.buttonTitle')}
×
147
            target="_blank"
×
148
            className={buttonStyles.icon}
×
149
            to={`/corpus/${corpus._id}/annotate`}
×
150
          >
151
            <Eye />
×
152
          </Link>
×
153
        </aside>
×
154
      </div>
×
155
      {expanded && (
×
156
        <div className={styles.detail}>
×
157
          {corpus.description && <p>{corpus.description}</p>}
×
158
          <CorpusArticles corpusId={corpusId} />
×
159
        </div>
×
160
      )}
161

162
      <Modal
×
163
        {...deleteCorpusModal.bindings}
×
164
        title={
×
165
          <>
×
166
            <Trash /> {t('corpus.deleteModal.title')}
×
167
          </>
×
168
        }
169
      >
170
        <p>{t('corpus.deleteModal.confirmMessage')}</p>
×
171
        <FormActions
×
172
          onCancel={() => deleteCorpusModal.close()}
×
173
          onSubmit={handleDeleteCorpus}
×
174
        />
×
175
      </Modal>
×
176

177
      <Modal
×
178
        {...exportCorpusModal.bindings}
×
179
        title={
×
180
          <>
×
181
            <Printer /> {t('corpus.exportModal.title')}
×
182
          </>
×
183
        }
184
      >
185
        <Export
×
186
          bookId={corpusId}
×
187
          name={corpus.name}
×
188
          onCancel={() => exportCorpusModal.close()}
×
189
        />
×
190
      </Modal>
×
191

192
      <Modal
×
193
        {...editCorpusModal.bindings}
×
194
        title={
×
195
          <>
×
196
            <Settings /> {t('corpus.editModal.title')}
×
197
          </>
×
198
        }
199
      >
200
        <CorpusForm corpus={corpus} onCancel={() => editCorpusModal.close()} />
×
201
      </Modal>
×
202
    </div>
×
203
  )
204
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc