Skip to content

Commit

Permalink
Merge pull request substance#40 from substance/references-i1
Browse files Browse the repository at this point in the history
References
  • Loading branch information
obuchtala authored Mar 5, 2020
2 parents 0f104e2 + 8552cd3 commit 092bc2c
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 11 deletions.
7 changes: 6 additions & 1 deletion data/kitchen-sink/smart-figure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
</panel>
</panels>
<additionalInformation>
<paragraph id="additional-information-p1">Data information: Values are expressed as mean ± SEM. *P &lt; 0.05; **P &lt; 0.01; ***P &lt; 0.001. Statistical tests used are as follows: ANOVA for (A, C, F, and G); and t‐test for (D).</paragraph>
<paragraph id="additional-information-p1">Data information: Values are expressed <cite references="reference-1 reference-3" /> as mean ± SEM. *P &lt; 0.05; **P &lt; 0.01; ***P &lt; 0.001. Statistical tests used are as follows: ANOVA for (A, C, F, and G); and t‐test for (D).</paragraph>
<paragraph id="additional-information-p2">Source data are available online for this figure.</paragraph>
</additionalInformation>
<files>
Expand All @@ -94,4 +94,9 @@
</legend>
</resource>
</resources>
<references>
<reference id="reference-1" label="1">Yuste R, Katz L. Control of postsynaptic Ca2+ influx in developing neocortex. Neuron. 1991;6:333-44. https://doi.org/10.1016/0896-6273(91)90243-S</reference>
<reference id="reference-2" label="2">Diabetes Australia. Diabetes globally [Internet]. Canberra ACT: Diabetes Australia; 2012. http://www.diabetesaustralia.com.au/en/​Understanding-Diabetes/Diabetes-Globally</reference>
<reference id="reference-3" label="3">Van Eck NJ, Waltman L. 2007. VOS: A new method for visualizing similarities between objects. Advances in Data Analysis: Proceedings of the 30th Annual Conference of the Gesellschaft Für Klassifikation e.V, Freie Universita ̈t Berlin, March 8–10, 2006. Berlin, Heidelberg: Springer Berlin Heidelberg. p299–306.</reference>
</references>
</smart-figure>
36 changes: 33 additions & 3 deletions src/SmartFigureConfiguration.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import {
UndoCommand, RedoCommand, SelectAllCommand, AnnotationCommand, CreateLinkCommand,
MoveItemCommand, RemoveItemCommand, MoveValueCommand, RemoveValueCommand,
AddAuthorCommand, InsertAuthorCommand, EditAuthorCommand,
AddAffiliationCommand, InsertAffiliationCommand, EditAffiliationCommand
AddAffiliationCommand, InsertAffiliationCommand, EditAffiliationCommand,
AddReferenceCommand, CreateCitationCommand, EditCitationCommand, CitationComponent,
RemoveInlineNodeCommand
} from 'substance'

import SmartFigureLoader from './model/SmartFigureLoader'
Expand Down Expand Up @@ -49,6 +51,7 @@ export default class SmartFigureConfiguration extends Configurator {
config.addComponent('heading', HeadingComponent)
config.addComponent('image', ImageComponent)
config.addComponent('link', LinkComponent)
config.addComponent('cite', CitationComponent)

// HTML conversion
config.addConverter('html', ParagraphConverter)
Expand Down Expand Up @@ -90,6 +93,10 @@ export default class SmartFigureConfiguration extends Configurator {
nodeType: 'link',
accelerator: 'CommandOrControl+K'
})
config.addCommand('create-citation', CreateCitationCommand, {
nodeType: 'cite',
accelerator: 'CommandOrControl+Shift+C'
})
config.addCommand('insert-panel', InsertPanelCommand)
config.addCommand('remove-panel', RemoveItemCommand, { type: 'panel' })
config.addCommand('rename-panel-image', RenamePanelImageCommand)
Expand Down Expand Up @@ -135,11 +142,19 @@ export default class SmartFigureConfiguration extends Configurator {
config.addCommand('move-file-up', MoveItemCommand, { type: 'file', direction: 'up' })
config.addCommand('move-file-down', MoveItemCommand, { type: 'file', direction: 'down' })

config.addCommand('add-reference', AddReferenceCommand)
config.addCommand('remove-reference', RemoveItemCommand, { type: 'reference' })
config.addCommand('move-reference-up', MoveItemCommand, { type: 'reference', direction: 'up' })
config.addCommand('move-reference-down', MoveItemCommand, { type: 'reference', direction: 'down' })

config.addCommand('add-resource', AddResourceCommand)
config.addCommand('remove-resource', RemoveItemCommand, { type: 'resource' })
config.addCommand('move-resource-up', MoveItemCommand, { type: 'resource', direction: 'up' })
config.addCommand('move-resource-down', MoveItemCommand, { type: 'resource', direction: 'down' })

config.addCommand('edit-citation', EditCitationCommand)
config.addCommand('remove-citation', RemoveInlineNodeCommand)

// Menus
const editorToolbar = {
type: 'toolbar',
Expand All @@ -155,6 +170,7 @@ export default class SmartFigureConfiguration extends Configurator {
{ command: 'toggle-subscript', icon: 'subscript', tooltip: 'Subscript' },
{ command: 'toggle-superscript', icon: 'superscript', tooltip: 'Superscript' },
{ command: 'create-link', icon: 'link', tooltip: 'Link' },
{ command: 'create-citation', icon: 'quote-right', tooltip: 'Citation' },
{
type: 'menu',
label: 'Smart Figure',
Expand All @@ -165,7 +181,8 @@ export default class SmartFigureConfiguration extends Configurator {
{ command: 'add-affiliation', label: 'Add Affiliation' },
{ command: 'insert-panel', label: 'Add Panel' },
{ command: 'add-file', label: 'Add File' },
{ command: 'add-resource', label: 'Add Resource' }
{ command: 'add-resource', label: 'Add Resource' },
{ command: 'add-reference', label: 'Add Reference' }
]
},
{
Expand All @@ -188,7 +205,8 @@ export default class SmartFigureConfiguration extends Configurator {
{ command: 'toggle-strike', icon: 'strikethrough', label: 'Strike Through' },
{ command: 'toggle-subscript', icon: 'subscript', label: 'Subscript' },
{ command: 'toggle-superscript', icon: 'superscript', label: 'Superscript' },
{ command: 'create-link', icon: 'link', label: 'Link' }
{ command: 'create-link', icon: 'link', label: 'Link' },
{ command: 'create-citation', icon: 'asterisk', label: 'Citation' }
]
})
config.addToolPanel('context-menu:panel', {
Expand Down Expand Up @@ -255,6 +273,17 @@ export default class SmartFigureConfiguration extends Configurator {
]
})

config.addToolPanel('context-menu:reference', {
type: 'menu',
noIcons: true,
items: [
{ command: 'add-reference', label: 'Insert Reference' },
{ command: 'remove-reference', label: 'Remove Reference' },
{ command: 'move-reference-up', label: 'Move Reference Up' },
{ command: 'move-reference-down', label: 'Move Reference Down' }
]
})

config.addToolPanel('context-menu:resource', {
type: 'menu',
noIcons: true,
Expand Down Expand Up @@ -300,6 +329,7 @@ export default class SmartFigureConfiguration extends Configurator {
config.addLabel('panel.resources', 'Attached Resource')
config.addLabel('keyword-group', 'Keyword Group')
config.addLabel('file', 'File')
config.addLabel('reference', 'Reference')
config.addLabel('resource', 'Resource')
}
}
84 changes: 84 additions & 0 deletions src/components/CitationLabelManager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { nodeHelpers } from 'substance'

const { getLabel } = nodeHelpers

// FIXME: here are race conditions, because the ReferenceLabelManager is called later then this one
// TODO: instead of having two managers, we should merge
export default class CitationLabelManager {
constructor (editorSession) {
this.editorSession = editorSession

this.initialize()
}

initialize () {
const editorSession = this.editorSession
const doc = editorSession.getDocument()
editorSession.getEditorState().addObserver(['document'], this._onChange, this, {
stage: 'update'
})
this._referencesPath = [doc.root.id, 'references']
}

getReferenceLabel (reference) {
return `${reference.getPosition() + 1}`
}

getCitationLabel (cite) {
const references = cite.resolve('references')
const refLabels = references.map(ref => getLabel(ref))
refLabels.sort()
return `[${refLabels.join(',')}]`
}

update () {
const doc = this.editorSession.getDocument()
const references = doc.resolve(this._referencesPath)
const citations = doc.findAll('cite')
// first update references
let stateUpdates = references.map(ref => {
const label = this.getReferenceLabel(ref)
return [ref.id, { label }]
})
if (stateUpdates.length > 0) {
this.editorSession.updateNodeStates(stateUpdates, { silent: true })
}
// then update citations
stateUpdates = citations.map(cite => {
const label = this.getCitationLabel(cite)
return [cite.id, { label }]
})
if (stateUpdates.length > 0) {
this.editorSession.updateNodeStates(stateUpdates, { silent: true })
}
}

_onChange (change) {
// Note: if the reference list has changed, recompute all labels
if (change.hasUpdated(this._referencesPath)) {
this.update()
// otherwise update the label for created citations (e.g. pasted, or after undo)
// or when the citation has been updated
} else {
const ops = change.primitiveOps
const stateUpdates = []
// TODO: with the new op system, we should also try to generalize the API for writing listeners
for (const op of ops) {
if (
(op.isCreate() && op.val.type === 'cite') ||
(op.isSet() && op.path[1] === 'references')
) {
const doc = this.editorSession.getDocument()
const id = op.path[0]
const cite = doc.get(id)
if (cite) {
stateUpdates.push([id, { label: this.getCitationLabel(cite) }])
}
}
}
if (stateUpdates.length > 0) {
this.editorSession.updateNodeStates(stateUpdates, { silent: true })
}
}
}
}
8 changes: 7 additions & 1 deletion src/components/SmartFigureComponent.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Component, $$, renderProperty, AuthorsListComponent, AffiliationsListComponent } from 'substance'
import {
Component, $$, renderProperty, AuthorsListComponent,
AffiliationsListComponent, ReferenceListComponent
} from 'substance'
import FigurePanelsComponent from './SmartFigurePanelsComponent'
import FileListComponent from './FileListComponent'
import ResourceListComponent from './ResourceListComponent'
Expand Down Expand Up @@ -46,6 +49,9 @@ export default class SmartFigureComponent extends Component {
el.append(
$$(ResourceListComponent, { document: doc })
)
el.append(
$$(ReferenceListComponent, { document: doc })
)

return el
}
Expand Down
4 changes: 3 additions & 1 deletion src/components/SmartFigureEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import _getContext from './_getContext'
import PanelLabelManager from './PanelLabelManager'
import FilesLabelManager from './FilesLabelManager'
import ResourcesLabelManager from './ResourcesLabelManager'
import CitationLabelManager from './CitationLabelManager'

export default class SmartFigureEditor extends AbstractEditor {
constructor (...args) {
Expand Down Expand Up @@ -42,7 +43,8 @@ export default class SmartFigureEditor extends AbstractEditor {
new AffiliationLabelManager(this.editorSession),
new FilesLabelManager(this.editorSession),
new PanelLabelManager(this.editorSession),
new ResourcesLabelManager(this.editorSession)
new ResourcesLabelManager(this.editorSession),
new CitationLabelManager(this.editorSession)
]

this._globalEventHandler.addEventListener('keydown', this._onKeydown, this)
Expand Down
5 changes: 5 additions & 0 deletions src/components/SmartFigureTOC.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export default class SmartFigureTOC extends Component {
$$(Section, { name: 'resources', label: 'Resources' })
)
)
el.append(
$$(_DynamicTOCItem, { doc: document, path: [root.id, 'references'], scrollTarget: { section: 'references' } },
$$(Section, { name: 'references', label: 'References' })
)
)

return el
}
Expand Down
5 changes: 3 additions & 2 deletions src/model/SmartFigureApi.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {
BasicEditorApi, AuthorApi, AffiliationApi,
isString, documentHelpers, cloneDeep
ReferenceApi, isString, documentHelpers, cloneDeep
} from 'substance'

export default class SmartFigureApi extends BasicEditorApi {
constructor (...args) {
super(...args)

this.extendWith(new AuthorApi())
this.extendWith(new AffiliationApi())
this.extendWith(new AuthorApi())
this.extendWith(new ReferenceApi())
}

insertPanels (files, currentPanelId) {
Expand Down
17 changes: 16 additions & 1 deletion src/model/SmartFigureSchema.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SchemaBuilder } from 'substance'
import PanelMixin from './PanelMixin'

const RICH_TEXT_ANNOS = ['bold', 'italic', 'link', 'subscript', 'superscript', 'strike']
const RICH_TEXT_ANNOS = ['bold', 'cite', 'italic', 'link', 'subscript', 'superscript', 'strike']
const TITLE = () => {
return {
type: 'text',
Expand Down Expand Up @@ -51,6 +51,11 @@ export default function SmartFigureSchema () {
type: 'children',
childTypes: ['resource'],
optional: true
},
references: {
type: 'children',
childTypes: ['reference'],
optional: true
}
})
// author
Expand Down Expand Up @@ -115,8 +120,18 @@ export default function SmartFigureSchema () {
title: TITLE(),
legend: LEGEND()
})
v.addNode('reference', '@node', {
label: { type: 'string' },
content: {
type: 'text',
childTypes: ['bold', 'italic', 'link', 'superscript', 'subscript']
}
}, { omitPropertyElement: true })
// annotations
v.addNode('bold', '@annotation')
v.addNode('cite', '@inlinenode', {
references: { type: 'many', targetTypes: ['reference'] }
})
v.addNode('italic', '@annotation')
v.addNode('link', '@annotation', {
href: 'string'
Expand Down
4 changes: 2 additions & 2 deletions styles/_card-style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
box-shadow: 0 0 0 2px rgba(0, 123, 255, .5);
}

& > .sc-section:first-child {
& > div:first-child {
margin: -20px -20px 20px -20px;
padding: 5px 20px;
background: #F4F4F4;
border-bottom: 1px solid #E5E5E5;
}

& > .sc-section + .sc-section {
& > div + div {
margin-top: var(--half-spacing);
}
}
33 changes: 33 additions & 0 deletions styles/_citation-popover.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.sc-citation-popover {
width: 500px;
margin: -4px 0;
}

.sc-citation-popover > .se-reference {
@include ts-small-interface;
font-weight: 500;
padding: var(--half-spacing) var(--default-spacing);
word-break: break-all;
}

.sc-citation-popover > .se-reference > .se-label {
align-self: baseline;
font-weight: 600;
}

.sc-citation-popover > .sc-horizontal-stack {
padding: var(--half-spacing) var(--default-spacing);
}

.sc-citation-popover > .se-footer {
@include ts-small-interface;
}

.sc-citation-popover > .se-footer > .se-label {
@include ts-quiet;
}

.sc-citation-popover > .sc-horizontal-stack > .sc-button {
width: 100px;
margin: 0 var(--half-spacing);
}
4 changes: 4 additions & 0 deletions styles/_citation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.sc-inline-node.sm-cite {
color: var(--link-color);
white-space: nowrap;
}
3 changes: 3 additions & 0 deletions styles/_inline-node.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.sc-inline-node {
cursor: default;
}
4 changes: 4 additions & 0 deletions styles/_multi-select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@

.sc-multi-select .se-options:focus {
box-shadow: 0 0 0 3px rgba(0, 123, 255, .5);
}

.sc-multi-select .se-placeholder {
@include ts-quiet;
}
3 changes: 3 additions & 0 deletions styles/_reference-list.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.sc-reference-list > .se-references > * + * {
margin-top: var(--default-spacing);
}
Loading

0 comments on commit 092bc2c

Please sign in to comment.