From 553fb2a11aa638c35192a1a2f7da99729867e542 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 13 Feb 2020 22:30:32 -0500 Subject: starting a broad cleanup of code. trying to make standard doc field names be more regular --- src/client/documents/Documents.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8304c2a7f..adcdf260d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -22,7 +22,6 @@ import { ImageField, VideoField, AudioField, PdfField, WebField, YoutubeField } import { HtmlField } from "../../new_fields/HtmlField"; import { List } from "../../new_fields/List"; import { Cast, NumCast } from "../../new_fields/Types"; -import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; import { dropActionType } from "../util/DragManager"; @@ -53,7 +52,6 @@ import { InkingStroke } from "../views/InkingStroke"; import { InkField } from "../../new_fields/InkField"; import { InkingControl } from "../views/InkingControl"; import { RichTextField } from "../../new_fields/RichTextField"; -import { Networking } from "../Network"; import { extname } from "path"; import { MessageStore } from "../../server/Message"; const requestImageSize = require('../util/request-image-size'); @@ -92,7 +90,6 @@ export interface DocumentOptions { scale?: number; isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents forceActive?: boolean; - preventTreeViewOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expande/collapse state to be independent of other views of the same document in the tree view layout?: string | Doc; hideHeadings?: boolean; // whether stacking view column headings should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template @@ -109,7 +106,6 @@ export interface DocumentOptions { curPage?: number; currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video) value is in seconds displayTimecode?: number; // the time that a document should be displayed (e.g., time an annotation should be displayed on a video) - documentText?: string; borderRounding?: string; boxShadow?: string; sectionFilter?: string; // field key used to determine headings for sections in stacking and masonry views @@ -124,15 +120,16 @@ export interface DocumentOptions { onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked onPointerDown?: ScriptField; onPointerUp?: ScriptField; + dropConverter?: ScriptField; // script to run when documents are dropped on this Document. dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop - clipboard?: Doc; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop + clipboard?: Doc; icon?: string; sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script - dropConverter?: ScriptField; // script to run when documents are dropped on this Document. strokeWidth?: number; color?: string; + treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view treeViewHideTitle?: boolean; // whether to hide the title of a tree view treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. treeViewOpen?: boolean; // whether this document is expanded in a tree view @@ -141,9 +138,9 @@ export interface DocumentOptions { limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents // [key: string]: Opt; pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown - isExpanded?: boolean; // is linear view expanded - textTransform?: string; // is linear view expanded - letterSpacing?: string; // is linear view expanded + linearViewIsExpanded?: boolean; // is linear view expanded + textTransform?: string; + letterSpacing?: string; } class EmptyBox { -- cgit v1.2.3-70-g09d2 From 5aecc6d75868dcafd0b1bb560ad5a4ad8ab976fa Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 14 Feb 2020 14:25:53 -0500 Subject: cleaned up backgroundColor settings and cluster overrides. added a darkScheme --- src/client/documents/Documents.ts | 2 +- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/MainView.tsx | 27 ++++++++++++----- .../views/collections/CollectionCarouselView.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 3 +- .../views/collections/CollectionSchemaCells.tsx | 3 +- .../views/collections/CollectionStackingView.tsx | 1 + .../views/collections/CollectionTreeView.scss | 9 ++++-- .../views/collections/CollectionTreeView.tsx | 16 ++++++---- src/client/views/collections/CollectionView.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 12 ++++---- .../collections/collectionFreeForm/MarqueeView.tsx | 3 +- .../CollectionMulticolumnView.tsx | 1 + .../CollectionMultirowView.tsx | 1 + .../views/nodes/CollectionFreeFormDocumentView.tsx | 7 ++--- .../views/nodes/ContentFittingDocumentView.tsx | 5 ++-- src/client/views/nodes/DocumentView.tsx | 34 +++++----------------- src/client/views/nodes/FieldView.tsx | 6 ++-- src/client/views/nodes/FormattedTextBox.tsx | 3 +- 19 files changed, 72 insertions(+), 67 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index adcdf260d..53671707e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -168,7 +168,7 @@ export namespace Docs { const TemplateMap: TemplateMap = new Map([ [DocumentType.TEXT, { layout: { view: FormattedTextBox, dataField: data }, - options: { _height: 150, backgroundColor: "#f1efeb", defaultBackgroundColor: "#f1efeb" } + options: { _height: 150 } }], [DocumentType.HIST, { layout: { view: HistogramBox, dataField: data }, diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index ff0d2718c..2201fe710 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -301,7 +301,7 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | const view0 = this.view0; const templates: Map = new Map(); Array.from(Object.values(Templates.TemplateList)).map(template => - templates.set(template, this.props.views.reduce((checked, doc) => checked || doc?.getLayoutPropStr("_show" + template.Name) ? true : false, false as boolean))); + templates.set(template, this.props.views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean))); return !view0 ? (null) :
v).map(v => v as DocumentView)} templates={templates} />}> diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 192f3b8fb..ba49a2b53 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -13,7 +13,7 @@ import { Doc, DocListCast, Field, FieldResult, Opt } from '../../new_fields/Doc' import { Id } from '../../new_fields/FieldSymbols'; import { List } from '../../new_fields/List'; import { listSpec } from '../../new_fields/Schema'; -import { Cast, FieldValue, StrCast } from '../../new_fields/Types'; +import { Cast, FieldValue, StrCast, BoolCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils, emptyPath } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; @@ -43,6 +43,7 @@ import SettingsManager from '../util/SettingsManager'; import { TraceMobx } from '../../new_fields/util'; import { RadialMenu } from './nodes/RadialMenu'; import RichTextMenu from '../util/RichTextMenu'; +import { DocumentType } from '../documents/DocumentTypes'; @observer export class MainView extends React.Component { @@ -56,8 +57,9 @@ export class MainView extends React.Component { @observable private _panelHeight: number = 0; @observable private _flyoutTranslate: boolean = true; @observable public flyoutWidth: number = 250; + private get darkScheme() { return BoolCast(Cast(this.userDoc.activeWorkspace, Doc, null)?.darkScheme); } - @computed private get userDoc() { return CurrentUserUtils.UserDocument; } + @computed private get userDoc() { return Doc.UserDoc(); } @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; } @computed public get mainFreeform(): Opt { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } @computed public get sidebarButtonsDoc() { return Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc; } @@ -207,7 +209,6 @@ export class MainView extends React.Component { _width: this._panelWidth * .7, _height: this._panelHeight, title: "Collection " + workspaceCount, - backgroundColor: "white" }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); Doc.AddDocToList(Doc.GetProto(CurrentUserUtils.UserDocument.documents as Doc), "data", freeformDoc); @@ -273,6 +274,16 @@ export class MainView extends React.Component { getPHeight = () => this._panelHeight; getContentsHeight = () => this._panelHeight - this._buttonBarHeight; + childBackgroundColor = (doc: Doc) => { + if (this.darkScheme) { + return doc.type === DocumentType.TEXT ? "#112423" : "black"; + } + return doc.type === DocumentType.TEXT ? "#f1efeb" : + doc.type === DocumentType.COL && doc._viewType === CollectionViewType.Tree ? "lightgray" : "white"; + } + sidebarBackgroundColor = (doc: Doc) => { + return this.childBackgroundColor(doc); + } @computed get mainDocView() { return new Transform(0, -this._buttonBarHeight, 1); @computed get flyout() { - const sidebarContent = this.userDoc && this.userDoc.sidebarContainer; + const sidebarContent = this.userDoc?.sidebarContainer; if (!(sidebarContent instanceof Doc)) { return (null); } @@ -388,7 +399,7 @@ export class MainView extends React.Component { PanelHeight={this.getPHeight} renderDepth={0} focus={emptyFunction} - backgroundColor={returnEmptyString} + backgroundColor={this.sidebarBackgroundColor} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -414,7 +425,7 @@ export class MainView extends React.Component { PanelHeight={this.getContentsHeight} renderDepth={0} focus={emptyFunction} - backgroundColor={returnEmptyString} + backgroundColor={this.sidebarBackgroundColor} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} @@ -437,7 +448,7 @@ export class MainView extends React.Component { @computed get mainContent() { const sidebar = this.userDoc && this.userDoc.sidebarContainer; return !this.userDoc || !(sidebar instanceof Doc) ? (null) : ( -
+
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 3c86bd799..226a1c813 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -52,6 +52,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
string| undefined; //collectionDockingView: CollectionDockingView } @observer @@ -756,7 +757,7 @@ export class DockedFrameRenderer extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyFunction} - backgroundColor={returnEmptyString} + backgroundColor={CollectionDockingView.Instance.props.backgroundColor} addDocTab={this.addDocTab} pinToPres={DockedFrameRenderer.PinDoc} ContainingCollectionView={undefined} diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index caffa7eb1..a3b1b5ec0 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -37,7 +37,8 @@ export interface CellProps { renderDepth: number; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; pinToPres: (document: Doc) => void; - moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + moveDocument: (document: Doc, targetCollection: Doc | undefined, + addDocument: (document: Doc) => boolean) => boolean; isFocused: boolean; changeFocusedCellByIndex: (row: number, col: number) => void; setIsEditing: (isEditing: boolean) => void; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 7d1f2c284..055035b3e 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -159,6 +159,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return void; outdentDocument?: () => void; ScreenToLocalTransform: () => Transform; + backgroundColor?: (doc: Doc) => string | undefined; outerXf: () => { translateX: number, translateY: number }; treeViewId: Doc; parentKey: string; @@ -289,7 +290,7 @@ class TreeView extends React.Component { const addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true); contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, - this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, + this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick); } else { @@ -332,7 +333,7 @@ class TreeView extends React.Component { {!docs ? (null) : TreeView.GetChildElements(docs, this.props.treeViewId, Doc.Layout(this.props.document), this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, - this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, + this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick)} ; @@ -348,6 +349,7 @@ class TreeView extends React.Component { DataDocument={this.templateDataDoc} LibraryPath={emptyPath} renderDepth={this.props.renderDepth + 1} + backgroundColor={this.props.backgroundColor} fitToBox={this.boundsOfCollectionDocument !== undefined} PanelWidth={this.docWidth} PanelHeight={this.docHeight} @@ -384,7 +386,7 @@ class TreeView extends React.Component { @computed get renderBullet() { const checked = this.props.document.type === DocumentType.COL ? undefined : this.props.onCheckedClick ? (this.props.document.treeViewChecked ? this.props.document.treeViewChecked : "unchecked") : undefined; - return
+ return
{}
; } @@ -415,7 +417,7 @@ class TreeView extends React.Component { return <>
{ dropAction: dropActionType, addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean, pinToPres: (document: Doc) => void, + backgroundColor: undefined | ((document: Doc) => string | undefined), screenToLocalXf: () => Transform, outerXf: () => { translateX: number, translateY: number }, active: (outsideReaction?: boolean) => boolean, @@ -561,6 +564,7 @@ class TreeView extends React.Component { renderDepth={renderDepth} deleteDoc={remove} addDocument={addDocument} + backgroundColor={backgroundColor} panelWidth={rowWidth} panelHeight={rowHeight} ChromeHeight={ChromeHeight} @@ -714,7 +718,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); return !this.childDocs ? (null) : (
this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} @@ -737,7 +741,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
    { TreeView.GetChildElements(this.childDocs, this.props.Document, this.props.Document, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, - moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, + moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => BoolCast(this.props.Document.treeViewHideHeaderFields), BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, ScriptCast(this.props.Document.onCheckedClick)) } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 39ce4d6e8..be971eda6 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -38,6 +38,7 @@ import { CollectionViewBaseChrome } from './CollectionViewChromes'; import { CollectionTimeView } from './CollectionTimeView'; import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView'; import { List } from '../../../new_fields/List'; +import { SubCollectionViewProps } from './CollectionSubView'; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy); @@ -177,7 +178,7 @@ export class CollectionView extends Touchable { } private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => { - const props = { ...this.props, ...renderProps, ChromeHeight: this.chromeHeight, CollectionView: this, annotationsKey: "" }; + const props: SubCollectionViewProps = { ...this.props, ...renderProps, ChromeHeight: this.chromeHeight, CollectionView: this, annotationsKey: "" }; switch (type) { case CollectionViewType.Schema: return (); case CollectionViewType.Docking: return (); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index e1854fc2d..969d6b3c8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -10,7 +10,7 @@ import { Id } from "../../../../new_fields/FieldSymbols"; import { InkTool } from "../../../../new_fields/InkField"; import { createSchema, listSpec, makeInterface } from "../../../../new_fields/Schema"; import { ScriptField } from "../../../../new_fields/ScriptField"; -import { Cast, NumCast, ScriptCast, StrCast } from "../../../../new_fields/Types"; +import { Cast, NumCast, ScriptCast, BoolCast, StrCast } from "../../../../new_fields/Types"; import { TraceMobx } from "../../../../new_fields/util"; import { GestureUtils } from "../../../../pen-gestures/GestureUtils"; import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils"; @@ -206,6 +206,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } @undoBatch + @action updateClusters(useClusters: boolean) { this.props.Document.useClusters = useClusters; this._clusterSets.length = 0; @@ -243,7 +244,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { docs.map(doc => this._clusterSets[doc.cluster = NumCast(docFirst.cluster)].push(doc)); } childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.cluster === i) && this.updateCluster(child)); - childLayouts.map(child => Doc.GetProto(child).clusterStr = child.cluster?.toString()); } } @@ -279,16 +279,16 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } getClusterColor = (doc: Doc) => { - let clusterColor = ""; + let clusterColor = this.props.backgroundColor?.(doc); const cluster = NumCast(doc.cluster); if (this.Document.useClusters) { if (this._clusterSets.length <= cluster) { setTimeout(() => this.updateCluster(doc), 0); } else { // choose a cluster color from a palette - const colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"]; + const colors = ["#da42429e", "#31ea318c", "rgba(197, 87, 20, 0.55)", "#4a7ae2c4", "rgba(216, 9, 255, 0.5)", "#ff7601", "#1dffff", "yellow", "rgba(27, 130, 49, 0.55)", "rgba(0, 0, 0, 0.268)"]; clusterColor = colors[cluster % colors.length]; - const set = this._clusterSets[cluster] && this._clusterSets[cluster].filter(s => s.backgroundColor && (s.backgroundColor !== s.defaultBackgroundColor)); + const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor); // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document set && set.filter(s => !s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor)); set && set.filter(s => s.isBackground).map(s => clusterColor = StrCast(s.backgroundColor)); @@ -709,6 +709,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed get libraryPath() { return this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : []; } @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } + backgroundHalo = () => BoolCast(this.Document.useClusters); getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps { return { @@ -728,6 +729,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ContainingCollectionDoc: this.props.Document, focus: this.focusDocument, backgroundColor: this.getClusterColor, + backgroundHalo: this.backgroundHalo, parentActive: this.props.active, bringToFront: this.bringToFront, zoomToScale: this.zoomToScale, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 4b0855635..85cda4ecb 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -308,8 +308,7 @@ export class MarqueeView extends React.Component this.nativeWidth > 0 && !this.props.Document.ignoreAspect && !this.props.fitToBox ? this.width / this.nativeWidth : 1; - clusterColorFunc = (doc: Doc) => this.clusterColor; panelWidth = () => (this.dataProvider?.width || this.props.PanelWidth()); panelHeight = () => (this.dataProvider?.height || this.props.PanelHeight()); getTransform = (): Transform => this.props.ScreenToLocalTransform() .translate(-this.X, -this.Y) .scale(1 / this.contentScaling()) - @computed - get clusterColor() { return this.props.backgroundColor(this.props.Document); } focusDoc = (doc: Doc) => this.props.focus(doc, false); render() { TraceMobx(); @@ -78,7 +75,7 @@ export class CollectionFreeFormDocumentView extends DocComponent : string | undefined; getTransform: () => Transform; addDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean; @@ -86,6 +87,7 @@ export class ContentFittingDocumentView extends React.Component boolean; pinToPres: (document: Doc) => void; zoomToScale: (scale: number) => void; - backgroundColor: (doc: Doc) => string | undefined; + backgroundHalo?: () => boolean; + backgroundColor?: (doc: Doc) => string | undefined; getScale: () => number; animateBetweenIcon?: (maximize: boolean, target: number[]) => void; ChromeHeight?: () => number; @@ -295,12 +296,6 @@ export class DocumentView extends DocComponent(Docu this._downX = touch.clientX; this._downY = touch.clientY; if (!e.nativeEvent.cancelBubble) { - this._hitTemplateDrag = false; - for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) { - if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") { - this._hitTemplateDrag = true; - } - } if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); this.removeMoveListeners(); this.addMoveListeners(); @@ -778,14 +773,6 @@ export class DocumentView extends DocComponent(Docu }); } - // does Document set a layout prop - setsLayoutProp = (prop: string) => this.props.Document[prop] !== this.props.Document["default" + prop[0].toUpperCase() + prop.slice(1)] && this.props.Document["default" + prop[0].toUpperCase() + prop.slice(1)]; - // get the a layout prop by first choosing the prop from Document, then falling back to the layout doc otherwise. - getLayoutPropStr = (prop: string) => { - return StrCast(this.setsLayoutProp(prop) ? this.props.Document[prop] : Cast(this.layoutDoc?.expandedTemplate, Doc, null)?.[prop] || this.layoutDoc[prop]); - } - getLayoutPropNum = (prop: string) => NumCast(this.setsLayoutProp(prop) ? this.props.Document[prop] : this.layoutDoc[prop]); - isSelected = (outsideReaction?: boolean) => SelectionManager.IsSelected(this, outsideReaction); select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; @@ -848,9 +835,9 @@ export class DocumentView extends DocComponent(Docu @computed get innards() { TraceMobx(); - const showTitle = StrCast(this.getLayoutPropStr("_showTitle")); - const showTitleHover = StrCast(this.getLayoutPropStr("_showTitleHover")); - const showCaption = this.getLayoutPropStr("_showCaption"); + const showTitle = StrCast(this.layoutDoc._showTitle); + const showTitleHover = StrCast(this.layoutDoc._showTitleHover); + const showCaption = StrCast(this.layoutDoc._showCaption); const showTextTitle = showTitle && (StrCast(this.layoutDoc.layout).indexOf("PresBox") !== -1 || StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1) ? showTitle : undefined; const searchHighlight = (!this.Document.searchFields ? (null) :
    @@ -921,14 +908,9 @@ export class DocumentView extends DocComponent(Docu render() { if (!(this.props.Document instanceof Doc)) return (null); - const colorSet = this.setsLayoutProp("backgroundColor"); - const clusterCol = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.clusterOverridesDefaultBackground; - const backgroundColor = (clusterCol && !colorSet) ? - this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) : - StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document); - + const backgroundColor = StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor?.(this.Document); const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document); - const borderRounding = this.getLayoutPropStr("borderRounding"); + const borderRounding = this.layoutDoc.borderRounding; const localScale = fullDegree; const highlightColors = ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; @@ -943,7 +925,7 @@ export class DocumentView extends DocComponent(Docu transform: this._animate ? `scale(${this._animate})` : undefined, transition: !this._animate ? StrCast(this.Document.transition) : this._animate < 1 ? "transform 0.5s ease-in" : "transform 0.5s ease-out", pointerEvents: this.ignorePointerEvents ? "none" : "all", - color: StrCast(this.Document.color), + color: StrCast(this.Document.color, "inherit"), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, boxShadow: this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 8250f41f3..00f00dd52 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -3,14 +3,13 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; import { DateField } from "../../../new_fields/DateField"; import { Doc, FieldResult, Opt } from "../../../new_fields/Doc"; -import { IconField } from "../../../new_fields/IconField"; import { List } from "../../../new_fields/List"; -import { AudioField, ImageField, VideoField } from "../../../new_fields/URLField"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { AudioField, VideoField } from "../../../new_fields/URLField"; import { Transform } from "../../util/Transform"; import { CollectionView } from "../collections/CollectionView"; import { AudioBox } from "./AudioBox"; import { VideoBox } from "./VideoBox"; -import { ScriptField } from "../../../new_fields/ScriptField"; // // these properties get assigned through the render() method of the DocumentView when it creates this node. @@ -34,6 +33,7 @@ export interface FieldViewProps { pinToPres: (document: Doc) => void; removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; + backgroundColor?: (document: Doc) => string | undefined; ScreenToLocalTransform: () => Transform; active: (outsideReaction?: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 2fb61f9db..3c64b3974 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -186,7 +186,6 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & tsel.marks().filter(m => m.type === this._editorView!.state.schema.marks.user_mark).map(m => AudioBox.SetScrubTime(Math.max(0, m.attrs.modified * 5000 - 1000))); this._applyingChange = true; if (!this.props.Document._textTemplate || Doc.GetProto(this.props.Document) === this.dataDoc) { - this.dataDoc[this.props.fieldKey + "-lastModified"] && (this.dataDoc[this.props.fieldKey + "-backgroundColor"] = "lightGray"); this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()), state.doc.textBetween(0, state.doc.content.size, "\n\n")); } @@ -1075,7 +1074,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
    Date: Fri, 14 Feb 2020 15:47:48 -0500 Subject: small tweaks --- src/client/documents/Documents.ts | 13 ++++++------- src/scraping/buxton/final/BuxtonImporter.ts | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 53671707e..072e8c612 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -357,6 +357,8 @@ export namespace Docs { }); const parentProto = Doc.GetProto(parent); const { _socket } = DocServer; + _socket.off(MessageStore.BuxtonDocumentResult.Message); + _socket.off(MessageStore.BuxtonImportComplete.Message); Utils.AddServerHandler(_socket, MessageStore.BuxtonDocumentResult, ({ device, errors }) => { if (!responded) { responded = true; @@ -688,15 +690,12 @@ export namespace Docs { if (input === undefined || input === null || ![...primitives, "object"].includes(typeof input)) { return undefined; } - let parsed = input; - if (typeof input === "string") { - parsed = JSONUtils.tryParse(input); - } + input = JSON.parse(typeof input === "string" ? input : JSON.stringify(input)); let converted: Doc; - if (typeof parsed === "object" && !(parsed instanceof Array)) { - converted = convertObject(parsed, title, appendToTarget); + if (typeof input === "object" && !(input instanceof Array)) { + converted = convertObject(input, title, appendToTarget); } else { - (converted = new Doc).json = toField(parsed); + (converted = new Doc).json = toField(input); } title && (converted.title = title); return converted; diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts index 098671942..47d6bbe83 100644 --- a/src/scraping/buxton/final/BuxtonImporter.ts +++ b/src/scraping/buxton/final/BuxtonImporter.ts @@ -43,8 +43,8 @@ export interface AnalysisResult { type Transformer = (raw: string) => { transformed?: T, error?: string }; export interface ImportResults { - deviceCount: number, - errorCount: number + deviceCount: number; + errorCount: number; } type ResultCallback = (result: AnalysisResult) => void; @@ -300,7 +300,7 @@ async function writeImages(zip: any): Promise { const { width, height, type } = await new Promise(async resolve => { const sizeStream = createImageSizeStream().on('size', (dimensions: Dimensions) => { readStream.destroy(); - resolve(dimensions) + resolve(dimensions); }); const readStream = await streamImage(); readStream.pipe(sizeStream); -- cgit v1.2.3-70-g09d2 From a71f1cbfe47bbe5bcefa7deb63fa812683a37178 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 15 Feb 2020 22:44:33 -0500 Subject: more color scheme fixes. --- src/client/documents/DocumentTypes.ts | 1 - src/client/views/DocumentDecorations.tsx | 24 +++++++------- src/client/views/MainView.scss | 16 ++++++++++ src/client/views/MainView.tsx | 37 ++++++++++++++-------- src/client/views/nodes/DocumentView.tsx | 4 ++- src/client/views/search/FilterBox.tsx | 2 +- src/client/views/search/SearchBox.tsx | 2 +- .../authentication/models/current_user_utils.ts | 3 +- 8 files changed, 57 insertions(+), 32 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 1220e9923..0e6b59b33 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -14,7 +14,6 @@ export enum DocumentType { LINKDOC = "linkdoc", BUTTON = "button", SLIDER = "slider", - TEMPLATE = "template", EXTENSION = "extension", YOUTUBE = "youtube", WEBCAM = "webcam", diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 12427cdac..3388ea46c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -491,16 +491,16 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
    ); - const titleArea = this._edtingTitle ? - <> - this.titleBlur(true)} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> -
    DocUtils.Publish(seldoc.props.Document, this._accumulatedTitle, seldoc.props.addDocument, seldoc.props.removeDocument)}> - -
    - : -
    {`${this.selectionTitle}`}
    ; + const titleArea = this._edtingTitle ? + <> + this.titleBlur(true)} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> +
    DocUtils.Publish(seldoc.props.Document, this._accumulatedTitle, seldoc.props.addDocument, seldoc.props.removeDocument)}> + +
    + : +
    {`${this.selectionTitle}`}
    ; bounds.x = Math.max(0, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2; bounds.y = Math.max(0, bounds.y - this._resizeBorderWidth / 2 - this._titleHeight) + this._resizeBorderWidth / 2 + this._titleHeight; @@ -539,7 +539,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
    e.preventDefault()}>
    e.preventDefault()}>
    + style={{ background: darkScheme }} onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}>
    e.preventDefault()}>
    e.preventDefault()}>
    e.preventDefault()}>
    + style={{ background: darkScheme }} onPointerDown={this.onRadiusDown} onContextMenu={(e) => e.preventDefault()}>
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index df594be4d..e91f7e94c 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -29,6 +29,9 @@ left: 0; z-index: 1; touch-action: none; + .searchBox-container { + background: lightgray; + } } .mainView-container-dark { @@ -38,6 +41,19 @@ .marquee { border-color: white; } + #search-input { + background: lightgray; + } + .searchBox-container { + background: rgb(45,45,45); + } + .contextMenu-cont, .contextMenu-item { + background: dimGray; + color: lightgray; + } + .contextMenu-item:hover { + background: gray; + } } .mainView-mainContent { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index de76106d1..7948da3c5 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -274,16 +274,25 @@ export class MainView extends React.Component { getPHeight = () => this._panelHeight; getContentsHeight = () => this._panelHeight - this._buttonBarHeight; - childBackgroundColor = (doc: Doc) => { + defaultBackgroundColors = (doc: Doc) => { if (this.darkScheme) { - return doc.type === DocumentType.TEXT || doc.type === DocumentType.BUTTON ? "#2d2d2d" : - (doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) || doc.type === DocumentType.BUTTON ? "#2d2d2d" : "black"; + switch (doc.type) { + case DocumentType.TEXT || DocumentType.BUTTON: return "#2d2d2d"; + case DocumentType.COL: { + if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; + } + default: return "black"; + } + } else { + switch (doc.type) { + case DocumentType.TEXT: return "#f1efeb"; + case DocumentType.BUTTON: return "lightgray"; + case DocumentType.COL: { + if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "lightgray"; + } + default: return "white"; + } } - return doc.type === DocumentType.TEXT ? "#f1efeb" : - (doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) || doc.type === DocumentType.BUTTON ? "lightgray" : "white"; - } - sidebarBackgroundColor = (doc: Doc) => { - return this.childBackgroundColor(doc); } @computed get mainDocView() { return -
+
; } - + //`${StrCast(sidebar.backgroundColor, this.darkScheme ? "dimGray" : "black")}` }} > @computed get mainContent() { const sidebar = this.userDoc && this.userDoc.sidebarContainer; return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
+ style={{ backgroundColor: this.defaultBackgroundColors(sidebar) }}> (Docu const borderRounding = this.layoutDoc.borderRounding; const localScale = fullDegree; - const highlightColors = ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; + const highlightColors = Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? + ["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] : + ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"]; let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc._viewType !== CollectionViewType.Linear; highlighting = highlighting && this.props.focus !== emptyFunction; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 684f50766..d4c9e67fb 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -33,7 +33,7 @@ export enum Keys { export class FilterBox extends React.Component { static Instance: FilterBox; - public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB, DocumentType.TEMPLATE]; + public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB]; //if true, any keywords can be used. if false, all keywords are required. //this also serves as an indicator if the word status filter is applied diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index be13dae03..9bd42b516 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -234,7 +234,7 @@ export class SearchBox extends React.Component { y += 300; } } - return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); + return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, title: `Search Docs: "${this._searchString}"` }); } @action.bound diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 888e27f28..930b021a4 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -227,8 +227,7 @@ export class CurrentUserUtils { // Finally, setup the list of buttons to display in the sidebar doc.sidebarButtons = Docs.Create.StackingDocument([doc.SearchBtn as Doc, doc.LibraryBtn as Doc, doc.ToolsBtn as Doc], { _width: 500, _height: 80, boxShadow: "0 0", sectionFilter: "title", hideHeadings: true, ignoreClick: true, - _chromeStatus: "disabled", title: "library stack", - _yMargin: 10, + _chromeStatus: "disabled", title: "library stack", backgroundColor: "dimGray", }); } -- cgit v1.2.3-70-g09d2 From 0f2872775a9a3bab73c92afc329e1279645f3a71 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 17 Feb 2020 22:50:10 -0500 Subject: made creation of template docs from context menu simpler --- src/client/documents/Documents.ts | 31 +++++++++++++++- .../CollectionStackingViewFieldColumn.tsx | 8 +++-- .../collections/collectionFreeForm/MarqueeView.tsx | 42 ++++------------------ src/client/views/nodes/DocumentView.tsx | 9 +++-- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/new_fields/Doc.ts | 16 ++++----- .../authentication/models/current_user_utils.ts | 11 ++---- 7 files changed, 61 insertions(+), 58 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 072e8c612..669aa97b5 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -21,7 +21,7 @@ import { Field, Doc, Opt, DocListCastAsync, FieldResult, DocListCast } from "../ import { ImageField, VideoField, AudioField, PdfField, WebField, YoutubeField } from "../../new_fields/URLField"; import { HtmlField } from "../../new_fields/HtmlField"; import { List } from "../../new_fields/List"; -import { Cast, NumCast } from "../../new_fields/Types"; +import { Cast, NumCast, StrCast } from "../../new_fields/Types"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; import { dropActionType } from "../util/DragManager"; @@ -54,6 +54,8 @@ import { InkingControl } from "../views/InkingControl"; import { RichTextField } from "../../new_fields/RichTextField"; import { extname } from "path"; import { MessageStore } from "../../server/Message"; +import { ContextMenuProps } from "../views/ContextMenuItem"; +import { ContextMenu } from "../views/ContextMenu"; const requestImageSize = require('../util/request-image-size'); const path = require('path'); @@ -898,6 +900,33 @@ export namespace DocUtils { return linkDocProto; } + export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number): void { + ContextMenu.Instance.addItem({ + description: "Add Note ...", + subitems: DocListCast((Doc.UserDoc().noteTypes as Doc).data).map((note, i) => ({ + description: ":" + StrCast(note.title), + event: (args: { x: number, y: number }) => docTextAdder(Docs.Create.TextDocument("", { _width: 200, x, y, _autoHeight: true, layout: note, title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1) })), + icon: "eye" + })) as ContextMenuProps[], + icon: "eye" + }); + ContextMenu.Instance.addItem({ + description: "Add Template Doc ...", + subitems: DocListCast(Cast(Doc.UserDoc().expandingButtons, Doc, null)?.data).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc).map((dragDoc, i) => ({ + description: ":" + StrCast(dragDoc.title), + event: (args: { x: number, y: number }) => { + const newDoc = Doc.ApplyTemplate(dragDoc); + if (newDoc) { + newDoc.x = x; + newDoc.y = y; + docAdder(newDoc); + } + }, + icon: "eye" + })) as ContextMenuProps[], + icon: "eye" + }); + } } Scripting.addGlobal("Docs", Docs); diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 2e3467d90..8c23ecd49 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -8,10 +8,10 @@ import { Doc, DocListCast } from "../../../new_fields/Doc"; import { RichTextField } from "../../../new_fields/RichTextField"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { ScriptField } from "../../../new_fields/ScriptField"; -import { NumCast, StrCast } from "../../../new_fields/Types"; +import { NumCast, StrCast, Cast } from "../../../new_fields/Types"; import { ImageField } from "../../../new_fields/URLField"; import { TraceMobx } from "../../../new_fields/util"; -import { Docs } from "../../documents/Documents"; +import { Docs, DocUtils } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; @@ -268,8 +268,10 @@ export class CollectionStackingViewFieldColumn extends React.Component dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof (dataDoc[fieldKey]) === "string").map(fieldKey => docItems.push({ description: ":" + fieldKey, event: () => { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 44109edc5..1db963fa4 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -3,24 +3,20 @@ import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../../new_fields/Doc"; import { InkField } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; -import { listSpec } from "../../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../../new_fields/SchemaHeaderField"; -import { ComputedField } from "../../../../new_fields/ScriptField"; -import { Cast, NumCast, StrCast } from "../../../../new_fields/Types"; +import { Cast, NumCast } from "../../../../new_fields/Types"; import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils"; import { Utils } from "../../../../Utils"; -import { Docs } from "../../../documents/Documents"; +import { Docs, DocUtils } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; +import { ContextMenu } from "../../ContextMenu"; import { PreviewCursor } from "../../PreviewCursor"; -import { CollectionViewType } from "../CollectionView"; +import { SubCollectionViewProps } from "../CollectionSubView"; +import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); -import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; -import { SubCollectionViewProps } from "../CollectionSubView"; -import { ContextMenu } from "../../ContextMenu"; -import { ContextMenuProps } from "../../ContextMenuItem"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -69,32 +65,8 @@ export class MarqueeView extends React.Component ({ - description: ":" + StrCast(note.title), - event: (args: { x: number, y: number }) => this.props.addLiveTextDocument(Docs.Create.TextDocument("", { _width: 200, x, y, _autoHeight: true, layout: note, title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1) })), - icon: "eye" - })) as ContextMenuProps[], - icon: "eye" - }); - ContextMenu.Instance.addItem({ - description: "Add Template Doc ...", - subitems: DocListCast(Cast(CurrentUserUtils.UserDocument.expandingButtons, Doc, null)?.data).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc).map((dragDoc, i) => ({ - description: ":" + StrCast(dragDoc.title), - event: (args: { x: number, y: number }) => { - const newDoc = Doc.ApplyTemplate(dragDoc); - if (newDoc) { - newDoc.x = x; - newDoc.y = y; - this.props.addDocument(newDoc); - } - }, - icon: "eye" - })) as ContextMenuProps[], - icon: "eye" - }); + DocUtils.addDocumentCreatorMenuItems(this.props.addLiveTextDocument, this.props.addDocument, x, y); + ContextMenu.Instance.displayMenu(this._downX, this._downY); } else if (e.key === "q" && e.ctrlKey) { e.preventDefault(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 704da3c74..e1d5fcc8a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -628,6 +628,8 @@ export class DocumentView extends DocComponent(Docu } e.preventDefault(); + const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); + const cm = ContextMenu.Instance; const subitems: ContextMenuProps[] = []; subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this, this.props.LibraryPath), icon: "desktop" }); @@ -636,6 +638,7 @@ export class DocumentView extends DocComponent(Docu subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" }); subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" }); subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), undefined, "onRight"), icon: "layer-group" }); + templateDoc && subitems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, undefined, "onRight"), icon: "eye" }); subitems.push({ description: "Open Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); @@ -756,7 +759,9 @@ export class DocumentView extends DocComponent(Docu select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; chromeHeight = () => { - return 1; + const showTitle = StrCast(this.layoutDoc._showTitle); + const showTextTitle = showTitle && (StrCast(this.layoutDoc.layout).indexOf("PresBox") !== -1 || StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1) ? showTitle : undefined; + return showTextTitle ? 25 : 1; } @computed get finalLayoutKey() { @@ -857,7 +862,7 @@ export class DocumentView extends DocComponent(Docu this.contents :
-
+
{this.contents}
{titleView} diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 317f95f81..c1e630e67 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -369,7 +369,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Make Template", event: () => { this.props.Document.isTemplateDoc = true; Doc.AddDocToList(Cast(Doc.UserDoc().noteTypes, Doc, null), "data", this.props.Document); }, icon: "eye" }); + !this.props.Document.expandedTemplate && funcs.push({ description: "Make Template", event: () => { this.props.Document.isTemplateDoc = true; Doc.AddDocToList(Cast(Doc.UserDoc().noteTypes, Doc, null), "data", this.props.Document); }, icon: "eye" }); funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.props.Document._showSidebar = !this.props.Document._showSidebar; }, icon: "expand-arrows-alt" }); funcs.push({ description: "Record Bullet", event: () => { e.stopPropagation(); this.recordBullet(); }, icon: "expand-arrows-alt" }); ["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option => diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 48890ac8d..43bbea623 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -1,22 +1,22 @@ -import { observable, ObservableMap, runInAction, action, computed } from "mobx"; +import { action, computed, observable, ObservableMap, runInAction } from "mobx"; +import { computedFn } from "mobx-utils"; import { alias, map, serializable } from "serializr"; import { DocServer } from "../client/DocServer"; import { DocumentType } from "../client/documents/DocumentTypes"; import { Scripting, scriptingGlobal } from "../client/util/Scripting"; import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from "../client/util/SerializationHelper"; -import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols"; +import { UndoManager } from "../client/util/UndoManager"; +import { intersectRect } from "../Utils"; +import { HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols"; import { List } from "./List"; import { ObjectField } from "./ObjectField"; import { PrefetchProxy, ProxyField } from "./Proxy"; import { FieldId, RefField } from "./RefField"; +import { RichTextField } from "./RichTextField"; import { listSpec } from "./Schema"; -import { ComputedField, ScriptField } from "./ScriptField"; -import { BoolCast, Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; +import { ComputedField } from "./ScriptField"; +import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; -import { intersectRect } from "../Utils"; -import { UndoManager, undoBatch } from "../client/util/UndoManager"; -import { computedFn } from "mobx-utils"; -import { RichTextField } from "./RichTextField"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 66d1129f2..e9c12b70c 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -34,30 +34,25 @@ export class CurrentUserUtils { @observable public static GuestWorkspace: Doc | undefined; @observable public static GuestMobile: Doc | undefined; - // a default set of note types .. not being used yet... - static setupNoteTypes(doc: Doc) { - return [ + static setupDefaultDocTemplates(doc: Doc, buttons?: string[]) { + const noteTemplates = [ Docs.Create.TextDocument("", { title: "Note", backgroundColor: "yellow", isTemplateDoc: true }), Docs.Create.TextDocument("", { title: "Idea", backgroundColor: "pink", isTemplateDoc: true }), Docs.Create.TextDocument("", { title: "Topic", backgroundColor: "lightBlue", isTemplateDoc: true }), Docs.Create.TextDocument("", { title: "Person", backgroundColor: "lightGreen", isTemplateDoc: true }), Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange", isTemplateDoc: true }) ]; - } - static setupDefaultDocTemplates(doc: Doc, buttons?: string[]) { - doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(CurrentUserUtils.setupNoteTypes(doc), { title: "Note Types", _height: 75 })); + doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates, { title: "Note Types", _height: 75 })); } // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc, buttons?: string[]) { - const notes = DocListCast(Cast(doc.noteTypes, Doc, null)?.data); const emptyPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" }); const emptyCollection = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, _LODdisable: true, _width: 150, _height: 100, title: "freeform" }); doc.activePen = doc; const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ { title: "collection", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: emptyCollection }, { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,true,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' }, - { title: "todo item", icon: "check", ignoreClick: true, drag: 'getCopy(this.dragFactory, true)', dragFactory: notes[notes.length - 1] }, { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", {_width: 300, _height: 300, title: "New Webpage" })' }, { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' }, { title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" }, -- cgit v1.2.3-70-g09d2 From d53ae2d90e7d7de8135ff19e18535cccd7a90ed0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 19 Feb 2020 00:45:23 -0500 Subject: getting rid of data docs from many places --- src/client/documents/Documents.ts | 2 +- src/client/util/DictationManager.ts | 4 +- src/client/util/DocumentManager.ts | 6 +-- src/client/util/RichTextSchema.tsx | 2 +- src/client/views/DocComponent.tsx | 4 +- src/client/views/DocumentButtonBar.tsx | 8 +-- src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/MainView.tsx | 6 +-- src/client/views/MainViewNotifs.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 60 +++++++++------------- .../views/collections/CollectionSchemaCells.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 6 +-- .../views/collections/CollectionTreeView.tsx | 12 ++--- src/client/views/collections/CollectionView.tsx | 4 +- .../views/collections/ParentDocumentSelector.tsx | 4 +- src/client/views/linking/LinkFollowBox.tsx | 16 +++--- src/client/views/linking/LinkMenu.tsx | 2 +- src/client/views/linking/LinkMenuGroup.tsx | 2 +- src/client/views/linking/LinkMenuItem.tsx | 2 +- .../views/nodes/ContentFittingDocumentView.tsx | 2 +- src/client/views/nodes/DocuLinkBox.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 22 ++++---- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/FontIconBox.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/FormattedTextBoxComment.tsx | 4 +- src/client/views/nodes/KeyValuePair.tsx | 4 +- src/client/views/nodes/PresBox.tsx | 4 +- src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/pdf/Annotation.tsx | 6 +-- src/client/views/pdf/PDFViewer.tsx | 2 +- .../views/presentationview/PresElementBox.tsx | 3 +- src/client/views/search/SearchItem.tsx | 6 +-- src/new_fields/Doc.ts | 4 +- 36 files changed, 105 insertions(+), 112 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 669aa97b5..650538e93 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -654,7 +654,7 @@ export namespace Docs { { type: type, content: [ - ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth, config.path)) + ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, config.initialWidth, config.path)) ] } ] diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 3394cb93d..569c1ef6d 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -326,7 +326,7 @@ export namespace DictationManager { ["open fields", { action: (target: DocumentView) => { const kvp = Docs.Create.KVPDocument(target.props.Document, { _width: 300, _height: 300 }); - target.props.addDocTab(kvp, target.props.DataDoc, "onRight"); + target.props.addDocTab(kvp, "onRight"); } }], @@ -340,7 +340,7 @@ export namespace DictationManager { const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`; proto.data = new RichTextField(proseMirrorState); proto.backgroundColor = "#eeffff"; - target.props.addDocTab(newBox, proto, "onRight"); + target.props.addDocTab(newBox, "onRight"); } }] diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index bfda8e75b..c639f07f5 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -148,7 +148,7 @@ export class DocumentManager { const targetDocContext = (annotatedDoc ? annotatedDoc : contextDoc); if (!targetDocContext) { // we don't have a view and there's no context specified ... create a new view of the target using the dockFunc or default - (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc)), undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc))); highlight(); } else { const targetDocContextView = DocumentManager.Instance.getFirstDocumentView(targetDocContext); @@ -164,12 +164,12 @@ export class DocumentManager { retryDocView.props.focus(targetDoc, willZoom); // focus on the target if it now exists in the context } else { if (closeContextIfNotFound && targetDocContextView.props.removeDocument) targetDocContextView.props.removeDocument(targetDocContextView.props.Document); - targetDoc.layout && (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc)), undefined); // otherwise create a new view of the target + targetDoc.layout && (dockFunc || CollectionDockingView.AddRightSplit)(Doc.BrushDoc(Doc.MakeAlias(targetDoc))); // otherwise create a new view of the target } highlight(); }, 0); } else { // there's no context view so we need to create one first and try again - (dockFunc || CollectionDockingView.AddRightSplit)(targetDocContext, undefined); + (dockFunc || CollectionDockingView.AddRightSplit)(targetDocContext); setTimeout(() => { const finalDocView = DocumentManager.Instance.getFirstDocumentView(targetDoc); const finalDocContextView = DocumentManager.Instance.getFirstDocumentView(targetDocContext); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 23b0a56a8..cfbae5dca 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -613,7 +613,7 @@ export class ImageResizeView { DocServer.GetRefField(node.attrs.docid).then(async linkDoc => (linkDoc instanceof Doc) && DocumentManager.Instance.FollowLink(linkDoc, view.state.schema.Document, - document => addDocTab(document, undefined, node.attrs.location ? node.attrs.location : "inTab"), false)); + document => addDocTab(document, node.attrs.location ? node.attrs.location : "inTab"), false)); } }; this._handle.onpointerdown = function (e: any) { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 0bf944f22..61b1f9e0f 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc, Opt } from '../../new_fields/Doc'; +import { Doc, Opt, DataSym } from '../../new_fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast } from '../../new_fields/Types'; @@ -58,7 +58,7 @@ export function DocAnnotatableComponent

(schema //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } - @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Cast(this.props.Document.resolvedDataDoc, Doc, null) || Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return this.props.Document[DataSym]; } _annotationKey: string = "annotations"; public set annotationKey(val: string) { this._annotationKey = val; } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index b530d8a42..c8ad78f47 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -251,10 +251,10 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | @computed get contextButton() { - return !this.view0 ? (null) : v).map(v => v as DocumentView)} Document={this.view0.props.Document} addDocTab={(doc, data, where) => { - where === "onRight" ? CollectionDockingView.AddRightSplit(doc, data) : - this.props.stack ? CollectionDockingView.Instance.AddTab(this.props.stack, doc, data) : - this.view0?.props.addDocTab(doc, data, "onRight"); + return !this.view0 ? (null) : v).map(v => v as DocumentView)} Document={this.view0.props.Document} addDocTab={(doc, where) => { + where === "onRight" ? CollectionDockingView.AddRightSplit(doc) : + this.props.stack ? CollectionDockingView.Instance.AddTab(this.props.stack, doc) : + this.view0?.props.addDocTab(doc, "onRight"); return true; }} />; } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 979687ffb..d0900251d 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -156,7 +156,7 @@ export default class KeyManager { return { stopPropagation: false, preventDefault: false }; } } - MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform, undefined); + MainView.Instance.mainFreeform && CollectionDockingView.AddRightSplit(MainView.Instance.mainFreeform); break; case "arrowleft": if (document.activeElement) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7948da3c5..1849ec250 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -185,7 +185,7 @@ export class MainView extends React.Component { reaction(() => CollectionDockingView.Instance && CollectionDockingView.Instance.initialized, initialized => initialized && received && DocServer.GetRefField(received).then(docField => { if (docField instanceof Doc && docField._viewType !== CollectionViewType.Docking) { - CollectionDockingView.AddRightSplit(docField, undefined); + CollectionDockingView.AddRightSplit(docField); } }), ); @@ -379,10 +379,10 @@ export class MainView extends React.Component { document.removeEventListener("pointerup", this.onPointerUp); } flyoutWidthFunc = () => this.flyoutWidth; - addDocTabFunc = (doc: Doc, data: Opt, where: string, libraryPath?: Doc[]): boolean => { + addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => { return where === "close" ? CollectionDockingView.CloseRightSplit(doc) : doc.dockingConfig ? this.openWorkspace(doc) : - CollectionDockingView.AddRightSplit(doc, undefined, libraryPath); + CollectionDockingView.AddRightSplit(doc, libraryPath); } mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); diff --git a/src/client/views/MainViewNotifs.tsx b/src/client/views/MainViewNotifs.tsx index 09fa1cb0c..82e07c449 100644 --- a/src/client/views/MainViewNotifs.tsx +++ b/src/client/views/MainViewNotifs.tsx @@ -15,7 +15,7 @@ export class MainViewNotifs extends React.Component { @observable static NotifsCol: Opt; openNotifsCol = () => { if (MainViewNotifs.NotifsCol) { - CollectionDockingView.AddRightSplit(MainViewNotifs.NotifsCol, undefined); + CollectionDockingView.AddRightSplit(MainViewNotifs.NotifsCol); } } render() { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 26b65c898..6e1d522fc 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -8,7 +8,7 @@ import * as ReactDOM from 'react-dom'; import Measure from "react-measure"; import * as GoldenLayout from "../../../client/goldenLayout"; import { DateField } from '../../../new_fields/DateField'; -import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc"; +import { Doc, DocListCast, Field, Opt, DataSym } from "../../../new_fields/Doc"; import { Id } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; import { FieldId } from "../../../new_fields/RefField"; @@ -38,7 +38,7 @@ const _global = (window /* browser */ || global /* node */) as any; export class CollectionDockingView extends React.Component { @observable public static Instances: CollectionDockingView[] = []; @computed public static get Instance() { return CollectionDockingView.Instances[0]; } - public static makeDocumentConfig(document: Doc, dataDoc: Doc | undefined, width?: number, libraryPath?: Doc[]) { + public static makeDocumentConfig(document: Doc, width?: number, libraryPath?: Doc[]) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -46,8 +46,7 @@ export class CollectionDockingView extends React.Component d[Id]) : [] + libraryPath: libraryPath?.map(d => d[Id]) //collectionDockingView: CollectionDockingView.Instance } }; @@ -76,12 +75,12 @@ export class CollectionDockingView extends React.Component { - CollectionDockingView.makeDocumentConfig(doc, undefined); + CollectionDockingView.makeDocumentConfig(doc); }) }; } @@ -97,10 +96,9 @@ export class CollectionDockingView extends React.Component { if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" && DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)?.Document.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, dataDoc, undefined, libraryPath); + const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[0].remove(); instance.layoutChanged(document); @@ -188,7 +186,7 @@ export class CollectionDockingView extends React.Component tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)?.Document.isDisplayPanel) { - const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, dataDoc, undefined, libraryPath); + const newItemStackConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); child.addChild(newItemStackConfig, undefined); !addToSplit && child.contentItems[j].remove(); instance.layoutChanged(document); @@ -210,12 +208,12 @@ export class CollectionDockingView extends React.Component { + public AddTab = (stack: any, document: Doc, libraryPath?: Doc[]) => { Doc.GetProto(document).lastOpened = new DateField; - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument, undefined, libraryPath); + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, undefined, libraryPath); if (stack === undefined) { let stack: any = this._goldenLayout.root; while (!stack.isStack) { @@ -427,7 +425,6 @@ export class CollectionDockingView extends React.Component`; tab.titleElement[0].onclick = (e: any) => tab.titleElement[0].focus(); @@ -507,7 +504,7 @@ export class CollectionDockingView extends React.Component { if (e.target === stack.header.element[0] && e.button === 1) { - this.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: "Untitled Collection" }), undefined); + this.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: "Untitled Collection" })); } }); @@ -580,7 +577,6 @@ export class CollectionDockingView extends React.Component string | undefined; @@ -593,7 +589,6 @@ export class DockedFrameRenderer extends React.Component { @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; - @observable private _dataDoc: Opt; @observable private _isActive: boolean = false; get _stack(): any { @@ -601,12 +596,7 @@ export class DockedFrameRenderer extends React.Component { } constructor(props: any) { super(props); - DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => { - this._document = f as Doc; - if (this.props.dataDocumentId && this.props.documentId !== this.props.dataDocumentId) { - DocServer.GetRefField(this.props.dataDocumentId).then(action((f: Opt) => this._dataDoc = f as Doc)); - } - })); + DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => this._document = f as Doc)); this.props.libraryPath && this.setupLibraryPath(); } @@ -630,7 +620,7 @@ export class DockedFrameRenderer extends React.Component { pinDoc.presentationTargetDoc = doc; Doc.AddDocToList(curPres, "data", pinDoc); if (!DocumentManager.Instance.getDocumentView(curPres)) { - CollectionDockingView.AddRightSplit(curPres, undefined); + CollectionDockingView.AddRightSplit(curPres); } } } @@ -708,16 +698,16 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return this.nativeWidth() ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } get widthpercent() { return this.nativeWidth() ? `${(this.nativeWidth() * this.contentScaling()) / this.panelWidth() * 100}%` : undefined; } - addDocTab = (doc: Doc, dataDoc: Opt, location: string, libraryPath?: Doc[]) => { + addDocTab = (doc: Doc, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); if (doc.dockingConfig) { return MainView.Instance.openWorkspace(doc); } else if (location === "onRight") { - return CollectionDockingView.AddRightSplit(doc, dataDoc, libraryPath); + return CollectionDockingView.AddRightSplit(doc, libraryPath); } else if (location === "close") { return CollectionDockingView.CloseRightSplit(doc); } else { - return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc, libraryPath); + return CollectionDockingView.Instance.AddTab(this._stack, doc, libraryPath); } } @@ -725,7 +715,7 @@ export class DockedFrameRenderer extends React.Component { TraceMobx(); if (!this._document) return (null); const document = this._document; - const resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc; + const resolvedDataDoc = this._document[DataSym] !== this._document && this._document[DataSym];// document.layout instanceof Doc ? document : this._dataDoc; return {

); } } -Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddRightSplit(doc, undefined); }); -Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.UseRightSplit(doc, undefined, undefined, shiftKey); }); +Scripting.addGlobal(function openOnRight(doc: any) { CollectionDockingView.AddRightSplit(doc); }); +Scripting.addGlobal(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.UseRightSplit(doc, undefined, shiftKey); }); diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index a3b1b5ec0..851fded71 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -35,7 +35,7 @@ export interface CellProps { Document: Doc; fieldKey: string; renderDepth: number; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; moveDocument: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index c422c38f1..7dee7f18f 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -224,7 +224,7 @@ export interface SchemaTableProps { ScreenToLocalTransform: () => Transform; active: (outsideReaction: boolean) => boolean; onDrop: (e: React.DragEvent, options: DocumentOptions, completed?: (() => void) | undefined) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; isSelected: (outsideReaction?: boolean) => boolean; isFocused: (document: Doc) => boolean; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index ad9dc8f7c..0d5d3e449 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -4,7 +4,7 @@ import { CursorProperty } from "csstype"; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import Switch from 'rc-switch'; -import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { Doc, HeightSym, WidthSym, DataSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; @@ -62,7 +62,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); const style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return
- {this.getDisplayDoc(d, Cast(d.resolvedDataDoc, Doc, null) || this.props.DataDoc, dxf, width)} + {this.getDisplayDoc(d, this.props.DataDoc, dxf, width)}
; }); } @@ -158,7 +158,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const height = () => this.getDocHeight(doc); return boolean; moveDocument: DragManager.MoveFunction; dropAction: "alias" | "copy" | undefined; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; + addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; panelWidth: () => number; panelHeight: () => number; @@ -128,7 +128,7 @@ class TreeView extends React.Component { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath); + @undoBatch openRight = () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath); @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); @undoBatch move = (doc: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); @@ -201,8 +201,8 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.GetProto(CurrentUserUtils.UserDocument.recentlyClosed as Doc).data = new List(), icon: "plus" }); } else if (this.props.document !== CurrentUserUtils.UserDocument.workspaces) { ContextMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.document), icon: "tv" }); - ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "inTab", this.props.libraryPath), icon: "folder" }); - ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath), icon: "caret-square-right" }); + ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab", this.props.libraryPath), icon: "folder" }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath), icon: "caret-square-right" }); if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) { ContextMenu.Instance.addItem({ description: "Focus", event: () => (view => view && view.props.focus(this.props.document, true))(DocumentManager.Instance.getFirstDocumentView(this.props.document)), icon: "camera" }); } @@ -212,7 +212,7 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Create New Workspace", event: () => MainView.Instance.createNewWorkspace(), icon: "plus" }); } ContextMenu.Instance.addItem({ description: "Toggle Theme Colors", event: () => this.props.document.darkScheme = !this.props.document.darkScheme, icon: "minus" }); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { const kvp = Docs.Create.KVPDocument(this.props.document, { _width: 300, _height: 300 }); this.props.addDocTab(kvp, this.props.dataDoc ? this.props.dataDoc : kvp, "onRight"); }, icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { const kvp = Docs.Create.KVPDocument(this.props.document, { _width: 300, _height: 300 }); this.props.addDocTab(kvp, "onRight"); }, icon: "layer-group" }); ContextMenu.Instance.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.document, StrCast(this.props.document.title), () => { }, () => { }), icon: "file" }); ContextMenu.Instance.displayMenu(e.pageX > 156 ? e.pageX - 156 : 0, e.pageY - 15); e.stopPropagation(); @@ -457,7 +457,7 @@ class TreeView extends React.Component { remove: ((doc: Doc) => boolean), move: DragManager.MoveFunction, dropAction: dropActionType, - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean, + addDocTab: (doc: Doc, where: string) => boolean, pinToPres: (document: Doc) => void, backgroundColor: undefined | ((document: Doc) => string | undefined), screenToLocalXf: () => Transform, diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 79fd7d792..95f9fa62f 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -229,10 +229,10 @@ export class CollectionView extends Touchable { const layoutItems = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }); if (this.props.Document.childLayout instanceof Doc) { - layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, undefined, "onRight"), icon: "project-diagram" }); + layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); } if (this.props.Document.childDetailed instanceof Doc) { - layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, undefined, "onRight"), icon: "project-diagram" }); + layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, "onRight"), icon: "project-diagram" }); } !existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" }); diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 027ac5a0e..43ba5c614 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -24,7 +24,7 @@ type SelectorProps = { Document: Doc, Views: DocumentView[], Stack?: any, - addDocTab(doc: Doc, dataDoc: Doc | undefined, location: string): void + addDocTab(doc: Doc, location: string): void }; @observer @@ -60,7 +60,7 @@ export class SelectorContextMenu extends React.Component { col._panX = newPanX; col._panY = newPanY; } - this.props.addDocTab(col, undefined, "inTab"); // bcz: dataDoc? + this.props.addDocTab(col, "inTab"); // bcz: dataDoc? }; } diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 325c92413..b47464517 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -183,9 +183,9 @@ export class LinkFollowBox extends React.Component { } - static _addDocTab: (undefined | ((doc: Doc, dataDoc: Opt, where: string) => boolean)); + static _addDocTab: (undefined | ((doc: Doc, where: string) => boolean)); - static setAddDocTab = (addFunc: (doc: Doc, dataDoc: Opt, where: string) => boolean) => { + static setAddDocTab = (addFunc: (doc: Doc, where: string) => boolean) => { LinkFollowBox._addDocTab = addFunc; } @@ -199,7 +199,7 @@ export class LinkFollowBox extends React.Component { options.context._panX = newPanX; options.context._panY = newPanY; } - (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "onRight"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, "onRight"); if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); @@ -212,7 +212,7 @@ export class LinkFollowBox extends React.Component { openLinkRight = () => { if (LinkFollowBox.destinationDoc) { const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, undefined, "onRight"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, "onRight"); this.highlightDoc(); SelectionManager.DeselectAll(); } @@ -222,8 +222,8 @@ export class LinkFollowBox extends React.Component { @undoBatch jumpToLink = async (options: { shouldZoom: boolean }) => { if (LinkFollowBox.sourceDoc && LinkFollowBox.linkDoc) { - const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; - //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)); + const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, "inTab"); SelectionManager.DeselectAll(); }; + //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, maxLocation)); DocumentManager.Instance.FollowLink(LinkFollowBox.linkDoc, LinkFollowBox.sourceDoc, focus, options && options.shouldZoom, false, undefined); } @@ -234,7 +234,7 @@ export class LinkFollowBox extends React.Component { if (LinkFollowBox.destinationDoc) { const fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc); // this.prosp.addDocTab is empty -- use the link source's addDocTab - (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, "inTab"); this.highlightDoc(); SelectionManager.DeselectAll(); @@ -251,7 +251,7 @@ export class LinkFollowBox extends React.Component { options.context._panX = newPanX; options.context._panY = newPanY; } - (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "inTab"); + (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, "inTab"); if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); this.highlightDoc(); diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 1a40f0c55..a8aa01306 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -16,7 +16,7 @@ library.add(faTrash); interface Props { docView: DocumentView; changeFlyout: () => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; } @observer diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 0c38ff45c..78c77e106 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -17,7 +17,7 @@ interface LinkMenuGroupProps { group: Doc[]; groupType: string; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; docView: DocumentView; } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index b7d27ee30..54f5636e4 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -20,7 +20,7 @@ interface LinkMenuItemProps { sourceDoc: Doc; destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; } @observer diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 73fe4fb5d..36233a7e6 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -34,7 +34,7 @@ interface ContentFittingDocumentViewProps { removeDocument?: (document: Doc) => boolean; active: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; dontRegisterView?: boolean; } diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index 156b16ec8..a0b5cd8ec 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -61,7 +61,7 @@ export class DocuLinkBox extends DocComponent(Doc onClick = (e: React.MouseEvent) => { if (!this.props.Document.onClick) { if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button !== 2 && !e.ctrlKey && this.props.Document.isButton)) { - DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, undefined, "inTab"), false); + DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, "inTab"), false); } e.stopPropagation(); } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 11a33b70a..c0f603171 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -82,7 +82,7 @@ export class DocumentContentsView extends React.Component boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; + addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; zoomToScale: (scale: number) => void; backgroundHalo?: () => boolean; @@ -152,9 +152,9 @@ export class DocumentView extends DocComponent(Docu // RadialMenu.Instance.openMenu(); - // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"), icon: "layer-group", selected: -1 }); // RadialMenu.Instance.addItem({ description: "Delete this document", event: () => this.props.ContainingCollectionView?.removeDocument(this.props.Document), icon: "trash", selected: -1 }); - // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, undefined, "onRight"), icon: "folder", selected: -1 }); + // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "folder", selected: -1 }); // RadialMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 }); // RadialMenu.Instance.displayMenu(pt.pageX - 15, pt.pageY - 15); @@ -253,7 +253,7 @@ export class DocumentView extends DocComponent(Docu if (StrCast(fullScreenAlias.layoutKey) !== "layout_fullScreen" && fullScreenAlias.layout_fullScreen) { fullScreenAlias.layoutKey = "layout_fullScreen"; } - UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, undefined, "inTab"), "double tap"); + UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, "inTab"), "double tap"); SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); } else if (this.onClickHandler && this.onClickHandler.script) { @@ -277,7 +277,7 @@ export class DocumentView extends DocComponent(Docu if (linkDocs.length) { DocumentManager.Instance.FollowLink(undefined, this.props.Document, // open up target if it's not already in view ... by zooming into the button document first and setting flag to reset zoom afterwards - (doc: Doc, maxLocation: string) => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)), + (doc: Doc, maxLocation: string) => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, maxLocation)), ctrlKey, altKey, this.props.ContainingCollectionDoc); } } @@ -644,12 +644,12 @@ export class DocumentView extends DocComponent(Docu const open = ContextMenu.Instance.findByDescription("Open..."); const openItems: ContextMenuProps[] = open && "subitems" in open ? open.subitems : []; openItems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this, this.props.LibraryPath), icon: "desktop" }); - openItems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab", this.props.LibraryPath), icon: "folder" }); - openItems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight", this.props.LibraryPath), icon: "caret-square-right" }); - openItems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" }); - openItems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" }); - openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), undefined, "onRight"), icon: "layer-group" }); - templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, undefined, "onRight"), icon: "eye" }); + openItems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, "inTab", this.props.LibraryPath), icon: "folder" }); + openItems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, "onRight", this.props.LibraryPath), icon: "caret-square-right" }); + openItems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), "inTab"), icon: "folder" }); + openItems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), "onRight"), icon: "caret-square-right" }); + openItems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); + templateDoc && openItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "onRight"), icon: "eye" }); openItems.push({ description: "Open Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); !open && cm.addItem({ description: "Open...", subitems: openItems, icon: "external-link-alt" }); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 00f00dd52..f5c85e143 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -29,7 +29,7 @@ export interface FieldViewProps { select: (isCtrlPressed: boolean) => void; renderDepth: number; addDocument?: (document: Doc) => boolean; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index a191ac4f4..d4da21239 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -36,7 +36,7 @@ export class FontIconBox extends DocComponent( showTemplate = (): void => { const dragFactory = Cast(this.props.Document.dragFactory, Doc, null); - dragFactory && this.props.addDocTab(dragFactory, undefined, "onRight"); + dragFactory && this.props.addDocTab(dragFactory, "onRight"); } specificContextMenu = (): void => { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index fd288f720..842ccdd7b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -916,7 +916,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & // if (linkClicked) { // DocServer.GetRefField(linkClicked).then(async linkDoc => { // (linkDoc instanceof Doc) && - // DocumentManager.Instance.FollowLink(linkDoc, this.props.Document, document => this.props.addDocTab(document, undefined, location ? location : "inTab"), false); + // DocumentManager.Instance.FollowLink(linkDoc, this.props.Document, document => this.props.addDocTab(document, location ? location : "inTab"), false); // }); // } // } else { diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index fda3e3285..1174110e7 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -84,9 +84,9 @@ export class FormattedTextBoxComment { const textBox = FormattedTextBoxComment.textBox; if (FormattedTextBoxComment.linkDoc && !keep && textBox) { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, - (doc: Doc, maxLocation: string) => textBox.props.addDocTab(doc, undefined, e.ctrlKey ? "inTab" : "onRight")); + (doc: Doc, maxLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "inTab" : "onRight")); } else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) { - textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400 }), undefined, "onRight"); + textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400 }), "onRight"); } keep && textBox && FormattedTextBoxComment.start !== undefined && textBox.adoptAnnotation( FormattedTextBoxComment.start, FormattedTextBoxComment.end, FormattedTextBoxComment.mark); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index e6b512adf..93bda6d02 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -22,7 +22,7 @@ export interface KeyValuePairProps { keyWidth: number; PanelHeight: () => number; PanelWidth: () => number; - addDocTab: (doc: Doc, data: Opt, where: string) => boolean; + addDocTab: (doc: Doc, where: string) => boolean; } @observer export class KeyValuePair extends React.Component { @@ -46,7 +46,7 @@ export class KeyValuePair extends React.Component { if (value instanceof Doc) { e.stopPropagation(); e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), undefined, "onRight"), icon: "layer-group" }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); ContextMenu.Instance.displayMenu(e.clientX, e.clientY); } } diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index d4a47c159..8d20bbe59 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -327,12 +327,12 @@ export class PresBox extends React.Component { if (toggle) { if (this.props.Document.inOverlay) { Doc.RemoveDocFromList((CurrentUserUtils.UserDocument.overlays as Doc), this.props.fieldKey, this.props.Document); - CollectionDockingView.AddRightSplit(this.props.Document, this.props.DataDoc); + CollectionDockingView.AddRightSplit(this.props.Document); this.props.Document.inOverlay = false; } else { this.props.Document.x = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[0];// 500;//e.clientX + 25; this.props.Document.y = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[1];////e.clientY - 25; - this.props.addDocTab && this.props.addDocTab(this.props.Document, this.props.DataDoc, "close"); + this.props.addDocTab?.(this.props.Document, "close"); Doc.AddDocToList((CurrentUserUtils.UserDocument.overlays as Doc), this.props.fieldKey, this.props.Document); } } diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 6695e04c3..69c6f2617 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -90,7 +90,7 @@ export class VideoBox extends DocAnnotatableComponent, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; focus: (doc: Doc) => void; dataDoc: Doc; @@ -30,7 +30,7 @@ interface IRegionAnnotationProps { y: number; width: number; height: number; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; document: Doc; dataDoc: Doc; @@ -98,7 +98,7 @@ class RegionAnnotation extends React.Component { const annoGroup = await Cast(this.props.document.group, Doc); if (annoGroup) { DocumentManager.Instance.FollowLink(undefined, annoGroup, - (doc: Doc, maxLocation: string) => this.props.addDocTab(doc, undefined, e.ctrlKey ? "inTab" : "onRight"), + (doc: Doc, maxLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : "onRight"), false, false, undefined); e.stopPropagation(); } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index a9b8c6bbe..198aeb856 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -65,7 +65,7 @@ interface IViewerProps { loaded: (nw: number, nh: number, np: number) => void; active: (outsideReaction?: boolean) => boolean; isChildActive: (outsideReaction?: boolean) => boolean; - addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (document: Doc, where: string) => boolean; pinToPres: (document: Doc) => void; addDocument?: (doc: Doc) => boolean; setPdfViewer: (view: PDFViewer) => void; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 888707ee3..8d62c34c5 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -4,7 +4,7 @@ import { faArrowDown, faArrowUp, faFile as fileSolid, faFileDownload, faLocation import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DataSym } from "../../../new_fields/Doc"; import { documentSchema } from '../../../new_fields/documentSchemas'; import { Id } from "../../../new_fields/FieldSymbols"; import { createSchema, makeInterface } from '../../../new_fields/Schema'; @@ -173,6 +173,7 @@ export class PresElementBox extends DocExtendableComponent { col._panX = newPanX; col._panY = newPanY; } - CollectionDockingView.AddRightSplit(col, undefined); + CollectionDockingView.AddRightSplit(col); }; } render() { @@ -108,7 +108,7 @@ export class LinkContextMenu extends React.Component { unHighlightDoc = (doc: Doc) => () => Doc.UnBrushDoc(doc); - getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col, undefined); + getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col); render() { return ( @@ -272,7 +272,7 @@ export class SearchItem extends React.Component { @computed get contextButton() { - return CollectionDockingView.AddRightSplit(doc, data)} />; + return CollectionDockingView.AddRightSplit(doc)} />; } render() { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 43bbea623..1f2dd1c8f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -17,6 +17,7 @@ import { listSpec } from "./Schema"; import { ComputedField } from "./ScriptField"; import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; +import { DatasetAbout } from "../client/northstar/model/idea/idea"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -495,7 +496,8 @@ export namespace Doc { // if the childDoc is a template for a field, then this will return the expanded layout with its data doc. // otherwise, it just returns the childDoc export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt, childDoc: Doc) { - const resolvedDataDoc = containerDataDoc === containerDoc || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc; + const existingResolvedDataDoc = childDoc[DataSym] !== Doc.GetProto(childDoc)[DataSym] && childDoc[DataSym]; + const resolvedDataDoc = existingResolvedDataDoc || (containerDataDoc === containerDoc || !containerDataDoc || (!childDoc.isTemplateDoc && !childDoc.isTemplateForField) ? undefined : containerDataDoc); return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) { -- cgit v1.2.3-70-g09d2 From 6e5abc3052f4df09b156deccdfe6a7b0b62f492b Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 20 Feb 2020 15:59:53 -0500 Subject: cleaned up a whole bunch of linking stuff. link menu / link types / link default behaviors / added LinkBox --- src/client/documents/Documents.ts | 68 ++++++++++++---------- src/client/util/LinkManager.ts | 48 +++------------ src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 13 +++-- src/client/views/MainView.tsx | 2 + .../CollectionSchemaMovableTableHOC.tsx | 7 ++- .../views/collections/CollectionSchemaView.tsx | 3 +- src/client/views/collections/CollectionSubView.tsx | 2 + .../views/collections/CollectionTreeView.tsx | 24 ++++---- src/client/views/linking/LinkEditor.tsx | 20 +------ src/client/views/linking/LinkMenuGroup.tsx | 2 +- src/client/views/linking/LinkMenuItem.tsx | 5 +- src/client/views/nodes/DocuLinkBox.tsx | 23 +++++++- src/client/views/nodes/DocumentBox.tsx | 6 +- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 9 ++- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/LinkBox.scss | 3 + src/client/views/nodes/LinkBox.tsx | 35 +++++++++++ src/client/views/nodes/PresBox.tsx | 2 +- src/new_fields/ObjectField.ts | 1 - 21 files changed, 152 insertions(+), 128 deletions(-) create mode 100644 src/client/views/nodes/LinkBox.scss create mode 100644 src/client/views/nodes/LinkBox.tsx (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 650538e93..2d2de54b7 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -26,7 +26,6 @@ import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; -import { UndoManager, undoBatch } from "../util/UndoManager"; import { YoutubeBox } from "../apis/youtube/YoutubeBox"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { LinkManager } from "../util/LinkManager"; @@ -56,6 +55,7 @@ import { extname } from "path"; import { MessageStore } from "../../server/Message"; import { ContextMenuProps } from "../views/ContextMenuItem"; import { ContextMenu } from "../views/ContextMenu"; +import { LinkBox } from "../views/nodes/LinkBox"; const requestImageSize = require('../util/request-image-size'); const path = require('path'); @@ -85,6 +85,7 @@ export interface DocumentOptions { y?: number; z?: number; dropAction?: dropActionType; + chilDropAction?: dropActionType; layoutKey?: string; type?: string; title?: string; @@ -103,6 +104,8 @@ export interface DocumentOptions { lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed opacity?: number; defaultBackgroundColor?: string; + isBackground?: boolean; + isButton?: boolean; columnWidth?: number; fontSize?: number; curPage?: number; @@ -220,6 +223,10 @@ export namespace Docs { layout: { view: DirectoryImportBox, dataField: data }, options: { _height: 150 } }], + [DocumentType.LINK, { + layout: { view: LinkBox, dataField: data }, + options: { _height: 75 } + }], [DocumentType.LINKDOC, { data: new List(), layout: { view: EmptyBox, dataField: data }, @@ -399,8 +406,8 @@ export namespace Docs { Scripting.addGlobal(Buxton); - const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "_annotationOn", - "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover"]; + const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "childDropAction", "_annotationOn", + "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "isButton", "isBackground", "removeDropProperties"]; /** * This function receives the relevant document prototype and uses @@ -516,6 +523,30 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.TEXT), text, options); } + export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) { + const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { isBackground: true, isButton: true, removeDropProperties: new List(["isBackground", "isButton"]), ...options }); + const linkDocProto = Doc.GetProto(doc); + linkDocProto.anchor1 = source.doc; + linkDocProto.anchor2 = target.doc; + linkDocProto.anchor1Context = source.ctx; + linkDocProto.anchor2Context = target.ctx; + linkDocProto.anchor1Timecode = source.doc.currentTimecode; + linkDocProto.anchor2Timecode = target.doc.currentTimecode; + + if (linkDocProto.layout_key1 === undefined) { + Cast(linkDocProto.proto, Doc, null)!.layout_key1 = DocuLinkBox.LayoutString("anchor1"); + Cast(linkDocProto.proto, Doc, null)!.layout_key2 = DocuLinkBox.LayoutString("anchor2"); + Cast(linkDocProto.proto, Doc, null)!.linkBoxExcludedKeys = new List(["treeViewExpandedView", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "proto", "aliasNumber", "title", "isPrototype", "lastOpened", "creationDate", "author"]); + Cast(linkDocProto.proto, Doc, null)!.layoutKey = undefined; + } + + LinkManager.Instance.addLink(doc); + + Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(this)"); + Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(this)"); + return doc; + } + export function InkDocument(color: string, tool: number, strokeWidth: number, points: { X: number, Y: number }[], options: DocumentOptions = {}) { const doc = InstanceFromProto(Prototypes.get(DocumentType.INK), new InkField(points), options); doc.color = color; @@ -870,34 +901,11 @@ export namespace DocUtils { if (sv && sv.props.ContainingCollectionDoc === target.doc) return; if (target.doc === CurrentUserUtils.UserDocument) return undefined; - const linkDocProto = new Doc(id, true); - UndoManager.RunInBatch(() => { - linkDocProto.type = DocumentType.LINK; + const linkDoc = Docs.Create.LinkDocument(source, target, { title }, id); - linkDocProto.title = title === "" ? source.doc.title + " to " + target.doc.title : title; - linkDocProto.linkDescription = description; - linkDocProto.isPrototype = true; - - linkDocProto.anchor1 = source.doc; - linkDocProto.anchor2 = target.doc; - linkDocProto.anchor1Context = source.ctx; - linkDocProto.anchor2Context = target.ctx; - linkDocProto.anchor1Groups = new List([]); - linkDocProto.anchor2Groups = new List([]); - linkDocProto.anchor1Timecode = source.doc.currentTimecode; - linkDocProto.anchor2Timecode = target.doc.currentTimecode; - linkDocProto.layout_key1 = DocuLinkBox.LayoutString("anchor1"); - linkDocProto.layout_key2 = DocuLinkBox.LayoutString("anchor2"); - linkDocProto.width = linkDocProto.height = 0; - linkDocProto.isBackground = true; - linkDocProto.isButton = true; - - LinkManager.Instance.addLink(linkDocProto); - - Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(this)"); - Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(this)"); - }, "make link"); - return linkDocProto; + Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(this)"); + Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(this)"); + return linkDoc; } export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number): void { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 1a793b524..1c328c04e 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -135,35 +135,13 @@ export class LinkManager { return DocListCast(linkDoc.anchor2Groups); } } - - // sets the groups of the given anchor in the given link - public setAnchorGroups(linkDoc: Doc, anchor: Doc, groups: Doc[]) { - if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) { - linkDoc.anchor1Groups = new List(groups); - } else { - linkDoc.anchor2Groups = new List(groups); - } - } - public addGroupToAnchor(linkDoc: Doc, anchor: Doc, groupDoc: Doc, replace: boolean = false) { - const groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); - const index = groups.findIndex(gDoc => { - return StrCast(groupDoc.title).toUpperCase() === StrCast(gDoc.title).toUpperCase(); - }); - if (index > -1 && replace) { - groups[index] = groupDoc; - } - if (index === -1) { - groups.push(groupDoc); - } - LinkManager.Instance.setAnchorGroups(linkDoc, anchor, groups); + linkDoc.title = groupDoc.title; } // removes group doc of given group type only from given anchor on given link public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) { - const groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); - const newGroups = groups.filter(groupDoc => StrCast(groupDoc.title).toUpperCase() !== groupType.toUpperCase()); - LinkManager.Instance.setAnchorGroups(linkDoc, anchor, newGroups); + linkDoc.title = "-ungrouped-"; } // returns map of group type to anchor's links in that group type @@ -171,19 +149,10 @@ export class LinkManager { const related = this.getAllRelatedLinks(anchor); const anchorGroups = new Map>(); related.forEach(link => { - const groups = LinkManager.Instance.getAnchorGroups(link, anchor); - - if (groups.length > 0) { - groups.forEach(groupDoc => { - const groupType = StrCast(groupDoc.title); - if (groupType === "") { - const group = anchorGroups.get("*"); - anchorGroups.set("*", group ? [...group, link] : [link]); - } else { - const group = anchorGroups.get(groupType); - anchorGroups.set(groupType, group ? [...group, link] : [link]); - } - }); + if (link.title && link.title !== "-ungrouped-") { + const group = anchorGroups.get(StrCast(link.title)); + anchorGroups.set(StrCast(link.title), group ? [...group, link] : [link]); + } else { // if link is in no groups then put it in default group const group = anchorGroups.get("*"); @@ -215,10 +184,7 @@ export class LinkManager { const md: Doc[] = []; const allLinks = LinkManager.Instance.getAllLinks(); allLinks.forEach(linkDoc => { - const anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, null)); - const anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, null)); - anchor1Groups.forEach(groupDoc => { if (StrCast(groupDoc.title).toUpperCase() === groupType.toUpperCase()) { md.push(groupDoc); } }); - anchor2Groups.forEach(groupDoc => { if (StrCast(groupDoc.title).toUpperCase() === groupType.toUpperCase()) { md.push(groupDoc); } }); + if (StrCast(linkDoc.title).toUpperCase() === groupType.toUpperCase()) { md.push(linkDoc); } }); return md; } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index c8ad78f47..b1cc8f26a 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -120,7 +120,7 @@ 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) { const proto = Doc.GetProto(linkDoc); - proto.sourceContext = this.view0.props.ContainingCollectionDoc; + proto.anchor1Context = this.view0.props.ContainingCollectionDoc; const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : ""; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 07cc1d984..61c199c1d 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -77,11 +77,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> var [sptX, sptY] = transform.transformPoint(0, 0); let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight()); if (documentView.props.Document.type === DocumentType.LINK) { - const rect = documentView.ContentDiv!.getElementsByClassName("docuLinkBox-cont")[0].getBoundingClientRect(); - sptX = rect.left; - sptY = rect.top; - bptX = rect.right; - bptY = rect.bottom; + const docuBox = documentView.ContentDiv!.getElementsByClassName("docuLinkBox-cont"); + if (docuBox.length) { + const rect = docuBox[0].getBoundingClientRect(); + sptX = rect.left; + sptY = rect.top; + bptX = rect.right; + bptY = rect.bottom; + } } return { x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cc75a68fe..8697c601a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -278,6 +278,7 @@ export class MainView extends React.Component { if (this.darkScheme) { switch (doc.type) { case DocumentType.TEXT || DocumentType.BUTTON: return "#2d2d2d"; + case DocumentType.LINK: case DocumentType.COL: { if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; } @@ -287,6 +288,7 @@ export class MainView extends React.Component { switch (doc.type) { case DocumentType.TEXT: return "#f1efeb"; case DocumentType.BUTTON: return "lightgray"; + case DocumentType.LINK: case DocumentType.COL: { if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "lightgray"; } diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 153bbd410..670d6dbb2 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -3,9 +3,9 @@ import { ReactTableDefaults, TableCellRenderer, RowInfo } from "react-table"; import "./CollectionSchemaView.scss"; import { Transform } from "../../util/Transform"; import { Doc } from "../../../new_fields/Doc"; -import { DragManager, SetupDrag } from "../../util/DragManager"; +import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; -import { Cast, FieldValue } from "../../../new_fields/Types"; +import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { ContextMenu } from "../ContextMenu"; import { action } from "mobx"; import { library } from '@fortawesome/fontawesome-svg-core'; @@ -135,6 +135,7 @@ export interface MovableRowProps { rowFocused: boolean; textWrapRow: (doc: Doc) => void; rowWrapped: boolean; + dropAction: string; } export class MovableRow extends React.Component { @@ -219,7 +220,7 @@ export class MovableRow extends React.Component { if (!doc) return <>; const reference = React.createRef(); - const onItemDown = SetupDrag(reference, () => doc, this.move); + const onItemDown = SetupDrag(reference, () => doc, this.move, StrCast(this.props.dropAction) as dropActionType); let className = "collectionSchema-row"; if (this.props.rowFocused) className += " row-focused"; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 7dee7f18f..9486d195a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -408,7 +408,8 @@ export class SchemaTable extends React.Component { rowInfo, rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document), textWrapRow: this.toggleTextWrapRow, - rowWrapped: this.textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1 + rowWrapped: this.textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1, + dropAction: StrCast(this.props.Document.childDropAction) }; } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index bebd99a3a..27a1c6367 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -41,6 +41,8 @@ export interface CollectionViewProps extends FieldViewProps { export interface SubCollectionViewProps extends CollectionViewProps { CollectionView: Opt; children?: never | (() => JSX.Element[]) | React.ReactNode; + overrideDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explict list (see LinkBox) + ignoreFields?: string[]; // used in TreeView to ignore specified fields (see LinkBox) isAnnotationOverlay?: boolean; annotationsKey: string; layoutEngine?: () => string; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index dd622bf9d..15ad49e26 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -34,7 +34,6 @@ import "./CollectionTreeView.scss"; import React = require("react"); import { CollectionViewType } from './CollectionView'; import { RichTextField } from '../../../new_fields/RichTextField'; -import { ObjectField } from '../../../new_fields/ObjectField'; export interface TreeViewProps { @@ -65,6 +64,7 @@ export interface TreeViewProps { treeViewPreventOpen: boolean; renderedIds: string[]; onCheckedClick?: ScriptField; + ignoreFields?: string[]; } library.add(faTrashAlt); @@ -283,6 +283,7 @@ class TreeView extends React.Component { const rows: JSX.Element[] = []; for (const key of Object.keys(ids).slice().sort()) { + if (this.props.ignoreFields?.includes(key)) continue; const contents = doc[key]; let contentElement: (JSX.Element | null)[] | JSX.Element = []; @@ -293,11 +294,11 @@ class TreeView extends React.Component { DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick); + [...this.props.renderedIds, doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.ignoreFields); } else { contentElement = Field.toKeyValueString(doc, key)} @@ -336,7 +337,7 @@ class TreeView extends React.Component { this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen, - [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick)} + [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.ignoreFields)} ; } else if (this.treeViewExpandedView === "fields") { return
    @@ -470,7 +471,8 @@ class TreeView extends React.Component { treeViewPreventOpen: boolean, renderedIds: string[], libraryPath: Doc[] | undefined, - onCheckedClick: ScriptField | undefined + onCheckedClick: ScriptField | undefined, + ignoreFields: string[] | undefined ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -579,7 +581,8 @@ class TreeView extends React.Component { active={active} treeViewHideHeaderFields={treeViewHideHeaderFields} treeViewPreventOpen={treeViewPreventOpen} - renderedIds={renderedIds} />; + renderedIds={renderedIds} + ignoreFields={ignoreFields} />; }); } } @@ -717,7 +720,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { const dropAction = StrCast(this.props.Document.dropAction) as dropActionType; const addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before); const moveDoc = (d: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); - return !this.childDocs ? (null) : ( + const childDocs = this.props.overrideDocuments ? this.props.overrideDocuments : this.childDocs; + return !childDocs ? (null) : (
    ([Templates.Title.Layout]) }); EditableView.loadId = doc[Id]; - this.addDoc(doc, this.childDocs.length ? this.childDocs[0] : undefined, true); + this.addDoc(doc, childDocs.length ? childDocs[0] : undefined, true); })} />)} {this.props.Document.allowClear ? this.renderClearButton : (null)}
      { - TreeView.GetChildElements(this.childDocs, this.props.Document, this.props.Document, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, + TreeView.GetChildElements(childDocs, this.props.Document, this.props.Document, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => BoolCast(this.props.Document.treeViewHideHeaderFields), - BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, ScriptCast(this.props.Document.onCheckedClick)) + BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, ScriptCast(this.props.Document.onCheckedClick), this.props.ignoreFields) }
    diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 3a5cba81b..3c3767832 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -166,7 +166,7 @@ class LinkMetadataEditor extends React.Component { setMetadataValue = (value: string): void => { if (!this._keyError) { this._value = value; - this.props.mdDoc[this._key] = value; + Doc.GetProto(this.props.mdDoc)[this._key] = value; } } @@ -343,25 +343,10 @@ export class LinkEditor extends React.Component { this.props.showLinks(); } - @action - addGroup = (): void => { - // create new metadata document for group - // create new group document - const groupDoc = new Doc(); - groupDoc.anchor1 = this.props.sourceDoc; - const opp = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - if (opp) { - groupDoc.anchor2 = opp; - } - - LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, this.props.sourceDoc, groupDoc); - } - render() { const destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - const groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); - const groups = groupList.map(groupDoc => { + const groups = [this.props.linkDoc].map(groupDoc => { return ; }); @@ -374,7 +359,6 @@ export class LinkEditor extends React.Component {
    Relationships: -
    {groups.length > 0 ? groups :
    There are currently no relationships associated with this link.
    }
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 78c77e106..88f837a03 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -58,7 +58,7 @@ export class LinkMenuGroup extends React.Component { if (index > -1) keys.splice(index, 1); const cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); const docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); - const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { _width: 500, _height: 300, title: groupType + " table" })); + const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { _width: 500, _height: 300, title: groupType + " table", childDropAction: "alias" })); const ref = React.createRef(); return
; } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 43a7daf00..7dd2c0fa8 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -39,9 +39,8 @@ export class LinkMenuItem extends React.Component { } renderMetadata = (): JSX.Element => { - const groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); - const index = groups.findIndex(groupDoc => StrCast(groupDoc.title).toUpperCase() === this.props.groupType.toUpperCase()); - const groupDoc = index > -1 ? groups[index] : undefined; + const index = StrCast(this.props.linkDoc.title).toUpperCase() === this.props.groupType.toUpperCase() ? 0 : -1; + const groupDoc = index > -1 ? this.props.linkDoc : undefined; let mdRows: Array = []; if (groupDoc) { diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index a0b5cd8ec..1983ae529 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -1,6 +1,6 @@ import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; import { makeInterface } from "../../../new_fields/Schema"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; @@ -11,6 +11,8 @@ import { DocComponent } from "../DocComponent"; import "./DocuLinkBox.scss"; import { FieldView, FieldViewProps } from "./FieldView"; import React = require("react"); +import { ContextMenuProps } from "../ContextMenuItem"; +import { ContextMenu } from "../ContextMenu"; type DocLinkSchema = makeInterface<[typeof documentSchema]>; const DocLinkDocument = makeInterface(documentSchema); @@ -61,12 +63,27 @@ export class DocuLinkBox extends DocComponent(Doc onClick = (e: React.MouseEvent) => { if (!this.props.Document.onClick) { if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button !== 2 && !e.ctrlKey && this.props.Document.isButton)) { - DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, "inTab"), false); + if (this.props.Document.linkTarget === "doc") { + const alias = Doc.MakeAlias(this.props.Document); + alias.isButton = undefined; + alias.isBackground = undefined; + this.props.addDocTab(alias, StrCast(this.props.Document.linkOpenLocation, "inTab")); + } else { + DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, StrCast(this.props.Document.linkOpenLocation, "inTab")), false); + } } e.stopPropagation(); } } + specificContextMenu = (e: React.MouseEvent): void => { + const funcs: ContextMenuProps[] = []; + funcs.push({ description: "Open Target " + (this.props.Document.linkOpenLocation !== "onRight" ? "on Right" : "in Tab"), event: () => { e.stopPropagation(); this.props.Document.linkOpenLocation = this.props.Document.linkOpenLocation !== "onRight" ? "onRight" : "inTab" }, icon: "eye" }); + funcs.push({ description: this.props.Document.linkTarget === "doc" ? "Open Link Target" : "Open Link Doc", event: () => { e.stopPropagation(); this.props.Document.linkTarget = this.props.Document.linkTarget === "doc" ? "anchor" : "doc" }, icon: "eye" }); + + ContextMenu.Instance.addItem({ description: "Link Funcs...", subitems: funcs, icon: "asterisk" }); + } + render() { const x = NumCast(this.props.Document[this.props.fieldKey + "_x"], 100); const y = NumCast(this.props.Document[this.props.fieldKey + "_y"], 100); @@ -76,7 +93,7 @@ export class DocuLinkBox extends DocComponent(Doc const timecode = this.props.Document[anchor + "Timecode"]; const targetTitle = StrCast((this.props.Document[anchor]! as Doc).title) + (timecode !== undefined ? ":" + timecode : ""); - return
; const DocBoxDocument = makeInterface(documentSchema); @observer -export class DocumentBox extends DocComponent(DocBoxDocument) { +export class DocumentBox extends DocAnnotatableComponent(DocBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocumentBox, fieldKey); } _prevSelectionDisposer: IReactionDisposer | undefined; _selections: Doc[] = []; @@ -80,7 +80,7 @@ export class DocumentBox extends DocComponent(DocB pheight = () => this.props.PanelHeight() - 30; getTransform = () => this.props.ScreenToLocalTransform().translate(-15, -15); render() { - const containedDoc = this.props.Document[this.props.fieldKey] as Doc; + const containedDoc = this.dataDoc[this.props.fieldKey] as Doc; return
(Docu dragData.dropAction = dropAction; dragData.moveDocument = this.props.moveDocument;// this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.dragDivName = this.props.dragDivName; - this.props.Document.sourceContext = this.props.ContainingCollectionDoc; // bcz: !! shouldn't need this ... use search find the document's context dynamically + this.props.Document.anchor1Context = this.props.ContainingCollectionDoc; // bcz: !! shouldn't need this ... use search find the document's context dynamically DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.Document.onDragStart }); } } @@ -534,7 +534,7 @@ export class DocumentView extends DocComponent(Docu // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true); // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView); de.complete.linkDragData.linkSourceDocument !== this.props.Document && - (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: de.complete.linkDragData.linkSourceDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, "in-text link being created")); // TODODO this is where in text links get passed + (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: de.complete.linkDragData.linkSourceDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, "-ungrouped-")); // TODODO this is where in text links get passed } } @@ -762,9 +762,8 @@ export class DocumentView extends DocComponent(Docu } @computed get finalLayoutKey() { - const { layoutKey } = this.props; - if (typeof layoutKey === "string") { - return layoutKey; + if (typeof this.props.layoutKey === "string") { + return this.props.layoutKey; } const fallback = Cast(this.props.Document.layoutKey, "string"); return typeof fallback === "string" ? fallback : "layout"; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 55d23da12..033511af4 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -114,7 +114,7 @@ export class FieldView extends React.Component { // return // } else if (!(field instanceof Promise)) { - return

{field.toString()}

; + return

{Field.toString(field)}

; } else { return

{"Waiting for server..."}

; diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss new file mode 100644 index 000000000..b5b8e660f --- /dev/null +++ b/src/client/views/nodes/LinkBox.scss @@ -0,0 +1,3 @@ +.linkBox-container-interactive { + pointer-events: all; +} \ No newline at end of file diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx new file mode 100644 index 000000000..0e327e130 --- /dev/null +++ b/src/client/views/nodes/LinkBox.tsx @@ -0,0 +1,35 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { makeInterface, listSpec } from "../../../new_fields/Schema"; +import { returnFalse, returnZero } from "../../../Utils"; +import { CollectionTreeView } from "../collections/CollectionTreeView"; +import { DocExtendableComponent } from "../DocComponent"; +import { FieldView, FieldViewProps } from './FieldView'; +import "./LinkBox.scss"; +import { Cast } from "../../../new_fields/Types"; + +type LinkDocument = makeInterface<[typeof documentSchema]>; +const LinkDocument = makeInterface(documentSchema); + +@observer +export class LinkBox extends DocExtendableComponent(LinkDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); } + render() { + return
e.button === 0 && !e.ctrlKey && e.stopPropagation()} + style={{ background: this.props.backgroundColor?.(this.props.Document) }} > + + + +
; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 8d20bbe59..791ed5ef1 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -187,7 +187,7 @@ export class PresBox extends React.Component { //docToJump stayed same meaning, it was not in the group or was the last element in the group const aliasOf = await Cast(docToJump.aliasOf, Doc); - const srcContext = aliasOf && await Cast(aliasOf.sourceContext, Doc); + const srcContext = aliasOf && await Cast(aliasOf.anchor1Context, Doc); if (docToJump === curDoc) { //checking if curDoc has navigation open const target = await Cast(curDoc.presentationTargetDoc, Doc); diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts index 566104b40..9aa1c9b04 100644 --- a/src/new_fields/ObjectField.ts +++ b/src/new_fields/ObjectField.ts @@ -1,4 +1,3 @@ -import { Doc } from "./Doc"; import { RefField } from "./RefField"; import { OnUpdate, Parent, Copy, ToScriptString, ToString } from "./FieldSymbols"; import { Scripting } from "../client/util/Scripting"; -- cgit v1.2.3-70-g09d2 From 72892f0811f03dae096ebea2dcac24b56d661b07 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 20 Feb 2020 23:45:59 -0500 Subject: more link editor fixes. fixed border rounding. --- src/client/documents/Documents.ts | 2 +- src/client/views/DocumentDecorations.tsx | 2 +- .../CollectionFreeFormLinkView.tsx | 9 ++- src/client/views/linking/LinkEditor.scss | 22 ++++--- src/client/views/linking/LinkEditor.tsx | 73 +++------------------- src/client/views/linking/LinkMenu.tsx | 2 +- src/client/views/linking/LinkMenuItem.tsx | 38 +++-------- 7 files changed, 39 insertions(+), 109 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2d2de54b7..9c83a6a9e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -85,7 +85,7 @@ export interface DocumentOptions { y?: number; z?: number; dropAction?: dropActionType; - chilDropAction?: dropActionType; + childDropAction?: dropActionType; layoutKey?: string; type?: string; title?: string; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 61c199c1d..dcd8dd113 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -256,7 +256,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let dist = Math.sqrt((e.clientX - down[0]) * (e.clientX - down[0]) + (e.clientY - down[1]) * (e.clientY - down[1])); dist = dist < 3 ? 0 : dist; SelectionManager.SelectedDocuments().map(dv => dv.props.Document).map(doc => doc.layout instanceof Doc ? doc.layout : doc.isTemplateForField ? doc : Doc.GetProto(doc)). - map(d => d.borderRounding = `${Math.min(100, dist)}%`); + map(d => d.borderRounding = `${Math.max(0, dist)}px`); return false; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index f04b79ea4..f0c706c1e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -95,10 +95,15 @@ export class CollectionFreeFormLinkView extends React.Component + + {text !== "-ungrouped-" ? text : ""} + ; + x2={`${pt2[0]}`} y2={`${pt2[1]}`} /> + ); } } \ No newline at end of file diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index fc5f2410c..0807216c9 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -22,10 +22,9 @@ } } -.linkEditor-button { - width: 20px; - height: 20px; - margin-left: 6px; +.linkEditor-button, .linkEditor-addbutton { + width: 18px; + height: 18px; padding: 0; // font-size: 12px; border-radius: 10px; @@ -34,6 +33,9 @@ background-color: gray; } } +.linkEditor-addbutton{ + margin-left: 0px; +} .linkEditor-groupsLabel { display: flex; @@ -49,10 +51,11 @@ .linkEditor-group-row { display: flex; margin-bottom: 3px; + } - .linkEditor-group-row-label { - margin-right: 6px; - } + .linkEditor-group-row-label { + margin-right: 6px; + display:inline-block; } .linkEditor-metadata-row { @@ -118,7 +121,6 @@ .linkEditor-typeButton { background-color: transparent; color: $dark-color; - width: 100%; height: 20px; padding: 0 3px; padding-bottom: 2px; @@ -127,6 +129,8 @@ letter-spacing: normal; font-size: 12px; font-weight: bold; + display: inline-block; + width: calc(100% - 40px); &:hover { background-color: $light-color; @@ -140,6 +144,6 @@ margin-top: 5px; .linkEditor-button { - margin-left: 6px; + margin-left: 3px; } } \ No newline at end of file diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 3c3767832..6cdd11430 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -108,7 +108,7 @@ class GroupTypesDropdown extends React.Component { if (this._isEditing || this._groupType === "") { return (
- this.onChange(e.target.value)} onKeyDown={this.onKeyDown} autoFocus>
{this.renderOptions()} @@ -187,7 +187,7 @@ class LinkMetadataEditor extends React.Component {
this.setMetadataKey(e.target.value)}>: this.setMetadataValue(e.target.value)}> - +
); } @@ -223,29 +223,6 @@ export class LinkGroupEditor extends React.Component { LinkManager.Instance.deleteGroupType(groupType); } - copyGroup = async (groupType: string): Promise => { - const sourceGroupDoc = this.props.groupDoc; - - const destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc); - const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); - - - // create new group doc with new metadata doc - const destGroupDoc = new Doc(); - destGroupDoc.title = groupType; - // create new metadata doc with copied kvp - destGroupDoc.anchor1 = sourceGroupDoc.anchor2; - destGroupDoc.anchor2 = sourceGroupDoc.anchor1; - keys.forEach(key => { - const val = sourceGroupDoc[key] === undefined ? "" : StrCast(sourceGroupDoc[key]); - destGroupDoc[key] = val; - }); - - if (destDoc) { - LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, destDoc, destGroupDoc, true); - } - } @action addMetadata = (groupType: string): void => { @@ -276,53 +253,22 @@ export class LinkGroupEditor extends React.Component { return metadata; } - viewGroupAsTable = (groupType: string): JSX.Element => { - const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); - const index = keys.indexOf(""); - if (index > -1) keys.splice(index, 1); - const cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb")); - const docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); - const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { _width: 500, _height: 300, title: groupType + " table" })); - const ref = React.createRef(); - return
; - } - render() { const groupType = StrCast(this.props.groupDoc.title); // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") { - let buttons; - if (groupType === "") { - buttons = ( - <> - - - - - - - ); - } else { - buttons = ( - <> - - - - - {this.viewGroupAsTable(groupType)} - - ); - } + let buttons = ; + let addButton = ; + return (
-

type:

+ {buttons} +
{this.renderMetadata().length > 0 ?

metadata:

: <>} + {addButton} {this.renderMetadata()} -
- {buttons} -
); } @@ -357,9 +303,6 @@ export class LinkEditor extends React.Component {

editing link to: {destination.proto!.title}

-
- Relationships: -
{groups.length > 0 ? groups :
There are currently no relationships associated with this link.
}
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index a8aa01306..b768eacc3 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -60,7 +60,7 @@ export class LinkMenu extends React.Component { if (this._editingLink === undefined) { return (
- + {/* */} {/* */}
{this.renderAllGroups(groups)} diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 7dd2c0fa8..5bf2e4547 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -11,6 +11,7 @@ import { ContextMenu } from '../ContextMenu'; import { LinkFollowBox } from './LinkFollowBox'; import './LinkMenuItem.scss'; import React = require("react"); +import { DocumentManager } from '../../util/DocumentManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -30,7 +31,7 @@ export class LinkMenuItem extends React.Component { private _downY = 0; private _eleClone: any; @observable private _showMore: boolean = false; - @action toggleShowMore() { this._showMore = !this._showMore; } + @action toggleShowMore(e: React.PointerEvent) { e.stopPropagation(); this._showMore = !this._showMore; } onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -40,17 +41,12 @@ export class LinkMenuItem extends React.Component { renderMetadata = (): JSX.Element => { const index = StrCast(this.props.linkDoc.title).toUpperCase() === this.props.groupType.toUpperCase() ? 0 : -1; - const groupDoc = index > -1 ? this.props.linkDoc : undefined; + const mdDoc = index > -1 ? this.props.linkDoc : undefined; let mdRows: Array = []; - if (groupDoc) { - const mdDoc = groupDoc; - if (mdDoc) { - const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); - mdRows = keys.map(key => { - return (
{key}: {StrCast(mdDoc[key])}
); - }); - } + if (mdDoc) { + const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + mdRows = keys.map(key =>
{key}: {StrCast(mdDoc[key])}
); } return (
{mdRows}
); @@ -71,11 +67,6 @@ export class LinkMenuItem extends React.Component { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - if (LinkFollowBox.Instance !== undefined) { - LinkFollowBox.Instance.props.Document.isMinimized = false; - LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); - LinkFollowBox.setAddDocTab(this.props.addDocTab); - } e.stopPropagation(); } @@ -92,26 +83,13 @@ export class LinkMenuItem extends React.Component { onContextMenu = (e: React.MouseEvent) => { e.preventDefault(); - ContextMenu.Instance.addItem({ description: "Open in Link Follower", event: () => this.openLinkFollower(), icon: "link" }); ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" }); ContextMenu.Instance.displayMenu(e.clientX, e.clientY); } @action.bound async followDefault() { - if (LinkFollowBox.Instance !== undefined) { - LinkFollowBox.setAddDocTab(this.props.addDocTab); - LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); - LinkFollowBox.Instance.defaultLinkBehavior(); - } - } - - @action.bound - async openLinkFollower() { - if (LinkFollowBox.Instance !== undefined) { - LinkFollowBox.Instance.props.Document.isMinimized = false; - LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); - } + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false); } render() { @@ -124,7 +102,7 @@ export class LinkMenuItem extends React.Component {

{StrCast(this.props.destinationDoc.title)}

- {canExpand ?
this.toggleShowMore()}> + {canExpand ?
this.toggleShowMore(e)}>
: <>}
-- cgit v1.2.3-70-g09d2 From 8274233572d5ff299e13868c86bd2436f4c276fc Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 21 Feb 2020 09:32:23 -0500 Subject: fixed link naming and exposed link database (at least for testing) --- src/client/documents/Documents.ts | 16 ++++++++++------ src/client/util/LinkManager.ts | 18 +++++++++--------- src/client/views/DocumentButtonBar.tsx | 5 +++-- src/client/views/GestureOverlay.tsx | 2 +- src/client/views/collections/CollectionTreeView.tsx | 4 ++-- src/client/views/linking/LinkEditor.tsx | 10 +++++----- src/client/views/nodes/DocuLinkBox.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 5 +++-- src/server/authentication/models/current_user_utils.ts | 2 +- 9 files changed, 35 insertions(+), 28 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9c83a6a9e..4bad24be9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -119,6 +119,7 @@ export interface DocumentOptions { annotationOn?: Doc; removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document dbDoc?: Doc; + linkRelationship?: string; // type of relatinoship a link represents ischecked?: ScriptField; // returns whether a font icon box is checked activePen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts) onClick?: ScriptField; @@ -225,11 +226,12 @@ export namespace Docs { }], [DocumentType.LINK, { layout: { view: LinkBox, dataField: data }, - options: { _height: 75 } + options: { _height: 150 } }], [DocumentType.LINKDOC, { data: new List(), layout: { view: EmptyBox, dataField: data }, + options: { childDropAction: "alias", title: "LINK DB" } }], [DocumentType.YOUTUBE, { layout: { view: YoutubeBox, dataField: data } @@ -407,7 +409,8 @@ export namespace Docs { Scripting.addGlobal(Buxton); const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "childDropAction", "_annotationOn", - "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "isButton", "isBackground", "removeDropProperties"]; + "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", + "isButton", "isBackground", "removeDropProperties", "treeViewOpen"]; /** * This function receives the relevant document prototype and uses @@ -524,7 +527,7 @@ export namespace Docs { } export function LinkDocument(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, options: DocumentOptions = {}, id?: string) { - const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { isBackground: true, isButton: true, removeDropProperties: new List(["isBackground", "isButton"]), ...options }); + const doc = InstanceFromProto(Prototypes.get(DocumentType.LINK), undefined, { isButton: true, treeViewHideTitle: true, treeViewOpen: false, removeDropProperties: new List(["isBackground", "isButton"]), ...options }); const linkDocProto = Doc.GetProto(doc); linkDocProto.anchor1 = source.doc; linkDocProto.anchor2 = target.doc; @@ -536,7 +539,7 @@ export namespace Docs { if (linkDocProto.layout_key1 === undefined) { Cast(linkDocProto.proto, Doc, null)!.layout_key1 = DocuLinkBox.LayoutString("anchor1"); Cast(linkDocProto.proto, Doc, null)!.layout_key2 = DocuLinkBox.LayoutString("anchor2"); - Cast(linkDocProto.proto, Doc, null)!.linkBoxExcludedKeys = new List(["treeViewExpandedView", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "proto", "aliasNumber", "title", "isPrototype", "lastOpened", "creationDate", "author"]); + Cast(linkDocProto.proto, Doc, null)!.linkBoxExcludedKeys = new List(["treeViewExpandedView", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "proto", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); Cast(linkDocProto.proto, Doc, null)!.layoutKey = undefined; } @@ -896,12 +899,13 @@ export namespace DocUtils { }); } - export function MakeLink(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, title: string = "", description: string = "", id?: string) { + export function MakeLink(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, title: string = "", linkRelationship: string = "", id?: string) { const sv = DocumentManager.Instance.getDocumentView(source.doc); if (sv && sv.props.ContainingCollectionDoc === target.doc) return; if (target.doc === CurrentUserUtils.UserDocument) return undefined; - const linkDoc = Docs.Create.LinkDocument(source, target, { title }, id); + const linkDoc = Docs.Create.LinkDocument(source, target, { title, linkRelationship }, id); + Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('this.anchor1.title +" " + (this.linkRelationship||"to") +" " + this.anchor2.title'); Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(this)"); Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(this)"); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 1c328c04e..4457f41e2 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -40,7 +40,7 @@ export class LinkManager { public getAllLinks(): Doc[] { const ldoc = LinkManager.Instance.LinkManagerDoc; if (ldoc) { - const docs = DocListCast(ldoc.allLinks); + const docs = DocListCast(ldoc.data); return docs; } return []; @@ -50,7 +50,7 @@ export class LinkManager { const linkList = LinkManager.Instance.getAllLinks(); linkList.push(linkDoc); if (LinkManager.Instance.LinkManagerDoc) { - LinkManager.Instance.LinkManagerDoc.allLinks = new List(linkList); + LinkManager.Instance.LinkManagerDoc.data = new List(linkList); return true; } return false; @@ -62,7 +62,7 @@ export class LinkManager { if (index > -1) { linkList.splice(index, 1); if (LinkManager.Instance.LinkManagerDoc) { - LinkManager.Instance.LinkManagerDoc.allLinks = new List(linkList); + LinkManager.Instance.LinkManagerDoc.data = new List(linkList); return true; } } @@ -136,12 +136,12 @@ export class LinkManager { } } public addGroupToAnchor(linkDoc: Doc, anchor: Doc, groupDoc: Doc, replace: boolean = false) { - linkDoc.title = groupDoc.title; + linkDoc.linkRelationship = groupDoc.linkRelationship; } // removes group doc of given group type only from given anchor on given link public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) { - linkDoc.title = "-ungrouped-"; + linkDoc.linkRelationship = "-ungrouped-"; } // returns map of group type to anchor's links in that group type @@ -149,9 +149,9 @@ export class LinkManager { const related = this.getAllRelatedLinks(anchor); const anchorGroups = new Map>(); related.forEach(link => { - if (link.title && link.title !== "-ungrouped-") { - const group = anchorGroups.get(StrCast(link.title)); - anchorGroups.set(StrCast(link.title), group ? [...group, link] : [link]); + if (!link.linkRelationship || link?.linkRelationship !== "-ungrouped-") { + const group = anchorGroups.get(StrCast(link.linkRelationship)); + anchorGroups.set(StrCast(link.linkRelationship), group ? [...group, link] : [link]); } else { // if link is in no groups then put it in default group @@ -184,7 +184,7 @@ export class LinkManager { const md: Doc[] = []; const allLinks = LinkManager.Instance.getAllLinks(); allLinks.forEach(linkDoc => { - if (StrCast(linkDoc.title).toUpperCase() === groupType.toUpperCase()) { md.push(linkDoc); } + if (StrCast(linkDoc.linkRelationship).toUpperCase() === groupType.toUpperCase()) { md.push(linkDoc); } }); return md; } diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index b1cc8f26a..a3d313224 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -25,6 +25,7 @@ import { DragManager } from '../util/DragManager'; import { MetadataEntryMenu } from './MetadataEntryMenu'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import { ComputedField } from '../../new_fields/ScriptField'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -125,8 +126,8 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView | 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); - if (linkDoc.anchor2 instanceof Doc) { - proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODO open to more descriptive descriptions of following in text link + if (linkDoc.anchor2 instanceof Doc && !proto.title) { + proto.title = Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('this.anchor1.title +" " + (this.linkRelationship||"to") +" " + this.anchor2.title'); } } linkDrag?.end(); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 580c53a37..a8cf8c197 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -333,7 +333,7 @@ export default class GestureOverlay extends Touchable { this._d1 = doc; } else if (this._d1 !== doc && !LinkManager.Instance.doesLinkExist(this._d1, doc)) { - DocUtils.MakeLink({ doc: this._d1 }, { doc: doc }); + DocUtils.MakeLink({ doc: this._d1 }, { doc: doc }, "gestural link"); actionPerformed = true; } }; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 15ad49e26..ee64b7d09 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -128,7 +128,7 @@ class TreeView extends React.Component { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = () => this.props.addDocTab(this.props.document, "onRight", this.props.libraryPath); + @undoBatch openRight = () => this.props.addDocTab(this.props.containingCollection.childDropAction === "alias" ? Doc.MakeAlias(this.props.document) : this.props.document, "onRight", this.props.libraryPath); @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); @undoBatch move = (doc: Doc, target: Doc | undefined, addDoc: (doc: Doc) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); @@ -229,7 +229,7 @@ class TreeView extends React.Component { if (de.complete.linkDragData) { const sourceDoc = de.complete.linkDragData.linkSourceDocument; const destDoc = this.props.document; - DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }); + DocUtils.MakeLink({ doc: sourceDoc }, { doc: destDoc }, "tree drop link"); e.stopPropagation(); } if (de.complete.docDragData) { diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 6cdd11430..913a04d66 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -206,13 +206,13 @@ export class LinkGroupEditor extends React.Component { constructor(props: LinkGroupEditorProps) { super(props); - const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.title)); + const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.linkRelationship)); groupMdKeys.forEach(key => this._metadataIds.set(key, Utils.GenerateGuid())); } @action setGroupType = (groupType: string): void => { - this.props.groupDoc.title = groupType; + Doc.GetProto(this.props.groupDoc).linkRelationship = groupType; } removeGroupFromLink = (groupType: string): void => { @@ -241,7 +241,7 @@ export class LinkGroupEditor extends React.Component { renderMetadata = (): JSX.Element[] => { const metadata: Array = []; const groupDoc = this.props.groupDoc; - const groupType = StrCast(groupDoc.title); + const groupType = StrCast(groupDoc.linkRelationship); const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); groupMdKeys.forEach((key) => { @@ -254,7 +254,7 @@ export class LinkGroupEditor extends React.Component { } render() { - const groupType = StrCast(this.props.groupDoc.title); + const groupType = StrCast(this.props.groupDoc.linkRelationship); // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") { let buttons = ; let addButton = ; @@ -293,7 +293,7 @@ export class LinkEditor extends React.Component { const destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); const groups = [this.props.linkDoc].map(groupDoc => { - return ; + return ; }); return !destination ? (null) : ( diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index 1983ae529..c4d99456d 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -67,6 +67,7 @@ export class DocuLinkBox extends DocComponent(Doc const alias = Doc.MakeAlias(this.props.Document); alias.isButton = undefined; alias.isBackground = undefined; + alias.layoutKey = "layout"; this.props.addDocTab(alias, StrCast(this.props.Document.linkOpenLocation, "inTab")); } else { DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, StrCast(this.props.Document.linkOpenLocation, "inTab")), false); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5a358b6d8..84e9b6abb 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -534,7 +534,8 @@ export class DocumentView extends DocComponent(Docu // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true); // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView); de.complete.linkDragData.linkSourceDocument !== this.props.Document && - (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: de.complete.linkDragData.linkSourceDocument }, { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, "-ungrouped-")); // TODODO this is where in text links get passed + (de.complete.linkDragData.linkDocument = DocUtils.MakeLink({ doc: de.complete.linkDragData.linkSourceDocument }, + { doc: this.props.Document, ctx: this.props.ContainingCollectionDoc }, `link from ${de.complete.linkDragData.linkSourceDocument.title} to ${this.props.Document.title}`)); // TODODO this is where in text links get passed } } @@ -868,7 +869,7 @@ export class DocumentView extends DocComponent(Docu ; } @computed get ignorePointerEvents() { - return (this.Document.isBackground && !this.isSelected()) || (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None); + return (this.Document.isBackground && !this.isSelected()) || this.props.layoutKey?.includes("layout_key") || (this.Document.type === DocumentType.INK && InkingControl.Instance.selectedTool !== InkTool.None); } @observable _animate = 0; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 125780c8e..3bab00bed 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -189,7 +189,7 @@ export class CurrentUserUtils { return Docs.Create.ButtonDocument({ _width: 50, _height: 25, title: "Library", fontSize: 10, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", - sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, doc.recentlyClosed as Doc], { + sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, Docs.Prototypes.MainLinkDocument(), doc.recentlyClosed as Doc], { title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, dropAction: "alias", lockedPosition: true, boxShadow: "0 0", }), targetContainer: sidebarContainer, -- cgit v1.2.3-70-g09d2 From ee80ef34d8a9354c2bfbbf4b4c233832f2ea5e26 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 21 Feb 2020 12:09:54 -0500 Subject: made double-click link editing for link anchors. --- src/client/documents/Documents.ts | 2 +- .../CollectionFreeFormLinkView.tsx | 2 +- src/client/views/linking/LinkEditor.scss | 1 + src/client/views/linking/LinkEditor.tsx | 22 +++-- src/client/views/nodes/DocuLinkBox.scss | 16 ++++ src/client/views/nodes/DocuLinkBox.tsx | 95 ++++++++++++++++------ 6 files changed, 101 insertions(+), 37 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4bad24be9..aed14e4f6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -539,7 +539,7 @@ export namespace Docs { if (linkDocProto.layout_key1 === undefined) { Cast(linkDocProto.proto, Doc, null)!.layout_key1 = DocuLinkBox.LayoutString("anchor1"); Cast(linkDocProto.proto, Doc, null)!.layout_key2 = DocuLinkBox.LayoutString("anchor2"); - Cast(linkDocProto.proto, Doc, null)!.linkBoxExcludedKeys = new List(["treeViewExpandedView", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "proto", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); + Cast(linkDocProto.proto, Doc, null)!.linkBoxExcludedKeys = new List(["treeViewExpandedView", "treeViewHideTitle", "removeDropProperties", "linkBoxExcludedKeys", "treeViewOpen", "proto", "aliasNumber", "isPrototype", "lastOpened", "creationDate", "author"]); Cast(linkDocProto.proto, Doc, null)!.layoutKey = undefined; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index f0c706c1e..1038347d4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -95,7 +95,7 @@ export class CollectionFreeFormLinkView extends React.Component {text !== "-ungrouped-" ? text : ""} diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index 0807216c9..b47c8976e 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -4,6 +4,7 @@ width: 100%; height: auto; font-size: 12px; // TODO + user-select: none; } .linkEditor-back { diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 913a04d66..ac4f8a3cf 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -1,17 +1,14 @@ -import { observable, computed, action, trace } from "mobx"; -import React = require("react"); +import { library } from "@fortawesome/fontawesome-svg-core"; +import { faArrowLeft, faCog, faEllipsisV, faExchangeAlt, faPlus, faTable, faTimes, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import './LinkEditor.scss'; -import { StrCast, Cast, FieldValue } from "../../../new_fields/Types"; import { Doc } from "../../../new_fields/Doc"; -import { LinkManager } from "../../util/LinkManager"; -import { Docs } from "../../documents/Documents"; +import { StrCast } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; -import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus } from '@fortawesome/free-solid-svg-icons'; -import { library } from "@fortawesome/fontawesome-svg-core"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { SetupDrag } from "../../util/DragManager"; -import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField"; +import { LinkManager } from "../../util/LinkManager"; +import './LinkEditor.scss'; +import React = require("react"); library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); @@ -279,6 +276,7 @@ interface LinkEditorProps { sourceDoc: Doc; linkDoc: Doc; showLinks: () => void; + hideback?: boolean; } @observer export class LinkEditor extends React.Component { @@ -298,7 +296,7 @@ export class LinkEditor extends React.Component { return !destination ? (null) : (
- + {this.props.hideback ? (null) : }

editing link to: {destination.proto!.title}

diff --git a/src/client/views/nodes/DocuLinkBox.scss b/src/client/views/nodes/DocuLinkBox.scss index 57c1a66e0..7b91b4f36 100644 --- a/src/client/views/nodes/DocuLinkBox.scss +++ b/src/client/views/nodes/DocuLinkBox.scss @@ -5,4 +5,20 @@ height: 25px; border-radius: 20px; pointer-events: all; + user-select: none; + + .docuLinkBox-linkCloser { + position: absolute; + width: 18; + height: 18; + background: rgb(219, 21, 21); + top: -1px; + left: -1px; + border-radius: 5px; + display: flex; + justify-content: center; + align-items: center; + padding-left: 2px; + padding-top: 1px; + } } \ No newline at end of file diff --git a/src/client/views/nodes/DocuLinkBox.tsx b/src/client/views/nodes/DocuLinkBox.tsx index c4d99456d..42e1c9b07 100644 --- a/src/client/views/nodes/DocuLinkBox.tsx +++ b/src/client/views/nodes/DocuLinkBox.tsx @@ -13,6 +13,12 @@ import { FieldView, FieldViewProps } from "./FieldView"; import React = require("react"); import { ContextMenuProps } from "../ContextMenuItem"; import { ContextMenu } from "../ContextMenu"; +import { LinkEditor } from "../linking/LinkEditor"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { SelectionManager } from "../../util/SelectionManager"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; type DocLinkSchema = makeInterface<[typeof documentSchema]>; const DocLinkDocument = makeInterface(documentSchema); @@ -20,16 +26,22 @@ const DocLinkDocument = makeInterface(documentSchema); @observer export class DocuLinkBox extends DocComponent(DocLinkDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocuLinkBox, fieldKey); } - _downx = 0; - _downy = 0; + _doubleTap = false; + _lastTap: number = 0; + _ref = React.createRef(); + _downX = 0; + _downY = 0; + _isOpen = false; + _timeout: NodeJS.Timeout | undefined; @observable _x = 0; @observable _y = 0; @observable _selected = false; - _ref = React.createRef(); + @observable _editing = false; + @observable _forceOpen = false; onPointerDown = (e: React.PointerEvent) => { - this._downx = e.clientX; - this._downy = e.clientY; + this._downX = e.clientX; + this._downY = e.clientY; document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -38,11 +50,11 @@ export class DocuLinkBox extends DocComponent(Doc } onPointerMove = action((e: PointerEvent) => { const cdiv = this._ref && this._ref.current && this._ref.current.parentElement; - if (cdiv && (Math.abs(e.clientX - this._downx) > 5 || Math.abs(e.clientY - this._downy) > 5)) { + if (!this._isOpen && cdiv && (Math.abs(e.clientX - this._downX) > 5 || Math.abs(e.clientY - this._downY) > 5)) { const bounds = cdiv.getBoundingClientRect(); const pt = Utils.getNearestPointInPerimeter(bounds.left, bounds.top, bounds.width, bounds.height, e.clientX, e.clientY); const separation = Math.sqrt((pt[0] - e.clientX) * (pt[0] - e.clientX) + (pt[1] - e.clientY) * (pt[1] - e.clientY)); - const dragdist = Math.sqrt((pt[0] - this._downx) * (pt[0] - this._downx) + (pt[1] - this._downy) * (pt[1] - this._downy)); + const dragdist = Math.sqrt((pt[0] - this._downX) * (pt[0] - this._downX) + (pt[1] - this._downY) * (pt[1] - this._downY)); if (separation > 100) { DragManager.StartLinkTargetsDrag(this._ref.current!, pt[0], pt[1], Cast(this.props.Document[this.props.fieldKey], Doc) as Doc, [this.props.Document]); // Containging collection is the document, not a collection... hack. document.removeEventListener("pointermove", this.onPointerMove); @@ -56,31 +68,53 @@ export class DocuLinkBox extends DocComponent(Doc onPointerUp = (e: PointerEvent) => { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button === 2 || e.ctrlKey || !this.props.Document.isButton)) { + if (Math.abs(e.clientX - this._downX) < 3 && Math.abs(e.clientY - this._downY) < 3 && (e.button === 2 || e.ctrlKey || !this.props.Document.isButton)) { this.props.select(false); } + this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2); + this._lastTap = Date.now(); } + + @action onClick = (e: React.MouseEvent) => { - if (!this.props.Document.onClick) { - if (Math.abs(e.clientX - this._downx) < 3 && Math.abs(e.clientY - this._downy) < 3 && (e.button !== 2 && !e.ctrlKey && this.props.Document.isButton)) { - if (this.props.Document.linkTarget === "doc") { - const alias = Doc.MakeAlias(this.props.Document); - alias.isButton = undefined; - alias.isBackground = undefined; - alias.layoutKey = "layout"; - this.props.addDocTab(alias, StrCast(this.props.Document.linkOpenLocation, "inTab")); - } else { - DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, StrCast(this.props.Document.linkOpenLocation, "inTab")), false); - } + if (!this._doubleTap) { + this._editing = true; + if (!this.props.Document.onClick && !this._isOpen) { + this._timeout = setTimeout(action(() => { + if (Math.abs(e.clientX - this._downX) < 3 && Math.abs(e.clientY - this._downY) < 3 && (e.button !== 2 && !e.ctrlKey && this.props.Document.isButton)) { + DocumentManager.Instance.FollowLink(this.props.Document, this.props.ContainingCollectionDoc as Doc, document => this.props.addDocTab(document, StrCast(this.props.Document.linkOpenLocation, "inTab")), false); + } + this._editing = false; + }), 300 - (Date.now() - this._lastTap)); } - e.stopPropagation(); + } else { + this._timeout && clearTimeout(this._timeout); + this._timeout = undefined; } + e.stopPropagation(); + } + + openLinkDocOnRight = (e: React.MouseEvent) => { + this.props.addDocTab(this.props.Document, "onRight"); + } + openLinkTargetOnRight = (e: React.MouseEvent) => { + const alias = Doc.MakeAlias(Cast(this.props.Document[this.props.fieldKey], Doc, null)); + alias.isButton = undefined; + alias.isBackground = undefined; + alias.layoutKey = "layout"; + this.props.addDocTab(alias, "onRight"); } + @action + openLinkEditor = action((e: React.MouseEvent) => { + SelectionManager.DeselectAll(); + this._editing = this._forceOpen = true; + }) specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Open Target " + (this.props.Document.linkOpenLocation !== "onRight" ? "on Right" : "in Tab"), event: () => { e.stopPropagation(); this.props.Document.linkOpenLocation = this.props.Document.linkOpenLocation !== "onRight" ? "onRight" : "inTab" }, icon: "eye" }); - funcs.push({ description: this.props.Document.linkTarget === "doc" ? "Open Link Target" : "Open Link Doc", event: () => { e.stopPropagation(); this.props.Document.linkTarget = this.props.Document.linkTarget === "doc" ? "anchor" : "doc" }, icon: "eye" }); + funcs.push({ description: "Open Link Target on Right", event: () => this.openLinkTargetOnRight(e), icon: "eye" }); + funcs.push({ description: "Open Link on Right", event: () => this.openLinkDocOnRight(e), icon: "eye" }); + funcs.push({ description: "Open Link Editor", event: () => this.openLinkEditor(e), icon: "eye" }); ContextMenu.Instance.addItem({ description: "Link Funcs...", subitems: funcs, icon: "asterisk" }); } @@ -94,10 +128,25 @@ export class DocuLinkBox extends DocComponent(Doc const timecode = this.props.Document[anchor + "Timecode"]; const targetTitle = StrCast((this.props.Document[anchor]! as Doc).title) + (timecode !== undefined ? ":" + timecode : ""); + const flyout = ( +
Doc.UnBrushDoc(this.props.Document)}> + { })} /> + {!this._forceOpen ? (null) :
this._isOpen = this._editing = this._forceOpen = false)}> + +
} +
+ ); return
; + }} > + {!this._editing && !this._forceOpen ? (null) : + this._isOpen = true} onClose={action(() => this._isOpen = this._forceOpen = this._editing = false)}> + + + + } +
; } } -- cgit v1.2.3-70-g09d2 From 1c73798b14bc91e59ab95225b341008271d0159a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 22 Feb 2020 01:04:55 -0500 Subject: removed LinkFollow box. --- src/client/documents/DocumentTypes.ts | 1 - src/client/documents/Documents.ts | 8 - src/client/views/OverlayView.tsx | 2 +- .../views/collections/CollectionLinearView.tsx | 2 +- .../views/collections/CollectionStackingView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 1 - .../collectionFreeForm/CollectionFreeFormView.tsx | 6 +- src/client/views/linking/LinkFollowBox.scss | 93 ---- src/client/views/linking/LinkFollowBox.tsx | 571 --------------------- src/client/views/linking/LinkMenuItem.tsx | 1 - src/client/views/nodes/DocumentContentsView.tsx | 3 +- .../authentication/models/current_user_utils.ts | 2 - 12 files changed, 7 insertions(+), 685 deletions(-) delete mode 100644 src/client/views/linking/LinkFollowBox.scss delete mode 100644 src/client/views/linking/LinkFollowBox.tsx (limited to 'src/client/documents') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 0e6b59b33..06b15d78c 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -19,7 +19,6 @@ export enum DocumentType { WEBCAM = "webcam", FONTICON = "fonticonbox", PRES = "presentation", - LINKFOLLOW = "linkfollow", PRESELEMENT = "preselement", QUERY = "search", COLOR = "color", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index aed14e4f6..ff64489bb 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -40,7 +40,6 @@ import { PresBox } from "../views/nodes/PresBox"; import { ComputedField, ScriptField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; -import { LinkFollowBox } from "../views/linking/LinkFollowBox"; import { PresElementBox } from "../views/presentationview/PresElementBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { QueryBox } from "../views/nodes/QueryBox"; @@ -250,9 +249,6 @@ export namespace Docs { layout: { view: FontIconBox, dataField: data }, options: { _width: 40, _height: 40, borderRounding: "100%" }, }], - [DocumentType.LINKFOLLOW, { - layout: { view: LinkFollowBox, dataField: data } - }], [DocumentType.WEBCAM, { layout: { view: DashWebRTCVideo, dataField: data } }], @@ -658,10 +654,6 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) }); } - export function LinkFollowBoxDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.LINKFOLLOW), undefined, { ...(options || {}) }); - } - export function PresElementBoxDocument(options?: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) }); } diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 7a99bf0ae..220efd4a8 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -169,7 +169,7 @@ export class OverlayView extends React.Component { document.addEventListener("pointermove", onPointerMove); document.addEventListener("pointerup", onPointerUp); }; - return
+ return
NumCast(this.props.Document._height); // 2 * the padding getTransform = (ele: React.RefObject) => () => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 0d5d3e449..a1cc21319 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -38,7 +38,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @observable _scroll = 0; // used to force the document decoration to update when scrolling @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); } - @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.isMinimized).map(pair => pair.layout); } + @computed get filteredChildren() { return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout); } @computed get xMargin() { return NumCast(this.props.Document._xMargin, 2 * Math.min(this.gridGap, .05 * this.props.PanelWidth())); } @computed get yMargin() { return Math.max(this.props.Document._showTitle && !this.props.Document._showTitleHover ? 30 : 0, NumCast(this.props.Document._yMargin, 0)); } // 2 * this.gridGap)); } @computed get gridGap() { return NumCast(this.props.Document._gridGap, 10); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ed1d674c6..7eeeb6ff1 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -421,7 +421,6 @@ class TreeView extends React.Component { return <>
DocumentManager.Instance.getDocumentView(doc)).map(dv => dv && SelectionManager.SelectDoc(dv, true)); } - public isCurrent(doc: Doc) { return !doc.isMinimized && (Math.abs(NumCast(doc.displayTimecode, -1) - NumCast(this.Document.currentTimecode, -1)) < 1.5 || NumCast(doc.displayTimecode, -1) === -1); } + public isCurrent(doc: Doc) { return (Math.abs(NumCast(doc.displayTimecode, -1) - NumCast(this.Document.currentTimecode, -1)) < 1.5 || NumCast(doc.displayTimecode, -1) === -1); } public getActiveDocuments = () => { return this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout); @@ -433,7 +433,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let x = this.Document._panX || 0; let y = this.Document._panY || 0; - const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.isMinimized).map(pair => pair.layout); + const docs = this.childLayoutPairs.filter(pair => pair.layout instanceof Doc).map(pair => pair.layout); const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay && docs.length && this.childDataProvider(docs[0])) { PDFMenu.Instance.fadeOut(true); @@ -869,7 +869,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { })); this._cachedPool.clear(); Array.from(newPool.keys()).forEach(k => this._cachedPool.set(k, newPool.get(k))); - const elements:ViewDefResult[] = computedElementData.slice(); + const elements: ViewDefResult[] = computedElementData.slice(); this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).forEach(pair => elements.push({ ele: { - - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkFollowBox, fieldKey); } - public static Instance: LinkFollowBox | undefined; - @observable static linkDoc: Doc | undefined = undefined; - @observable static destinationDoc: Doc | undefined = undefined; - @observable static sourceDoc: Doc | undefined = undefined; - @observable selectedMode: string = ""; - @observable selectedContext: Doc | undefined = undefined; - @observable selectedContextAliases: Doc[] | undefined = undefined; - @observable selectedOption: string = ""; - @observable selectedContextString: string = ""; - @observable sourceView: DocumentView | undefined = undefined; - @observable canPan: boolean = false; - @observable shouldUseOnlyParentContext = false; - _contextDisposer?: IReactionDisposer; - - @observable private _docs: { col: Doc, target: Doc }[] = []; - @observable private _otherDocs: { col: Doc, target: Doc }[] = []; - - constructor(props: FieldViewProps) { - super(props); - LinkFollowBox.Instance = this; - this.resetVars(); - this.props.Document.isBackground = true; - } - - componentDidMount = () => { - this.resetVars(); - - this._contextDisposer = reaction( - () => this.selectedContextString, - async () => { - const ref = await DocServer.GetRefField(this.selectedContextString); - runInAction(() => { - if (ref instanceof Doc) { - this.selectedContext = ref; - } - }); - if (this.selectedContext instanceof Doc) { - const aliases = await SearchUtil.GetViewsOfDocument(this.selectedContext); - runInAction(() => { this.selectedContextAliases = aliases; }); - } - } - ); - } - - componentWillUnmount = () => { - this._contextDisposer && this._contextDisposer(); - } - - async resetPan() { - if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionDoc) { - runInAction(() => this.canPan = false); - if (this.sourceView.props.ContainingCollectionDoc._viewType === CollectionViewType.Freeform) { - const docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []); - const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc)); - - aliases.forEach(alias => { - if (docs.filter(doc => doc === alias).length > 0) { - runInAction(() => { this.canPan = true; }); - } - }); - } - } - } - - @action - resetVars = () => { - this.selectedContext = undefined; - this.selectedContextString = ""; - this.selectedMode = ""; - this.selectedOption = ""; - LinkFollowBox.linkDoc = undefined; - LinkFollowBox.sourceDoc = undefined; - LinkFollowBox.destinationDoc = undefined; - this.sourceView = undefined; - this.canPan = false; - this.shouldUseOnlyParentContext = false; - } - - async fetchDocuments() { - if (LinkFollowBox.destinationDoc) { - const dest: Doc = LinkFollowBox.destinationDoc; - const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(dest)); - const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${dest[Id]}"` }); - const map: Map = new Map; - const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs))); - allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index]))); - docs.forEach(doc => map.delete(doc)); - runInAction(async () => { - this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: dest })); - this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target })); - const tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.anchor2Context, Doc)) as Doc; - runInAction(() => tcontext && this._docs.splice(0, 0, { col: tcontext, target: dest })); - }); - } - } - - @action - setLinkDocs = (linkDoc: Doc, source: Doc, dest: Doc) => { - this.resetVars(); - - LinkFollowBox.linkDoc = linkDoc; - LinkFollowBox.sourceDoc = source; - LinkFollowBox.destinationDoc = dest; - this.fetchDocuments(); - - SelectionManager.SelectedDocuments().forEach(dv => { - if (dv.props.Document === LinkFollowBox.sourceDoc) { - this.sourceView = dv; - } - }); - - this.resetPan(); - } - - highlightDoc = () => LinkFollowBox.destinationDoc && Doc.linkFollowHighlight(LinkFollowBox.destinationDoc); - - @undoBatch - openFullScreen = () => { - if (LinkFollowBox.destinationDoc) { - const view = DocumentManager.Instance.getDocumentView(LinkFollowBox.destinationDoc); - view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); - } - } - - @undoBatch - openColFullScreen = (options: { context: Doc }) => { - if (LinkFollowBox.destinationDoc) { - if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { - const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2; - const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2; - options.context._panX = newPanX; - options.context._panY = newPanY; - } - const view = DocumentManager.Instance.getDocumentView(options.context); - view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); - this.highlightDoc(); - } - } - - // should container be a doc or documentview or what? This one needs work and is more long term - @undoBatch - openInContainer = (options: { container: Doc }) => { - - } - - static _addDocTab: (undefined | ((doc: Doc, where: string) => boolean)); - - static setAddDocTab = (addFunc: (doc: Doc, where: string) => boolean) => { - LinkFollowBox._addDocTab = addFunc; - } - - @undoBatch - openLinkColRight = (options: { context: Doc, shouldZoom: boolean }) => { - if (LinkFollowBox.destinationDoc) { - options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context; - if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { - const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2; - const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2; - options.context._panX = newPanX; - options.context._panY = newPanY; - } - (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, "onRight"); - - if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); - - this.highlightDoc(); - SelectionManager.DeselectAll(); - } - } - - @undoBatch - openLinkRight = () => { - if (LinkFollowBox.destinationDoc) { - const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, "onRight"); - this.highlightDoc(); - SelectionManager.DeselectAll(); - } - - } - - @undoBatch - jumpToLink = async (options: { shouldZoom: boolean }) => { - if (LinkFollowBox.sourceDoc && LinkFollowBox.linkDoc) { - const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, "inTab"); SelectionManager.DeselectAll(); }; - //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, maxLocation)); - - DocumentManager.Instance.FollowLink(LinkFollowBox.linkDoc, LinkFollowBox.sourceDoc, focus, options && options.shouldZoom, false, undefined); - } - } - - @undoBatch - openLinkTab = () => { - if (LinkFollowBox.destinationDoc) { - const fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - // this.prosp.addDocTab is empty -- use the link source's addDocTab - (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, "inTab"); - - this.highlightDoc(); - SelectionManager.DeselectAll(); - } - } - - @undoBatch - openLinkColTab = (options: { context: Doc, shouldZoom: boolean }) => { - if (LinkFollowBox.destinationDoc) { - options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context; - if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { - const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2; - const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2; - options.context._panX = newPanX; - options.context._panY = newPanY; - } - (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, "inTab"); - if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom }); - - this.highlightDoc(); - SelectionManager.DeselectAll(); - } - } - - @undoBatch - openLinkInPlace = (options: { shouldZoom: boolean }) => { - - if (LinkFollowBox.destinationDoc && LinkFollowBox.sourceDoc) { - if (this.sourceView && this.sourceView.props.addDocument) { - const destViews = DocumentManager.Instance.getDocumentViews(LinkFollowBox.destinationDoc); - if (!destViews.find(dv => dv.props.ContainingCollectionView === this.sourceView!.props.ContainingCollectionView)) { - const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); - const y = NumCast(LinkFollowBox.sourceDoc.y); - const x = NumCast(LinkFollowBox.sourceDoc.x); - - const width = NumCast(LinkFollowBox.sourceDoc._width); - const height = NumCast(LinkFollowBox.sourceDoc._height); - - alias.x = x + width + 30; - alias.y = y; - alias._width = width; - alias._height = height; - - this.sourceView.props.addDocument(alias); - } - } - - this.jumpToLink({ shouldZoom: options.shouldZoom }); - - this.highlightDoc(); - SelectionManager.DeselectAll(); - } - } - - //set this to be the default link behavior, can be any of the above - public defaultLinkBehavior: (options?: any) => void = this.jumpToLink; - - @action - currentLinkBehavior = () => { - // this.resetPan(); - if (LinkFollowBox.destinationDoc) { - if (this.selectedContextString === "") { - this.selectedContextString = "self"; - this.selectedContext = LinkFollowBox.destinationDoc; - } - if (this.selectedOption === "") this.selectedOption = FollowOptions.NOZOOM; - const shouldZoom: boolean = this.selectedOption === FollowOptions.NOZOOM ? false : true; - const notOpenInContext: boolean = this.selectedContextString === "self" || this.selectedContextString === LinkFollowBox.destinationDoc[Id]; - - if (this.selectedMode === FollowModes.INPLACE) { - if (shouldZoom !== undefined) this.openLinkInPlace({ shouldZoom: shouldZoom }); - } - else if (this.selectedMode === FollowModes.OPENFULL) { - if (notOpenInContext) this.openFullScreen(); - else this.selectedContext && this.openColFullScreen({ context: this.selectedContext }); - } - else if (this.selectedMode === FollowModes.OPENRIGHT) { - if (notOpenInContext) this.openLinkRight(); - else this.selectedContext && this.openLinkColRight({ context: this.selectedContext, shouldZoom: shouldZoom }); - } - else if (this.selectedMode === FollowModes.OPENTAB) { - if (notOpenInContext) this.openLinkTab(); - else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom }); - } - else if (this.selectedMode === FollowModes.PAN) { - this.jumpToLink({ shouldZoom: shouldZoom }); - } - else return; - } - } - - @action - handleModeChange = (e: React.ChangeEvent) => { - const target = e.target as HTMLInputElement; - this.selectedMode = target.value; - this.selectedContext = undefined; - this.selectedContextString = ""; - - this.shouldUseOnlyParentContext = (this.selectedMode === FollowModes.INPLACE || this.selectedMode === FollowModes.PAN); - - if (this.shouldUseOnlyParentContext) { - if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { - this.selectedContext = this.sourceView.props.ContainingCollectionDoc; - this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionDoc.title)); - } - } - } - - @action - handleOptionChange = (e: React.ChangeEvent) => { - const target = e.target as HTMLInputElement; - this.selectedOption = target.value; - } - - @action - handleContextChange = (e: React.ChangeEvent) => { - const target = e.target as HTMLInputElement; - this.selectedContextString = target.value; - // selectedContext is updated in reaction - this.selectedOption = ""; - } - - @computed - get canOpenInPlace() { - if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { - const colDoc = this.sourceView.props.ContainingCollectionDoc; - if (colDoc._viewType === CollectionViewType.Freeform) return true; - } - return false; - } - - @computed - get availableModes() { - return ( -
-
-
-
-
-
-
- ); - } - - @computed - get parentName() { - if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { - return this.sourceView.props.ContainingCollectionDoc.title; - } - } - - @computed - get parentID(): string { - if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) { - return StrCast(this.sourceView.props.ContainingCollectionDoc[Id]); - } - return "col"; - } - - @computed - get availableContexts() { - return ( - this.shouldUseOnlyParentContext ? - - : -
-
- {[...this._docs, ...this._otherDocs].map(doc => { - if (doc && doc.target && doc.col.title !== "Recently Closed") { - return

; - } - })} -
- ); - } - - @computed - get shouldShowZoom(): boolean { - if (this.selectedMode === FollowModes.OPENFULL) return false; - if (this.shouldUseOnlyParentContext) return true; - if (LinkFollowBox.destinationDoc ? this.selectedContextString === LinkFollowBox.destinationDoc[Id] : "self") return false; - - let contextMatch: boolean = false; - if (this.selectedContextAliases) { - this.selectedContextAliases.forEach(alias => { - if (alias._viewType === CollectionViewType.Freeform) contextMatch = true; - }); - } - if (contextMatch) return true; - - return false; - } - - @computed - get availableOptions() { - if (LinkFollowBox.destinationDoc) { - return ( - this.shouldShowZoom ? -
-
-
-
- : -
No Available Options
- ); - } - return null; - } - - render() { - return ( -
-
-
- {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"} -
this.props.Document.isMinimized = true} className="closeDocument">
-
-
{LinkFollowBox.linkDoc ? - LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc ? "Source: " + StrCast(LinkFollowBox.sourceDoc.title) + ", Destination: " + StrCast(LinkFollowBox.destinationDoc.title) - : "" : ""}
-
-
-
-
Mode
-
- {LinkFollowBox.linkDoc ? this.availableModes : "Please select a link to view modes"} -
-
-
-
Context
-
- {this.selectedMode !== "" ? this.availableContexts : "Please select a mode to view contexts"} -
-
-
-
Options
-
- {this.selectedContextString !== "" ? this.availableOptions : "Please select a context to view options"} -
-
-
-
- -
- -
-
- ); - } -} \ No newline at end of file diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 376afa64b..5fd6e4630 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -8,7 +8,6 @@ import { Cast, StrCast } from '../../../new_fields/Types'; import { DragManager } from '../../util/DragManager'; import { LinkManager } from '../../util/LinkManager'; import { ContextMenu } from '../ContextMenu'; -import { LinkFollowBox } from './LinkFollowBox'; import './LinkMenuItem.scss'; import React = require("react"); import { DocumentManager } from '../../util/DocumentManager'; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 73a53f5cc..bfda13eb3 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -9,7 +9,6 @@ import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionView } from "../collections/CollectionView"; -import { LinkFollowBox } from "../linking/LinkFollowBox"; import { YoutubeBox } from "./../../apis/youtube/YoutubeBox"; import { AudioBox } from "./AudioBox"; import { ButtonBox } from "./ButtonBox"; @@ -108,7 +107,7 @@ export class DocumentContentsView extends React.Component