diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 57 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkMenu.tsx | 9 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkMenuGroup.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkMenuItem.tsx | 28 |
4 files changed, 82 insertions, 14 deletions
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5ac4af0bb..d5f539194 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -5,7 +5,7 @@ import { observer } from "mobx-react"; import { baseKeymap } from "prosemirror-commands"; import { history } from "prosemirror-history"; import { keymap } from "prosemirror-keymap"; -import { NodeType } from 'prosemirror-model'; +import { NodeType, Slice, Node, Fragment } from 'prosemirror-model'; import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; import { Doc, Opt } from "../../../new_fields/Doc"; @@ -34,7 +34,6 @@ import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); import { DateField } from '../../../new_fields/DateField'; -import { thisExpression } from 'babel-types'; import { Utils } from '../../../Utils'; library.add(faEdit); @@ -251,6 +250,56 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this.setupEditor(config, this.dataDoc, this.props.fieldKey); } + clipboardTextSerializer = (slice: Slice): string => { + let text = "", separated = true; + const from = 0, to = slice.content.size; + slice.content.nodesBetween(from, to, (node, pos) => { + if (node.isText) { + text += node.text!.slice(Math.max(from, pos) - pos, to - pos); + separated = false; + } else if (!separated && node.isBlock) { + text += "\n"; + separated = true; + } else if (node.type.name === "hard_break") { + text += "\n"; + } + }, 0); + return text; + } + + sliceSingleNode(slice: Slice) { + return slice.openStart === 0 && slice.openEnd === 0 && slice.content.childCount === 1 ? slice.content.firstChild : null; + } + + handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => { + return false; + function addMarkToFrag(frag: Fragment) { + const nodes: Node[] = []; + frag.forEach(node => nodes.push(addLinkMark(node))); + return Fragment.fromArray(nodes); + } + function addLinkMark(node: Node) { + if (!node.isText) { + const content = addMarkToFrag(node.content); + return node.copy(content); + } + const marks = [...node.marks]; + const linkIndex = marks.findIndex(mark => mark.type.name === "link"); + const link = view.state.schema.mark(view.state.schema.marks.link, { href: "http://localhost:1050/doc/[link document id]", location: "onRight" }); + if (linkIndex !== -1) { + marks.splice(linkIndex, 1, link); + } else { + marks.push(link); + } + return node.mark(marks); + } + let frag = addMarkToFrag(slice.content); + slice = new Slice(frag, slice.openStart, slice.openEnd); + var tr = view.state.tr.replaceSelection(slice); + view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste")); + return true; + } + private setupEditor(config: any, doc: Doc, fieldKey: string) { let field = doc ? Cast(doc[fieldKey], RichTextField) : undefined; let startup = StrCast(doc.documentText); @@ -270,7 +319,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe nodeViews: { image(node, view, getPos) { return new ImageResizeView(node, view, getPos); }, star(node, view, getPos) { return new SummarizedView(node, view, getPos); } - } + }, + clipboardTextSerializer: this.clipboardTextSerializer, + handlePaste: this.handlePaste, }); if (startup) { Doc.GetProto(doc).documentText = undefined; diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 1eda7d1fb..1a4af04f8 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -19,6 +19,7 @@ import { DocumentType } from "../../documents/Documents"; interface Props { docView: DocumentView; changeFlyout: () => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; } @observer @@ -39,7 +40,13 @@ export class LinkMenu extends React.Component<Props> { let linkItems: Array<JSX.Element> = []; groups.forEach((group, groupType) => { linkItems.push( - <LinkMenuGroup key={groupType} sourceDoc={this.props.docView.props.Document} group={group} groupType={groupType} showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)} /> + <LinkMenuGroup + key={groupType} + sourceDoc={this.props.docView.props.Document} + group={group} + groupType={groupType} + showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)} + addDocTab={this.props.addDocTab} /> ); }); diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index 3637807ad..0cb216aa6 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -21,6 +21,7 @@ interface LinkMenuGroupProps { group: Doc[]; groupType: string; showEditor: (linkDoc: Doc) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; } @observer @@ -83,6 +84,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); if (destination && this.props.sourceDoc) { return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]} groupType={this.props.groupType} + addDocTab={this.props.addDocTab} linkDoc={linkDoc} sourceDoc={this.props.sourceDoc} destinationDoc={destination} showEditor={this.props.showEditor} />; } }); diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index d4c92c9f2..1d4fcad69 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -12,6 +12,7 @@ import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; import { DragLinkAsDocument } from '../../util/DragManager'; import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { SelectionManager } from '../../util/SelectionManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -21,6 +22,7 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; } @observer @@ -42,18 +44,24 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { let targetContext = await Cast(proto.targetContext, Doc); let sourceContext = await Cast(proto.sourceContext, Doc); let self = this; - if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { + + + let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + if (e.ctrlKey) { + dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); + } + + if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(targetContext!)); + } + else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); + } + else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page))); } - else if (!((this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) || (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext))) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(document, undefined)); - } else { - if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(targetContext!, undefined)); - } - else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => CollectionDockingView.Instance.AddRightSplit(sourceContext!, undefined)); - } + else { + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc); } } |
