From 4859d4e3f5827c3341d43d19a5309d2ec25ab67b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 1 Apr 2020 17:15:14 -0400 Subject: fixed warnings and some compile errors. Made a key value layout and extened DocumentBox to have a childLayoutKey field --- src/client/views/DocumentButtonBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index e673189f9..c6fb9ad0b 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -39,7 +39,7 @@ library.add(faCheckCircle); library.add(faCloudUploadAlt); library.add(faSyncAlt); library.add(faShare); -library.add(faPhotoVideo) +library.add(faPhotoVideo); const cloud: IconProp = "cloud-upload-alt"; const fetch: IconProp = "sync-alt"; -- cgit v1.2.3-70-g09d2 From 6ae33795b8d23a5dd14593ba8963cf14ec0b2a0e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 1 Apr 2020 20:56:27 -0400 Subject: fixed document box to have sizable borders using x/ypadding. enabled upSelector to select documentBox --- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/nodes/DocumentBox.scss | 4 -- src/client/views/nodes/DocumentBox.tsx | 77 +++++++++++++++++++-------------- 3 files changed, 46 insertions(+), 37 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index c6fb9ad0b..b0c701b65 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -312,7 +312,7 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | render() { if (!this.view0) return (null); - const isText = this.view0.props.Document.data instanceof RichTextField; // bcz: Todo - can't assume layout is using the 'data' field. need to add fieldKey to DocumentView + const isText = this.view0.props.Document[Doc.LayoutFieldKey(this.view0.props.Document)] instanceof RichTextField; const considerPull = isText && this.considerGoogleDocsPull; const considerPush = isText && this.considerGoogleDocsPush; return
diff --git a/src/client/views/nodes/DocumentBox.scss b/src/client/views/nodes/DocumentBox.scss index b7d06b364..6fc87e4f1 100644 --- a/src/client/views/nodes/DocumentBox.scss +++ b/src/client/views/nodes/DocumentBox.scss @@ -3,13 +3,9 @@ height: 100%; pointer-events: all; background: gray; - border: #00000021 solid 15px; - border-top: #0000005e inset 15px; - border-bottom: #0000005e outset 15px; .documentBox-lock { margin: auto; color: white; - margin-top: -15px; position: absolute; } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx index 655dc5de2..9d1c08389 100644 --- a/src/client/views/nodes/DocumentBox.tsx +++ b/src/client/views/nodes/DocumentBox.tsx @@ -5,7 +5,7 @@ import { Doc, Field } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { makeInterface } from "../../../new_fields/Schema"; import { ComputedField } from "../../../new_fields/ScriptField"; -import { Cast, StrCast } from "../../../new_fields/Types"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { emptyPath } from "../../../Utils"; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; @@ -85,13 +85,15 @@ export class DocumentBox extends DocAnnotatableComponent { let hitWidget: boolean | undefined = false; - if (this._contRef.current!.getBoundingClientRect().top + 15 > e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); - else if (this._contRef.current!.getBoundingClientRect().bottom - 15 < e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); + if (this._contRef.current!.getBoundingClientRect().top + this.yPad > e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); + else if (this._contRef.current!.getBoundingClientRect().bottom - this.yPad < e.clientY) hitWidget = (() => { this.props.select(false); return true; })(); else { - if (this._contRef.current!.getBoundingClientRect().left + 15 > e.clientX) hitWidget = this.prevSelection(); - if (this._contRef.current!.getBoundingClientRect().right - 15 < e.clientX) hitWidget = this.nextSelection(); + if (this._contRef.current!.getBoundingClientRect().left + this.xPad > e.clientX) hitWidget = this.prevSelection(); + if (this._contRef.current!.getBoundingClientRect().right - this.xPad < e.clientX) hitWidget = this.nextSelection(); } if (hitWidget) { (e.nativeEvent as any).formattedHandled = true; @@ -99,39 +101,50 @@ export class DocumentBox extends DocAnnotatableComponent(); - pwidth = () => this.props.PanelWidth() - 30; - pheight = () => this.props.PanelHeight() - 30; - getTransform = () => this.props.ScreenToLocalTransform().translate(-15, -15); + pwidth = () => this.props.PanelWidth() - 2 * this.xPad; + pheight = () => this.props.PanelHeight() - 2 * this.yPad; + getTransform = () => this.props.ScreenToLocalTransform().translate(-this.xPad, -this.yPad); + get renderContents() { + const containedDoc = this.contentDoc[this.props.fieldKey]; + const contents = !(containedDoc instanceof Doc) ? (null) : ; + return contents; + } render() { TraceMobx(); - const containedDoc = this.contentDoc[this.props.fieldKey]; return
-
+ style={{ + background: StrCast(this.props.Document.backgroundColor), + border: `#00000021 solid ${this.xPad}px`, + borderTop: `#0000005e solid ${this.yPad}px`, + borderBottom: `#0000005e solid ${this.yPad}px`, + }}> +
- {!(containedDoc instanceof Doc) ? (null) : } -
; + {this.renderContents} +
; } } -- cgit v1.2.3-70-g09d2 From cf77e5f861c0927956e5453873839c81f0229374 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 1 Apr 2020 23:24:12 -0400 Subject: made it possible to link from one text selection to another --- src/client/util/DragManager.ts | 1 + src/client/views/DocumentButtonBar.tsx | 9 +++----- src/client/views/nodes/DocumentContentsView.tsx | 4 +++- src/client/views/nodes/DocumentView.tsx | 7 +++++- src/client/views/nodes/FormattedTextBox.tsx | 29 +++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 8 deletions(-) (limited to 'src/client/views/DocumentButtonBar.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 63a11c85a..8d3f6751e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -148,6 +148,7 @@ export namespace DragManager { linkSourceDocument: Doc; dontClearTextBox?: boolean; linkDocument?: Doc; + linkDropCallback?: (data: LinkDragData) => void; } export class ColumnDragData { constructor(colKey: SchemaHeaderField) { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index b0c701b65..b95cc6627 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -4,12 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../new_fields/Doc"; -import { Id } from '../../new_fields/FieldSymbols'; import { RichTextField } from '../../new_fields/RichTextField'; import { NumCast, StrCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; -import RichTextMenu from '../util/RichTextMenu'; import { UndoManager } from "../util/UndoManager"; import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; @@ -121,10 +119,9 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop if (this.view0 && linkDoc) { Doc.GetProto(linkDoc).linkRelationship = "hyperlink"; - - const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; - const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : ""; - const text = RichTextMenu.Instance.MakeLinkToSelection(linkDoc[Id], anchor2Title, e.ctrlKey ? "onRight" : "inTab", anchor2Id); + dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData); + runInAction(() => this.view0!._link = linkDoc); + setTimeout(action(() => this.view0!._link = undefined), 0); } linkDrag?.end(); }, diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index c250da874..da035a6ce 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -58,7 +58,9 @@ export class DocumentContentsView extends React.Component void, layoutKey: string, forceLayout?: string, - forceFieldKey?: string + forceFieldKey?: string, + hideOnLeave?:boolean, + makeLink?: () => Opt; }> { @computed get layout(): string { TraceMobx(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7770a5caf..d8bbd88ce 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -40,7 +40,6 @@ import { ScriptBox } from '../ScriptBox'; import { ScriptingRepl } from '../ScriptingRepl'; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; -import { FormattedTextBox } from './FormattedTextBox'; import React = require("react"); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField'; @@ -967,6 +966,7 @@ export class DocumentView extends DocComponent(Docu Document={this.props.Document} DataDoc={this.props.DataDoc} LayoutDoc={this.props.LayoutDoc} + makeLink={this.makeLink} fitToBox={this.props.fitToBox} LibraryPath={this.props.LibraryPath} addDocument={this.props.addDocument} @@ -1002,6 +1002,11 @@ export class DocumentView extends DocComponent(Docu const ept = Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1_timecode : linkDoc.anchor2_timecode; return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true; } +c + @observable _link:Opt; + makeLink = () => { + return this._link; + } @computed get innards() { TraceMobx(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index bc43beab9..241345f3e 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -54,6 +54,7 @@ library.add(faSmile, faTextHeight, faUpload); export interface FormattedTextBoxProps { hideOnLeave?: boolean; + makeLink?: () => Opt; } const richTextSchema = createSchema({ @@ -91,6 +92,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & private _pullReactionDisposer: Opt; private _pushReactionDisposer: Opt; private _buttonBarReactionDisposer: Opt; + private _linkMakerDisposer: Opt; private _scrollDisposer: Opt; private dropDisposer?: DragManager.DragDropDisposer; @@ -282,8 +284,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.stopPropagation(); // } } // otherwise, fall through to outer collection to handle drop + } else if (de.complete.linkDragData) { + de.complete.linkDragData.linkDropCallback = this.linkDrop; } } + linkDrop = (data: DragManager.LinkDragData) => { + const linkDoc = data.linkDocument!; + const anchor1Title = linkDoc.anchor1 instanceof Doc ? StrCast(linkDoc.anchor1.title) : "-untitled-"; + const anchor1Id = linkDoc.anchor1 instanceof Doc ? linkDoc.anchor1[Id] : ""; + this.makeLinkToSelection(linkDoc[Id], anchor1Title, "onRight", anchor1Id) + } getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null { let offset = 0; @@ -513,6 +523,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & }; } + makeLinkToSelection(linkDocId: string, title: string, location: string, targetDocId: string) { + if (this._editorView) { + const link = this._editorView.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId }); + this._editorView.dispatch(this._editorView.state.tr.removeMark(this._editorView.state.selection.from, this._editorView.state.selection.to, this._editorView.state.schema.marks.link). + addMark(this._editorView.state.selection.from, this._editorView.state.selection.to, link)); + } + } componentDidMount() { this._buttonBarReactionDisposer = reaction( () => DocumentButtonBar.Instance, @@ -523,6 +540,17 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } } ); + this._linkMakerDisposer = reaction( + () => this.props.makeLink?.(), + (linkDoc: Opt) => { + if (linkDoc) { + const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; + const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : ""; + this.makeLinkToSelection(linkDoc[Id], anchor2Title, "onRight", anchor2Id); + } + }, + { fireImmediately: true } + ); this._reactionDisposer = reaction( () => { @@ -858,6 +886,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._searchReactionDisposer?.(); this._recordReactionDisposer?.(); this._buttonBarReactionDisposer?.(); + this._linkMakerDisposer?.(); this._editorView?.destroy(); } -- cgit v1.2.3-70-g09d2