Skip to content
Snippets Groups Projects
Commit eadc3d5a authored by john's avatar john
Browse files

move scrolling and resolving to the track changes provider

parent f0f9e42a
No related branches found
No related tags found
No related merge requests found
......@@ -35,7 +35,6 @@ class Editor extends ProseEditor {
this.props.updateTrackChangesStatus(!this.props.trackChanges)
this.extendState({ trackChanges: !this.props.trackChanges })
console.log(this.el)
}
updateTrackChangeView () {
......@@ -178,9 +177,10 @@ class Editor extends ProseEditor {
// TODO -- do I need all of these?
// track changes provider
const trackChangesProvider = new TrackChangesProvider({
const trackChangesProvider = new TrackChangesProvider(doc, {
commandManager: this.commandManager,
containerId: this.props.containerId,
controller: this,
documentSession: this.documentSession,
surfaceManager: this.surfaceManager,
user: this.props.user
......
import { pickBy, clone, map, sortBy, findIndex } from 'lodash'
import { AnnotationComponent, createAnnotation, deleteNode } from 'substance'
import { AnnotationComponent } from 'substance'
class TrackChangeComponent extends AnnotationComponent {
render ($$) {
const { status } = this.props.node
const trackChangesView = this.toggleTrackChangeView()
const { id, status } = this.props.node
const trackChangesView = this.context.controller.state.trackChangesView
const accept = $$('a')
.addClass('sc-track-item-accept')
.on('click', this.acceptTrackChange)
.on('click', this.accept)
const reject = $$('a')
.addClass('sc-track-item-reject')
.on('click', this.rejectTrackChange)
.on('click', this.reject)
const separator = $$('span')
.addClass('sc-track-item-separator')
......@@ -24,6 +23,7 @@ class TrackChangeComponent extends AnnotationComponent {
.append(reject)
let el = $$('span')
.attr('data-id', id)
.addClass(this.getClassNames())
.append(this.props.children)
.append(container)
......@@ -41,133 +41,23 @@ class TrackChangeComponent extends AnnotationComponent {
return el
}
// TODO -- Move most of the funcs into provider
getSurface () {
const surfaceManager = this.context.surfaceManager
const containerId = this.context.controller.props.containerId
return surfaceManager.getSurface(containerId)
}
toggleTrackChangeView () {
const self = this
const surface = self.getSurface()
if (!surface) return
return surface._owner.state.trackChangesView
}
acceptTrackChange () {
const nodeId = this.props.node.id
const status = this.props.node.status
const ds = this.getDocumentSession()
const doc = ds.getDocument()
const nodeData = this.buildNodeData(nodeId)
const nextNodeId = this.findNextTrackNode(nodeId)
var self = this
ds.transaction(function (tx, args) {
if (status === 'add') createAnnotation(doc, nodeData)
deleteNode(tx, { nodeId: nodeId })
if (status === 'delete') self.context.surface.delete(tx, nodeData)
})
if (nextNodeId) {
this.focusToNext(nextNodeId)
}
}
rejectTrackChange () {
const nodeId = this.props.node.id
const status = this.props.node.status
const ds = this.getDocumentSession()
const doc = ds.getDocument()
const nodeData = this.buildNodeData(nodeId)
const nextNodeId = this.findNextTrackNode(nodeId)
var self = this
ds.transaction(function (tx, args) {
if (status === 'delete') createAnnotation(doc, nodeData)
deleteNode(tx, { nodeId: nodeId })
if (status === 'add') self.context.surface.delete(tx, nodeData)
})
if (nextNodeId) {
this.focusToNext(nextNodeId)
}
accept () {
this.resolve('accept')
}
buildNodeData (nodeId) {
const ds = this.getDocumentSession()
const doc = ds.getDocument()
const trackChangeNode = doc.get(nodeId)
const path = trackChangeNode.path
const startOffset = trackChangeNode.startOffset
const endOffset = trackChangeNode.endOffset
const sel = ds.createSelection(path, startOffset, endOffset)
return {
selection: sel,
node: { type: 'paragraph' }
}
reject () {
this.resolve('reject')
}
findNextTrackNode (currentNodeId) {
const ds = this.getDocumentSession()
let doc = ds.getDocument()
let documentNodes = doc.getNodes()
const trackChanges = pickBy(documentNodes, function (value, key) {
return value.type === 'track-change'
})
// return entries sorted in document
const entries = this.sortNodes(trackChanges)
// find index in Array of resolved track Change
const index = findIndex(entries, function (entry) {
return entry.id === currentNodeId
})
const nextIndex = index + 1
// If next index exist move to that else move to first
if (entries[nextIndex]) {
return entries[nextIndex].id
} else if (entries.length > 0) {
return entries[0].id
}
return
}
focusToNext (nextNodeId) {
const nextNodeData = this.buildNodeData(nextNodeId)
this.context.surface.setSelection(nextNodeData.selection)
this.context.controller.scrollTo(nextNodeId)
}
resolve (action) {
const annotation = this.props.node
const provider = this.getProvider()
sortNodes (nodes) {
let trackChanges = clone(nodes)
const ds = this.getDocumentSession()
let doc = ds.getDocument()
const container = doc.get('body')
trackChanges = map(trackChanges, function (trackChange) {
const blockId = trackChange.path[0]
const blockPosition = container.getPosition(blockId)
const nodePosition = trackChange.startOffset
return {
id: trackChange.id,
blockPosition: blockPosition,
nodePosition: nodePosition,
node: trackChange
}
})
return sortBy(trackChanges, ['blockPosition', 'nodePosition'])
provider.resolve(annotation, action)
}
getDocumentSession () {
return this.context.documentSession
getProvider () {
return this.context.trackChangesProvider
}
}
......
......@@ -3,10 +3,14 @@ import {
each,
filter,
find,
findIndex,
keys,
last,
map,
maxBy,
minBy
minBy,
pickBy,
sortBy
} from 'lodash'
import {
......@@ -15,13 +19,17 @@ import {
deleteNode,
deleteSelection as deleteSel,
expandAnnotation,
truncateAnnotation
truncateAnnotation,
TOCProvider
} from 'substance'
class TrackChangesProvider {
constructor (config) {
this.config = config
this.config.documentSession.on('didUpdate', this.handleUndoRedo, this)
class TrackChangesProvider extends TOCProvider {
constructor (document, config) {
super(document, config)
config.documentSession.on('didUpdate', this.handleUndoRedo, this)
// HACK -- use TOCProvider's event to capture new / deleted changes
this.on('toc:updated', this.reComputeEntries, this)
}
/*
......@@ -514,6 +522,90 @@ class TrackChangesProvider {
surface.transaction(transformation, info)
}
/*
ACCEPT / REJECT
*/
resolve (annotation, action) {
const next = this.getNext(annotation)
const selection = annotation.getSelection()
const status = annotation.status
this.removeTrackAnnotation(annotation)
if (
(action === 'accept' && status === 'delete') ||
(action === 'reject' && status === 'add')
) {
this.deleteSelection(selection)
}
this.focus(next)
}
computeEntries () {
let doc = this.getDocument()
let nodes = doc.getNodes()
let changes = pickBy(nodes, node => {
return node.type === 'track-change'
})
let entries = this.sortNodes(changes)
return entries
}
reComputeEntries () {
this.entries = this.computeEntries()
}
sortNodes (nodes) {
const changes = clone(nodes)
const doc = this.getDocument()
const container = doc.get('body')
const changesArray = map(changes, annotation => {
const blockId = annotation.path[0]
const blockPosition = container.getPosition(blockId)
const nodePosition = annotation.startOffset
return {
id: annotation.id,
blockPosition: blockPosition,
nodePosition: nodePosition,
node: annotation
}
})
return sortBy(changesArray, ['blockPosition', 'nodePosition'])
}
getNext (annotation) {
const entries = this.entries
if (entries.length <= 1) return
const position = findIndex(entries, change => {
return change.node.id === annotation.id
})
if (position === -1) return
const next = position + 1
if (next >= entries.length) return entries[0].node
return entries[next].node
}
focus (annotation) {
if (!annotation) return
const surface = this.getSurface()
const { controller } = this.config
controller.scrollTo(annotation.id)
annotation.endOffset = annotation.startOffset
surface.setSelection(annotation.getSelection())
}
/*
ANNOTATION HELPERS
......@@ -760,4 +852,6 @@ class TrackChangesProvider {
}
}
TOCProvider.tocTypes = ['track-change']
export default TrackChangesProvider
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment