@manuscripts/body-editor 3.19.0 → 3.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,7 +32,12 @@ import {
32
32
  useScrollDetection,
33
33
  withListNavigation,
34
34
  withNavigableListItem,
35
+ ButtonGroup,
36
+ DeleteIcon,
37
+ LinkIcon,
38
+ outlineStyle,
35
39
  } from '@manuscripts/style-guide'
40
+ import { Button, IconButton } from '@manuscripts/style-guide/mui'
36
41
  import {
37
42
  BibliographyItemAttrs,
38
43
  generateNodeID,
@@ -40,11 +45,12 @@ import {
40
45
  } from '@manuscripts/transform'
41
46
  import isEqual from 'lodash/isEqual'
42
47
  import React, { useEffect, useMemo, useRef, useState } from 'react'
43
- import styled from 'styled-components'
48
+ import styled, { css } from 'styled-components'
44
49
 
45
50
  import {
46
51
  ReferenceForm,
47
52
  ReferenceFormActions,
53
+ validateReference,
48
54
  } from './ReferenceForm/ReferenceForm'
49
55
  import { ReferenceLine } from './ReferenceLine'
50
56
  import { ImportBibliographyModal } from './ImportBibliographyModal'
@@ -87,6 +93,7 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
87
93
 
88
94
  const [selection, setSelection] = useState<BibliographyItemAttrs>()
89
95
  const [isNew, setIsNew] = useState<boolean>(false)
96
+ const [showDeleteDialog, setShowDeleteDialog] = useState(false)
90
97
  const selectionRef = useRef<HTMLDivElement>(null)
91
98
 
92
99
  const sortedItems = useMemo(
@@ -173,6 +180,12 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
173
180
  return extraKeys.length > 0
174
181
  }
175
182
 
183
+ const canDeleteSelectedItem =
184
+ (selection &&
185
+ !citationCounts.get(selection.id) &&
186
+ isNewItem(selection, ['id', 'type'])) ??
187
+ false
188
+
176
189
  const handleSave = (values: BibliographyItemAttrs | undefined) => {
177
190
  if (!values || !selection) {
178
191
  return
@@ -221,8 +234,14 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
221
234
  setSelection(item)
222
235
  }
223
236
 
237
+ const [canSave, setCanSave] = useState(false)
238
+
224
239
  const handleChange = (values: BibliographyItemAttrs) => {
225
240
  valuesRef.current = values
241
+ const errors = validateReference(values)
242
+ const isValid = Object.keys(errors).length === 0
243
+ const dirty = actionsRef.current?.isDirty() ?? false
244
+ setCanSave(isValid && dirty)
226
245
  }
227
246
 
228
247
  const handleImportSave = (data: BibliographyItemAttrs[]) => {
@@ -257,6 +276,25 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
257
276
  },
258
277
  }}
259
278
  />
279
+ <Dialog
280
+ isOpen={showDeleteDialog}
281
+ category={Category.confirmation}
282
+ header="Delete Reference"
283
+ message="Are you sure you want to delete this reference from the list?"
284
+ actions={{
285
+ secondary: {
286
+ action: () => {
287
+ handleDelete()
288
+ setShowDeleteDialog(false)
289
+ },
290
+ title: 'Delete',
291
+ },
292
+ primary: {
293
+ action: () => setShowDeleteDialog(false),
294
+ title: 'Cancel',
295
+ },
296
+ }}
297
+ />
260
298
  <ReferencesModalContainer data-cy={'references-editor'}>
261
299
  <ModalHeader>
262
300
  <CloseButton data-cy="modal-close-button" onClick={onCancel} />
@@ -286,9 +324,11 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
286
324
  <span>New Reference</span>
287
325
  </NewReferenceButton>
288
326
  <ReferencesInnerWrapper>
