From 747581ac65f706710becad034c5f5abff76b8e51 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 9 Jun 2020 17:26:05 -0400 Subject: fixed lots of errors/warnings. added 'a' to be able embed documents on drop. added 'l' toggle to perist lasso/marquee mode. --- src/client/views/nodes/formattedText/DashFieldView.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/client/views/nodes/formattedText/DashFieldView.tsx') diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index d05e8f1ea..9a1b909c1 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -12,6 +12,7 @@ import React = require("react"); import * as ReactDOM from 'react-dom'; import "./DashFieldView.scss"; import { observer } from "mobx-react"; +import { DocUtils } from "../../../documents/Documents"; export class DashFieldView { @@ -117,7 +118,7 @@ export class DashFieldViewInternal extends React.Component { if (e.key === "Enter") { // handle the enter key by "submitting" the current text to Dash's database. - e.ctrlKey && Doc.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: span.textContent! }]); + e.ctrlKey && DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: span.textContent! }]); this.updateText(span.textContent!, true); e.preventDefault();// prevent default to avoid a newline from being generated and wiping out this field view } @@ -147,7 +148,7 @@ export class DashFieldViewInternal extends React.Component (forceMatch ? StrCast(opt.title).startsWith(newText) : StrCast(opt.title) === newText) && (modText = StrCast(opt.title))); if (modText) { // elementfieldSpan.innerHTML = this._dashDoc![this._fieldKey as string] = modText; - Doc.addFieldEnumerations(this._textBoxDoc, this._fieldKey, []); + DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, []); this._dashDoc![this._fieldKey] = modText; } // if the text starts with a ':=' then treat it as an expression by making a computed field from its value storing it in the key else if (nodeText.startsWith(":=")) { @@ -167,7 +168,7 @@ export class DashFieldViewInternal extends React.Component { e.stopPropagation(); - const collview = await Doc.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: this._fieldKey }]); + const collview = await DocUtils.addFieldEnumerations(this._textBoxDoc, this._fieldKey, [{ title: this._fieldKey }]); collview instanceof Doc && this.props.tbox.props.addDocTab(collview, "onRight"); } -- cgit v1.2.3-70-g09d2 From 279e71d098053dc2ca5b69e6e502a95dab230daa Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 15 Jun 2020 11:58:04 -0400 Subject: added a linkView and changed display of docFieldView to inline to allow text wrapping on the same line as the fieldLabel --- src/client/documents/Documents.ts | 4 +- src/client/util/CurrentUserUtils.ts | 58 ++++++++++++++++++++-- src/client/views/nodes/ComparisonBox.tsx | 6 +-- src/client/views/nodes/DocumentView.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.scss | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 19 ++++--- 6 files changed, 72 insertions(+), 19 deletions(-) (limited to 'src/client/views/nodes/formattedText/DashFieldView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2ecc8c8b7..002bfe6a2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -606,7 +606,6 @@ export namespace Docs { selection: { type: "text", anchor: 1, head: 1 }, storedMarks: [] }; - const field = text ? new RichTextField(JSON.stringify(rtf), text) : undefined; return InstanceFromProto(Prototypes.get(DocumentType.RTF), field, options, undefined, fieldKey); } @@ -823,7 +822,8 @@ export namespace DocUtils { if (sv && sv.props.ContainingCollectionDoc === target.doc) return; if (target.doc === Doc.UserDoc()) return undefined; - const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship }, id); + const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView" }, id); + linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null); Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1.title +" (" + (self.linkRelationship||"to") +") " + self.anchor2.title'); Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(self)"); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 0acfb72c6..47672f7c9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -86,6 +86,52 @@ export class CurrentUserUtils { }); } + if (doc["template-button-link"] === undefined) { + const linkTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created + Doc.GetProto(linkTemplate).layout = + "
" + + " " + + " " + + "
"; + linkTemplate.isTemplateDoc = makeTemplate(linkTemplate, true, "linkView"); + + const rtf2 = { + doc: { + type: "doc", content: [ + { + type: "paragraph", + content: [{ + type: "dashField", + attrs: { + fieldKey: "src", + hideKey: false + } + }] + }, + { type: "paragraph" }, + { + type: "paragraph", + content: [{ + type: "dashField", + attrs: { + fieldKey: "dst", + hideKey: false + } + }] + }] + }, + selection: { type: "text", anchor: 1, head: 1 }, + storedMarks: [] + }; + linkTemplate.header = new RichTextField(JSON.stringify(rtf2), ""); + + doc["template-button-link"] = CurrentUserUtils.ficon({ + onDragStart: ScriptField.MakeFunction('makeDelegate(this.dragFactory)'), + dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, + removeDropProperties: new List(["dropAction"]), title: "link view", icon: "window-maximize" + }); + } + if (doc["template-button-switch"] === undefined) { const { FreeformDocument, MulticolumnDocument, TextDocument } = Docs.Create; @@ -168,17 +214,21 @@ export class CurrentUserUtils { }); } + const requiredTypes = [ + doc["template-button-slides"] as Doc, + doc["template-button-description"] as Doc, + doc["template-button-query"] as Doc, + doc["template-button-detail"] as Doc, + doc["template-button-link"] as Doc, + doc["template-button-switch"] as Doc]; if (doc["template-buttons"] === undefined) { - doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument([doc["template-button-slides"] as Doc, doc["template-button-description"] as Doc, - doc["template-button-query"] as Doc, doc["template-button-detail"] as Doc, doc["template-button-switch"] as Doc], { + doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, { title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title", _autoHeight: true, _width: 500, columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), })); } else { const curButnTypes = Cast(doc["template-buttons"], Doc, null); - const requiredTypes = [doc["template-button-slides"] as Doc, doc["template-button-description"] as Doc, - doc["template-button-query"] as Doc, doc["template-button-detail"] as Doc, doc["template-button-switch"] as Doc]; DocListCastAsync(curButnTypes.data).then(async curBtns => { await Promise.all(curBtns!); requiredTypes.map(btype => Doc.AddDocToList(curButnTypes, "data", btype)); diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index cce60628d..14a2c25bf 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -76,12 +76,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { return
e.stopPropagation()} // prevent triggering slider movement in registerSliding - onClick={e => this.clearDoc(e, `${which}Doc`)}> + onClick={e => this.clearDoc(e, `compareBox-${which}`)}>
; }; const displayDoc = (which: string) => { - const whichDoc = Cast(this.dataDoc[`${which}Doc`], Doc, null); + const whichDoc = Cast(this.dataDoc[`compareBox-${which}`], Doc, null); return whichDoc ? <> {clearButton(which)} @@ -93,7 +93,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent { return
this.registerSliding(e, cover)} - ref={ele => this.createDropTarget(ele, `${which}Doc`, index)} > + ref={ele => this.createDropTarget(ele, `compareBox-${which}`, index)} > {displayDoc(which)}
; }; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index e4e4dfdd6..35bf5344e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -335,7 +335,7 @@ export class DocumentView extends DocComponent(Docu this.props.addDocTab(alias, "onRight"); // UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"); //ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click"); - } else if (this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { + } else if (this.props.Document.links && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) { DocListCast(this.props.Document.links).length && this.followLinkClick(e.altKey, e.ctrlKey, e.shiftKey); } else { if ((this.props.Document.onDragStart || (this.props.Document.rootDocument)) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTEmplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part diff --git a/src/client/views/nodes/formattedText/DashFieldView.scss b/src/client/views/nodes/formattedText/DashFieldView.scss index 35ff9c1e6..23cf1e79b 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.scss +++ b/src/client/views/nodes/formattedText/DashFieldView.scss @@ -25,7 +25,7 @@ margin-left: 2px; margin-right: 5px; position: relative; - display: inline-block; + display: inline; background-color: rgba(155, 155, 155, 0.24); span { min-width: 100%; diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 9a1b909c1..60a9c2a27 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -103,11 +103,14 @@ export class DashFieldViewInternal extends React.Component { - r?.addEventListener("keydown", e => this.fieldSpanKeyDown(e, r)); - r?.addEventListener("blur", e => r && this.updateText(r.textContent!, false)); - r?.addEventListener("pointerdown", action((e) => this._showEnumerables = true)); - }} > + return { + r?.addEventListener("keydown", e => this.fieldSpanKeyDown(e, r)); + r?.addEventListener("blur", e => r && this.updateText(r.textContent!, false)); + r?.addEventListener("pointerdown", action((e) => this._showEnumerables = true)); + }} > {strVal} ; } @@ -205,9 +208,9 @@ export class DashFieldViewInternal extends React.Component} -
- {this.fieldValueContent} -
+ {/*
*/} + {this.fieldValueContent} + {/*
*/} {!this._showEnumerables ? (null) :
} -- cgit v1.2.3-70-g09d2 From 997035dfaf78ec0bcb4ec1b85e2e3f7dae410ca0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 16 Jun 2020 12:40:21 -0400 Subject: cleaned up some of the prosemirror plugin views. --- .../nodes/formattedText/DashDocCommentView.tsx | 38 +++--- .../views/nodes/formattedText/DashFieldView.tsx | 7 +- .../views/nodes/formattedText/FootnoteView.tsx | 17 +-- .../views/nodes/formattedText/FormattedTextBox.tsx | 8 +- .../formattedText/FormattedTextBoxComment.tsx | 7 +- .../views/nodes/formattedText/RichTextSchema.tsx | 96 +------------- .../views/nodes/formattedText/SummaryView.tsx | 144 +++++++-------------- 7 files changed, 86 insertions(+), 231 deletions(-) (limited to 'src/client/views/nodes/formattedText/DashFieldView.tsx') diff --git a/src/client/views/nodes/formattedText/DashDocCommentView.tsx b/src/client/views/nodes/formattedText/DashDocCommentView.tsx index 2d4e360a8..ad204f3df 100644 --- a/src/client/views/nodes/formattedText/DashDocCommentView.tsx +++ b/src/client/views/nodes/formattedText/DashDocCommentView.tsx @@ -4,6 +4,10 @@ import { Doc } from "../../../../fields/Doc"; import { DocServer } from "../../../DocServer"; import React = require("react"); + +// creates an inline comment in a note when '>>' is typed. +// the comment sits on the right side of the note and vertically aligns with its anchor in the text. +// the comment can be toggled on/off with the '<-' text anchor. export class DashDocCommentView { _fieldWrapper: HTMLDivElement; // container for label and value @@ -19,11 +23,7 @@ export class DashDocCommentView { this._fieldWrapper.onkeyup = function (e: any) { e.stopPropagation(); }; this._fieldWrapper.onmousedown = function (e: any) { e.stopPropagation(); }; - ReactDOM.render(, this._fieldWrapper); + ReactDOM.render(, this._fieldWrapper); (this as any).dom = this._fieldWrapper; } @@ -35,12 +35,11 @@ export class DashDocCommentView { } interface IDashDocCommentViewInternal { - node: any; + docid: string; view: any; getPos: any; } - export class DashDocCommentViewInternal extends React.Component{ constructor(props: IDashDocCommentViewInternal) { @@ -51,18 +50,14 @@ export class DashDocCommentViewInternal extends React.Component dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); + DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); e.preventDefault(); e.stopPropagation(); }; onPointerEnterCollapsed(e: any) { - DocServer.GetRefField(this.props.node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); + DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); e.preventDefault(); e.stopPropagation(); }; @@ -75,7 +70,7 @@ export class DashDocCommentViewInternal extends React.Component { - expand && DocServer.GetRefField(this.props.node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); + expand && DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); try { this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + (expand ? 2 : 1)))); } catch (e) { } }, 0); } @@ -87,16 +82,17 @@ export class DashDocCommentViewInternal extends React.Component { // search forward in the prosemirror doc for the attached dashDocNode that is the target of the comment anchor - for (let i = this.props.getPos() + 1; i < this.props.view.state.doc.content.size; i++) { - const m = this.props.view.state.doc.nodeAt(i); - if (m && m.type === this.props.view.state.schema.nodes.dashDoc && m.attrs.docid === this.props.node.attrs.docid) { + const state = this.props.view.state; + for (let i = this.props.getPos() + 1; i < state.doc.content.size; i++) { + const m = state.doc.nodeAt(i); + if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docid === this.props.docid) { return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any, pos: number, hidden: boolean }; } } - const dashDoc = this.props.view.state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: this.props.node.attrs.docid, float: "right" }); - this.props.view.dispatch(this.props.view.state.tr.insert(this.props.getPos() + 1, dashDoc)); - setTimeout(() => { try { this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + 2))); } catch (e) { } }, 0); + const dashDoc = state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: this.props.docid, float: "right" }); + this.props.view.dispatch(state.tr.insert(this.props.getPos() + 1, dashDoc)); + setTimeout(() => { try { this.props.view.dispatch(state.tr.setSelection(TextSelection.create(state.tr.doc, this.props.getPos() + 2))); } catch (e) { } }, 0); return undefined; }; @@ -104,7 +100,7 @@ export class DashDocCommentViewInternal extends React.Component, this._fieldWrapper); (this as any).dom = this._fieldWrapper; } - destroy() { - ReactDOM.unmountComponentAtNode(this._fieldWrapper); - } + destroy() { ReactDOM.unmountComponentAtNode(this._fieldWrapper); } selectNode() { } - } + interface IDashFieldViewInternal { fieldKey: string; docid: string; diff --git a/src/client/views/nodes/formattedText/FootnoteView.tsx b/src/client/views/nodes/formattedText/FootnoteView.tsx index 1d21f2ae9..1683cc972 100644 --- a/src/client/views/nodes/formattedText/FootnoteView.tsx +++ b/src/client/views/nodes/formattedText/FootnoteView.tsx @@ -28,15 +28,11 @@ export class FootnoteView { } selectNode() { - const attrs = { ...this.node.attrs }; - attrs.visibility = true; this.dom.classList.add("ProseMirror-selectednode"); if (!this.innerView) this.open(); } deselectNode() { - const attrs = { ...this.node.attrs }; - attrs.visibility = false; this.dom.classList.remove("ProseMirror-selectednode"); if (this.innerView) this.close(); } @@ -78,7 +74,7 @@ export class FootnoteView { }) as any } }); - setTimeout(() => this.innerView && this.innerView.docView.setSelection(0, 0, this.innerView.root, true), 0); + setTimeout(() => this.innerView?.docView.setSelection(0, 0, this.innerView.root, true), 0); } ignore = (e: PointerEvent) => { @@ -88,13 +84,11 @@ export class FootnoteView { toggle = () => { if (this.innerView) this.close(); - else { - this.open(); - } + else this.open(); } close() { - this.innerView && this.innerView.destroy(); + this.innerView?.destroy(); this.innerView = null; this.dom.textContent = ""; } @@ -106,8 +100,7 @@ export class FootnoteView { if (!tr.getMeta("fromOutside")) { const outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1); for (const transaction of transactions) { - const steps = transaction.steps; - for (const step of steps) { + for (const step of transaction.steps) { outerTr.step(step.map(offsetMap)); } } @@ -139,7 +132,7 @@ export class FootnoteView { } stopEvent(event: any) { - return this.innerView && this.innerView.dom.contains(event.target); + return this.innerView?.dom.contains(event.target); } ignoreMutation() { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 99cd503ec..ba36a1618 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -35,8 +35,8 @@ import buildKeymap from "./ProsemirrorExampleTransfer"; import RichTextMenu from './RichTextMenu'; import { RichTextRules } from "./RichTextRules"; -import { DashDocView } from "./DashDocView"; -// import { DashDocView } from "./RichTextSchema"; +//import { DashDocView } from "./DashDocView"; +import { DashDocView } from "./RichTextSchema"; import { DashDocCommentView } from "./DashDocCommentView"; import { DashFieldView } from "./DashFieldView"; @@ -903,9 +903,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp }, dispatchTransaction: this.dispatchTransaction, nodeViews: { - dashComment(node, view, getPos) { console.log("rendering dashComment"); return new DashDocCommentView(node, view, getPos); }, - dashField(node, view, getPos) { return new DashFieldView(node, view, getPos, self); }, + dashComment(node, view, getPos) { return new DashDocCommentView(node, view, getPos); }, dashDoc(node, view, getPos) { return new DashDocView(node, view, getPos, self); }, + dashField(node, view, getPos) { return new DashFieldView(node, view, getPos, self); }, summary(node, view, getPos) { return new SummaryView(node, view, getPos); }, ordered_list(node, view, getPos) { return new OrderedListView(); }, footnote(node, view, getPos) { return new FootnoteView(node, view, getPos); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 5ac173602..000b3c2e5 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -50,7 +50,9 @@ export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (mark return after; } - +// this view appears when clicking on text that has a hyperlink which is configured to show a preview of its target. +// this will also display metadata information about text when the view is configured to display things like other people who authored text. +// export class FormattedTextBoxComment { static tooltip: HTMLElement; static tooltipText: HTMLElement; @@ -235,9 +237,6 @@ export class FormattedTextBoxComment { FormattedTextBoxComment.tooltip.style.width = NumCast(target._width) ? `${NumCast(target._width)}` : "100%"; FormattedTextBoxComment.tooltip.style.height = NumCast(target._height) ? `${NumCast(target._height)}` : "100%"; } - // let ext = (target && target.type !== DocumentType.PDFANNO && Doc.fieldExtensionDoc(target, "data")) || target; // try guessing that the target doc's data is in the 'data' field. probably need an 'overviewLayout' and then just display the target Document .... - // let text = ext && StrCast(ext.text); - // ext && (FormattedTextBoxComment.tooltipText.textContent = (target && target.type === DocumentType.PDFANNO ? "Quoted from " : "") + "=> " + (text || StrCast(ext.title))); } }); } diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx index 79abfa995..05557e22a 100644 --- a/src/client/views/nodes/formattedText/RichTextSchema.tsx +++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx @@ -1,95 +1,20 @@ -import { IReactionDisposer, observable, reaction, runInAction } from "mobx"; -import { baseKeymap, toggleMark } from "prosemirror-commands"; -import { redo, undo } from "prosemirror-history"; -import { keymap } from "prosemirror-keymap"; -import { DOMOutputSpecArray, Fragment, MarkSpec, Node, NodeSpec, Schema, Slice } from "prosemirror-model"; -import { bulletList, listItem, orderedList } from 'prosemirror-schema-list'; -import { EditorState, NodeSelection, Plugin, TextSelection } from "prosemirror-state"; -import { StepMap } from "prosemirror-transform"; -import { EditorView } from "prosemirror-view"; +import { IReactionDisposer, reaction } from "mobx"; +import { NodeSelection } from "prosemirror-state"; import * as ReactDOM from 'react-dom'; -import { Doc, DocListCast, Field, HeightSym, WidthSym } from "../../../../fields/Doc"; +import { Doc, HeightSym, WidthSym } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; -import { List } from "../../../../fields/List"; import { ObjectField } from "../../../../fields/ObjectField"; -import { listSpec } from "../../../../fields/Schema"; -import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField"; import { ComputedField } from "../../../../fields/ScriptField"; -import { BoolCast, Cast, NumCast, StrCast, FieldValue } from "../../../../fields/Types"; -import { emptyFunction, returnEmptyString, returnFalse, returnOne, Utils, returnZero } from "../../../../Utils"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../../fields/Types"; +import { emptyFunction, returnEmptyString, returnFalse, returnZero, Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from "../../../documents/Documents"; -import { CollectionViewType } from "../../collections/CollectionView"; +import { Transform } from "../../../util/Transform"; import { DocumentView } from "../DocumentView"; import { FormattedTextBox } from "./FormattedTextBox"; -import { DocumentManager } from "../../../util/DocumentManager"; -import { Transform } from "../../../util/Transform"; import React = require("react"); - -// export class DashDocCommentView { -// _collapsed: HTMLElement; -// _view: any; -// constructor(node: any, view: any, getPos: any) { - -// console.log("DashDocCommentView constructor"); - -// //moved -// this._collapsed = document.createElement("span"); -// this._collapsed.className = "formattedTextBox-inlineComment"; -// this._collapsed.id = "DashDocCommentView-" + node.attrs.docid; -// this._view = view; -// //moved -// const targetNode = () => { // search forward in the prosemirror doc for the attached dashDocNode that is the target of the comment anchor -// for (let i = getPos() + 1; i < view.state.doc.content.size; i++) { -// const m = view.state.doc.nodeAt(i); -// if (m && m.type === view.state.schema.nodes.dashDoc && m.attrs.docid === node.attrs.docid) { -// return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any, pos: number, hidden: boolean }; -// } -// } -// const dashDoc = view.state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: node.attrs.docid, float: "right" }); -// view.dispatch(view.state.tr.insert(getPos() + 1, dashDoc)); -// setTimeout(() => { try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + 2))); } catch (e) { } }, 0); -// return undefined; -// }; -// //moved -// this._collapsed.onpointerdown = (e: any) => { -// e.stopPropagation(); -// }; -// //moved -// this._collapsed.onpointerup = (e: any) => { -// const target = targetNode(); -// if (target) { -// const expand = target.hidden; -// const tr = view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true }); -// view.dispatch(tr.setSelection(TextSelection.create(tr.doc, getPos() + (expand ? 2 : 1)))); // update the attrs -// setTimeout(() => { -// expand && DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); -// try { view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos() + (expand ? 2 : 1)))); } catch (e) { } -// }, 0); -// } -// e.stopPropagation(); -// }; -// //moved -// this._collapsed.onpointerenter = (e: any) => { -// DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); -// e.preventDefault(); -// e.stopPropagation(); -// }; -// //moved -// this._collapsed.onpointerleave = (e: any) => { -// DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); -// e.preventDefault(); -// e.stopPropagation(); -// }; - -// (this as any).dom = this._collapsed; -// } -// //moved -// selectNode() { } -// } - export class DashDocView { _dashSpan: HTMLDivElement; _outer: HTMLElement; @@ -132,10 +57,6 @@ export class DashDocView { this._dashSpan.style.whiteSpace = "normal"; this._dashSpan.onpointerleave = () => { - - console.log("DashDocView_dashSpan.onpointerleave"); // SMM - console.log("DashDocCommentView-id=", node.attrs.docid); // SMM - const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { (ele as HTMLDivElement).style.backgroundColor = ""; @@ -143,9 +64,6 @@ export class DashDocView { }; this._dashSpan.onpointerenter = () => { - console.log("DashDocView_dashSpan.onpointerenter"); // SMM - console.log("DashDocCommentView-id=", node.attrs.docid); // SMM - const ele = document.getElementById("DashDocCommentView-" + node.attrs.docid); if (ele) { (ele as HTMLDivElement).style.backgroundColor = "orange"; @@ -208,7 +126,7 @@ export class DashDocView { this._dashSpan.style.height = this._outer.style.height = Math.max(20, dim[1]) + "px"; this._outer.style.border = "1px solid " + StrCast(finalLayout.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray")); }, { fireImmediately: true }); - + const doReactRender = (finalLayout: Doc, resolvedDataDoc: Doc) => { ReactDOM.unmountComponentAtNode(this._dashSpan); diff --git a/src/client/views/nodes/formattedText/SummaryView.tsx b/src/client/views/nodes/formattedText/SummaryView.tsx index e5328496c..922285bd0 100644 --- a/src/client/views/nodes/formattedText/SummaryView.tsx +++ b/src/client/views/nodes/formattedText/SummaryView.tsx @@ -1,108 +1,45 @@ -import { IReactionDisposer, observable, computed, action } from "mobx"; -import { Fragment, Node, Slice } from "prosemirror-model"; import { TextSelection } from "prosemirror-state"; +import { Fragment, Node, Slice } from "prosemirror-model"; import * as ReactDOM from 'react-dom'; import React = require("react"); -// import { dom } from "@fortawesome/fontawesome-svg-core"; -// import { observer } from "mobx-react"; +// an elidable textblock that collapses when its '<-' is clicked and expands when its '...' anchor is clicked. +// this node actively edits prosemirror (as opposed to just changing how things are rendered) and thus doesn't +// really need a react view. However, it would be cleaner to figure out how to do this just as a react rendering +// method instead of changing prosemirror's text when the expand/elide buttons are clicked. export class SummaryView { - - _fieldWrapper: HTMLDivElement; // container for label + _fieldWrapper: HTMLSpanElement; // container for label and value constructor(node: any, view: any, getPos: any) { - console.log("You are here") - this._fieldWrapper = document.createElement("div"); - this._fieldWrapper.style.fontWeight = "bold"; - this._fieldWrapper.style.position = "relative"; - this._fieldWrapper.style.display = "inline-block"; + const self = this; + this._fieldWrapper = document.createElement("span"); + this._fieldWrapper.className = this.className(node.attrs.visibility); + this._fieldWrapper.onpointerdown = function (e: any) { self.onPointerDown(e, node, view, getPos); } + this._fieldWrapper.onkeypress = function (e: any) { e.stopPropagation(); }; + this._fieldWrapper.onkeydown = function (e: any) { e.stopPropagation(); }; + this._fieldWrapper.onkeyup = function (e: any) { e.stopPropagation(); }; + this._fieldWrapper.onmousedown = function (e: any) { e.stopPropagation(); }; const js = node.toJSON; - node.toJSON = function () { - return js.apply(this, arguments); - }; + node.toJSON = function () { return js.apply(this, arguments); }; - console.log("rendering new SummaryViewInternal") - ReactDOM.render(, this._fieldWrapper); + ReactDOM.render(, this._fieldWrapper); (this as any).dom = this._fieldWrapper; } + className = (visible: boolean) => "formattedTextBox-summarizer" + (visible ? "" : "-collapsed"); + destroy() { ReactDOM.unmountComponentAtNode(this._fieldWrapper); } selectNode() { } - deselectNode() { } - - destroy() { - ReactDOM.unmountComponentAtNode(this._fieldWrapper); - } -} - -interface ISummaryViewInternal { - node: any; - view: any; - getPos: any; -} - -export class SummaryViewInternal extends React.Component{ - _className: any; - _view: any; - _reactionDisposer: IReactionDisposer | undefined; - - constructor(props: ISummaryViewInternal) { - super(props); - - this._className = this.className(this.props.node.attrs.visibility); - this._view = this.props.view; - this.onPointerDownCollapsed = this.onPointerDownCollapsed.bind(this); - this.updateSummarizedText = this.updateSummarizedText.bind(this); - } - - componentWillUnmount() { - this._reactionDisposer?.(); - } - - - className(visible: boolean) { - return "formattedTextBox-summarizer" + (visible ? "" : "-collapsed"); - } - - onPointerDownCollapsed(e: any) { - const visible = !this.props.node.attrs.visibility; - const attrs = { ...this.props.node.attrs, visibility: visible }; - let textSelection = TextSelection.create(this.props.view.state.doc, this.props.getPos() + 1); - - - if (!visible) { // update summarized text and save in attrs - textSelection = this.updateSummarizedText(this.props.getPos() + 1); - attrs.text = textSelection.content(); - attrs.textslice = attrs.text.toJSON(); - } - - this.props.view.dispatch(this.props.view.state.tr. - setSelection(textSelection). // select the current summarized text (or where it will be if its collapsed) - replaceSelection(!visible ? new Slice(Fragment.fromArray([]), 0, 0) : this.props.node.attrs.text). // collapse/expand it - setNodeMarkup(this.props.getPos(), undefined, attrs)); // update the attrs - - e.preventDefault(); - e.stopPropagation(); - - this._className = this.className(visible); - - } - - updateSummarizedText(start?: any) { - const mtype = this.props.view.state.schema.marks.summarize; - const mtypeInc = this.props.view.state.schema.marks.summarizeInclusive; + updateSummarizedText(start: any, view: any) { + const mtype = view.state.schema.marks.summarize; + const mtypeInc = view.state.schema.marks.summarizeInclusive; let endPos = start; const visited = new Set(); - for (let i: number = start + 1; i < this.props.view.state.doc.nodeSize - 1; i++) { + for (let i: number = start + 1; i < view.state.doc.nodeSize - 1; i++) { let skip = false; - this.props.view.state.doc.nodesBetween(start, i, (node: Node, pos: number, parent: Node, index: number) => { + view.state.doc.nodesBetween(start, i, (node: Node, pos: number, parent: Node, index: number) => { if (node.isLeaf && !visited.has(node) && !skip) { if (node.marks.find((m: any) => m.type === mtype || m.type === mtypeInc)) { visited.add(node); @@ -112,18 +49,33 @@ export class SummaryViewInternal extends React.Component{ } }); } - return TextSelection.create(this.props.view.state.doc, start, endPos); + return TextSelection.create(view.state.doc, start, endPos); } - render() { - return ( - - - - ); - + onPointerDown = (e: any, node: any, view: any, getPos: any) => { + const visible = !node.attrs.visibility; + const attrs = { ...node.attrs, visibility: visible }; + let textSelection = TextSelection.create(view.state.doc, getPos() + 1); + if (!visible) { // update summarized text and save in attrs + textSelection = this.updateSummarizedText(getPos() + 1, view); + attrs.text = textSelection.content(); + attrs.textslice = attrs.text.toJSON(); + } + view.dispatch(view.state.tr. + setSelection(textSelection). // select the current summarized text (or where it will be if its collapsed) + replaceSelection(!visible ? new Slice(Fragment.fromArray([]), 0, 0) : node.attrs.text). // collapse/expand it + setNodeMarkup(getPos(), undefined, attrs)); // update the attrs + e.preventDefault(); + e.stopPropagation(); + this._fieldWrapper.className = this.className(visible); } +} +interface ISummaryView { } +// currently nothing needs to be rendered for the internal view of a summary. +export class SummaryViewInternal extends React.Component { + render() { + return <> ; + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2