289
- <ExistingReferencesHeading>
290
- Existing References
291
- </ExistingReferencesHeading>
327
+ {sortedItems.length ? (
328
+ <ExistingReferencesHeading>
329
+ Existing References
330
+ </ExistingReferencesHeading>
331
+ ) : null}
292
332
  {sortedItems.slice(startIndex, endIndex + 1).map((item) => (
293
333
  <ReferenceButton
294
334
  key={item.id}
@@ -311,6 +351,25 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
311
351
  showUncited={!citationCounts.get(item.id)}
312
352
  item={item}
313
353
  />
354
+ {isSelected(item) && (
355
+ <ButtonGroup>
356
+ <IconButton
357
+ component={'a'}
358
+ href={`https://doi.org/${item.DOI}`}
359
+ target={'_blank'}
360
+ size={'small'}
361
+ >
362
+ <DOILinkIcon fill={'#6E6E6E'} />
363
+ </IconButton>
364
+ <IconButton
365
+ disabled={!canDeleteSelectedItem}
366
+ size={'small'}
367
+ onClick={() => setShowDeleteDialog(true)}
368
+ >
369
+ <DeleteIcon fill={'#6E6E6E'} />
370
+ </IconButton>
371
+ </ButtonGroup>
372
+ )}
314
373
  </ReferenceButton>
315
374
  ))}
316
375
  </ReferencesInnerWrapper>
@@ -326,27 +385,32 @@ export const ReferencesModal: React.FC<ReferencesModalProps> = ({
326
385
  </ImportFromFileButton>
327
386
  </ImportFromFileFooter>
328
387
  </ReferencesSidebar>
329
- <ScrollableModalContent>
388
+ <ReferencesContent>
330
389
  {importSuccessCount !== null ? (
331
390
  <ImportSuccessPlaceholder count={importSuccessCount} />
332
391
  ) : (
333
392
  selection && (
334
393
  <ReferenceForm
335
394
  values={normalizeBlblioItem(selection)}
336
- showDelete={
337
- !citationCounts.get(selection.id) &&
338
- isNewItem(selection, ['id', 'type']) // disable the delete button for the new citations
339
- }
340
395
  onChange={handleChange}
341
- onCancel={onCancel}
342
- onDelete={handleDelete}
343
396
  onSave={handleSave}
344
397
  actionsRef={actionsRef}
345
398
  />
346
399
  )
347
400
  )}
348
- </ScrollableModalContent>
401
+ </ReferencesContent>
349
402
  </ModalBody>
403
+ <Footer>
404
+ <TertiaryButton variant="tertiary" onClick={onCancel}>
405
+ Close
406
+ </TertiaryButton>
407
+ <Button
408
+ disabled={!canSave}
409
+ onClick={() => actionsRef.current?.submit()}
410
+ >
411
+ Save Changes
412
+ </Button>
413
+ </Footer>
350
414
  </ReferencesModalContainer>
351
415
  </StyledModal>
352
416
  </>
@@ -361,8 +425,13 @@ const ReferencesSidebar = styled(ModalSidebar)`
361
425
  width: 70%;
362
426
  `
363
427
 
428
+ const ReferencesContent = styled(ScrollableModalContent)`
429
+ padding-top: 32px;
430
+ `
431
+
364
432
  const ReferencesSidebarContent = styled(SidebarContent)`
365
433
  overflow-y: auto;
434
+ padding-top: 8px;
366
435
  `
367
436
 
368
437
  const ReferencesInnerWrapper = withListNavigation(styled.div`
@@ -372,7 +441,7 @@ const ReferencesInnerWrapper = withListNavigation(styled.div`
372
441
 
373
442
  const CitationCountIconStyled = styled(CitationCountIcon)``
374
443
 
375
- const ReferenceButton = withNavigableListItem(styled.button`
444
+ const referenceButtonStyles = css`
376
445
  cursor: pointer;
377
446
  display: flex;
378
447
  width: 100%;
@@ -384,6 +453,7 @@ const ReferenceButton = withNavigableListItem(styled.button`
384
453
  border: none;
385
454
  border-radius: 0;
386
455
  text-align: inherit;
456
+ color: #353535;
387
457
 
388
458
  padding: ${(props) => props.theme.grid.unit * 4}px 0;
389
459
  border-top: 1px solid transparent;
@@ -408,6 +478,13 @@ const ReferenceButton = withNavigableListItem(styled.button`
408
478
  padding: ${(props) => props.theme.grid.unit * 2}px;
409
479
  border-radius: 6px;
410
480
  }
481
+ `
482
+
483
+ const ReferenceButton = withNavigableListItem(styled.div.attrs({
484
+ role: 'button',
485
+ tabIndex: 0,
486
+ })`
487
+ ${referenceButtonStyles}
411
488
  `)
412
489
 
413
490
  const IconContainer = styled.div`
@@ -433,10 +510,14 @@ const CitationCount = styled.div`
433
510
  }
434
511
  `
435
512
 
436
- const NewReferenceButton = styled(ReferenceButton)`
513
+ const NewReferenceButton = styled.button`
514
+ ${referenceButtonStyles}
515
+
437
516
  svg {
438
517
  margin-right: 8px;
439
518
  }
519
+
520
+ ${outlineStyle}
440
521
  `
441
522
  const ExistingReferencesHeading = styled.h3`
442
523
  font-size: 18px;
@@ -474,3 +555,24 @@ const ImportFromFileButton = styled.button`
474
555
  fill: #6e6e6e;
475
556
  }
476
557
  `
558
+
559
+ const Footer = styled.div`
560
+ display: flex;
561
+ justify-content: flex-end;
562
+ padding: 16px 32px;
563
+ gap: 16px;
564
+ `
565
+
566
+ const TertiaryButton = styled(Button)`
567
+ &.MuiButton-textSecondary {
568
+ color: #0d79d0;
569
+
570
+ &:hover {
571
+ background-color: rgba(13, 121, 208, 0.04);
572
+ }
573
+ }
574
+ `
575
+
576
+ const DOILinkIcon = styled(LinkIcon)`
577
+ transform: rotate(-45deg);
578
+ `
package/src/lib/view.ts CHANGED
@@ -180,3 +180,4 @@ export const isSelectionInsideNode = (
180
180
 
181
181
  return from >= pos && to <= end
182
182
  }
183
+
package/src/menus.tsx CHANGED
@@ -66,6 +66,7 @@ import { isEditAllowed } from './lib/utils'
66
66
  import { getEditorProps } from './plugins/editor-props'
67
67
  import { useEditor } from './useEditor'
68
68
  import { openInsertAwardModal } from './components/awards/AwardModal'
69
+ import { openReferencesEditor } from './components/references/ReferencesEditor'
69
70
 
70
71
  export const getEditorMenus = (
71
72
  editor: ReturnType<typeof useEditor>
@@ -652,6 +653,17 @@ export const getEditorMenus = (
652
653
  run: doCommand(insertInlineCitation),
653
654
  isHidden: !templateAllows(state, schema.nodes.citation),
654
655
  },
656
+ {
657
+ id: 'insert-reference-section',
658
+ label: 'New reference',
659
+ shortcut: {
660
+ mac: 'Option+CommandOrControl+N',
661
+ pc: 'CommandOrControl+Option+N',
662
+ },
663
+ isEnabled: isEditAllowed(state),
664
+ run: doCommand(openReferencesEditor),
665
+ isHidden: !templateAllows(state, schema.nodes.bibliography_item),
666
+ },
655
667
  {
656
668
  id: 'insert-cross-reference',
657
669
  label: 'Cross-reference',
package/src/versions.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  //THIS FILE WAS GENERATED BY versions.mjs
2
- export const VERSION = '3.19.0';
2
+ export const VERSION = '3.19.1';
3
3
  export const MATHJAX_VERSION = '3.2.2';