From 646175b9870fb535648c8a9473c245bac57474b3 Mon Sep 17 00:00:00 2001 From: dinhanhtruong <70963346+dinhanhtruong@users.noreply.github.com> Date: Sat, 28 Aug 2021 16:58:02 -0400 Subject: added variable link weights based on relationship importance Link lines are thicker for links belonging to more important relationships. Thickness varies linearly from 3px to 12px. Removed dashed linked lines. --- .../collectionFreeForm/CollectionFreeFormLinkView.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 59891b7a1..92696138e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -41,7 +41,7 @@ export class CollectionFreeFormLinkView extends React.Component this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() + setTimeout(action(() => this._opacity = 0.75), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. const acont = A.rootDoc.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; const bcont = B.rootDoc.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; @@ -175,15 +175,24 @@ export class CollectionFreeFormLinkView extends React.Component; const linkColorList = Doc.UserDoc().linkColorList as List; + const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List; + const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); + //access stroke color using index of the relationship in the color list (default black) - const strokeColor = linkRelationshipList.indexOf(linkRelationship) == -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; + const strokeColor = currRelationshipIndex == -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; + + //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) + //thickness varies linearly from 3px to 12px for increasing link count + const strokeWidth: string = currRelationshipIndex == -1 ? "3px" : Math.floor(2 + 10 * (linkRelationshipSizes[currRelationshipIndex] / Math.max(...linkRelationshipSizes))) + "px"; + return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> - {textX === undefined ? (null) : {StrCast(this.props.LinkDocs[0].description)} -- cgit v1.2.3-70-g09d2 From 80baae4dcf49f818dca4dbfe340013e0e9d197bb Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 3 Sep 2021 03:58:21 -0400 Subject: fixed drawing of link lines - doesn't generate duplicates, and works with text regions, scroll locations, and document anchors. --- src/client/documents/Documents.ts | 9 +++--- src/client/util/DocumentManager.ts | 37 ++++++++++++++-------- .../CollectionFreeFormLinkView.tsx | 8 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 24 ++++++++++---- src/client/views/nodes/PDFBox.tsx | 10 +++--- src/client/views/nodes/WebBox.tsx | 10 +++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 8 files changed, 63 insertions(+), 39 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index bd247bd01..671e27408 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -157,6 +157,7 @@ export class DocumentOptions { z?: number; // whether document is in overlay (1) or not (0 or undefined) author?: string; _layoutKey?: string; + unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf) type?: string; title?: string; "acl-Public"?: string; // public permissions @@ -277,7 +278,7 @@ export class DocumentOptions { // Action Button buttonMenu?: boolean; // whether a action button should be displayed buttonMenuDoc?: Doc; - explainer?:string; + explainer?: string; treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view _treeViewOpen?: boolean; // whether this document is expanded in a tree view (note: need _ and regular versions since this can be specified for both proto and layout docs) @@ -1188,7 +1189,7 @@ export namespace DocUtils { })) as ContextMenuProps[], icon: "sticky-note" }); - const math:ContextMenuProps = ({ + const math: ContextMenuProps = ({ description: ":Math", event: () => { const created = Docs.Create.EquationDocument(); if (created) { @@ -1202,7 +1203,7 @@ export namespace DocUtils { } }, icon: "calculator" }); - const documentList:ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ + const documentList: ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ description: ":" + StrCast(dragDoc.title), event: undoBatch((args: { x: number, y: number }) => { const newDoc = Doc.copyDragFactory(dragDoc); @@ -1215,7 +1216,7 @@ export namespace DocUtils { } }), icon: Doc.toIcon(dragDoc), - })) as ContextMenuProps[]; + })) as ContextMenuProps[]; documentList.push(math) ContextMenu.Instance.addItem({ description: "Create document", diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index cb0ee411c..b72a3189d 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -25,24 +25,35 @@ export class DocumentManager { @action public AddView = (view: DocumentView) => { - DocListCast(view.rootDoc.links).forEach(link => { - const whichOtherAnchor = view.props.LayoutTemplateString?.includes("anchor2") ? "anchor1" : "anchor2"; - const otherDoc = link && (link[whichOtherAnchor] as Doc); - const otherDocAnno = DocumentType.MARKER === otherDoc?.type ? otherDoc.annotationOn as Doc : undefined; - otherDoc && DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, otherDoc) || Doc.AreProtosEqual(dv.rootDoc, otherDocAnno)). - forEach(otherView => { - if (otherView.rootDoc.type !== DocumentType.LINK || otherView.props.LayoutTemplateString !== view.props.LayoutTemplateString) { - this.LinkedDocumentViews.push({ a: whichOtherAnchor === "anchor1" ? otherView : view, b: whichOtherAnchor === "anchor1" ? view : otherView, l: link }); - } - }); - }); + //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString); + if (view.props.LayoutTemplateString?.includes("LinkAnchorBox")) { + const viewAnchorIndex = view.props.LayoutTemplateString.includes("anchor2") ? "anchor2" : "anchor1"; + view.props.LayoutTemplateString && DocListCast(view.rootDoc.links).forEach(link => { + DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)). + forEach(otherView => { + this.LinkedDocumentViews.push( + { + a: viewAnchorIndex === "anchor2" ? otherView : view, + b: viewAnchorIndex === "anchor2" ? view : otherView, + l: link + }); + }); + }); + // this.LinkedDocumentViews.forEach(view => console.log(" LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " + + // view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString)); + } this.DocumentViews.push(view); } public RemoveView = action((view: DocumentView) => { + this.LinkedDocumentViews.slice().forEach(action(pair => { + if (pair.a === view || pair.b === view) { + const li = this.LinkedDocumentViews.indexOf(pair); + li !== -1 && this.LinkedDocumentViews.splice(li, 1); + } + })); + const index = this.DocumentViews.indexOf(view); index !== -1 && this.DocumentViews.splice(index, 1); - - this.LinkedDocumentViews.slice().forEach(action((pair, i) => pair.a === view || pair.b === view ? this.LinkedDocumentViews.splice(i, 1) : null)); }); //gets all views diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 16258404d..6fe46bbb2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -43,8 +43,8 @@ export class CollectionFreeFormLinkView extends React.Component this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. - const acont = A.rootDoc.type === DocumentType.LINK ? A.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; - const bcont = B.rootDoc.type === DocumentType.LINK ? B.ContentDiv.getElementsByClassName("linkAnchorBox-cont") : []; + const acont = A.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); + const bcont = B.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); const adiv = acont.length ? acont[0] : A.ContentDiv; const bdiv = bcont.length ? bcont[0] : B.ContentDiv; const a = adiv.getBoundingClientRect(); @@ -140,8 +140,8 @@ export class CollectionFreeFormLinkView extends React.Component + Doc.AreProtosEqual(link.anchor1 as Doc, this.rootDoc) || + Doc.AreProtosEqual(link.anchor2 as Doc, this.rootDoc) || + ((link.anchor1 as Doc).unrendered && Doc.AreProtosEqual((link.anchor1 as Doc).annotationOn as Doc, this.rootDoc)) || + ((link.anchor2 as Doc).unrendered && Doc.AreProtosEqual((link.anchor2 as Doc).annotationOn as Doc, this.rootDoc)) + ); + } @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); } @computed get allLinkEndpoints() { // the small blue dots that mark the endpoints of links TraceMobx(); - if (this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null; + if (this.layoutDoc.unrendered || this.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return null; if (this.layoutDoc.presBox || this.rootDoc.type === DocumentType.LINK || this.props.dontRegisterView) return (null); - // need to use allLinks for RTF since embedded linked text anchors are not rendered with DocumentViews. All other documents render their anchors with nested DocumentViews so we just need to render the directLinks here - const filtered = DocUtils.FilterDocs(this.rootDoc.type === DocumentType.RTF ? this.allLinks : this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => !d.hidden); + const filtered = DocUtils.FilterDocs(this.directLinks, this.props.docFilters?.() ?? [], []).filter(d => !d.hidden); return filtered.map((link, i) => -
+
{ } componentWillUnmount() { Object.values(this._disposers).forEach(disposer => disposer?.()); - !this.props.dontRegisterView && DocumentManager.Instance.RemoveView(this); + !BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this); } render() { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 3a399bfdb..2bafb3b7f 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -79,9 +79,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent
- +
; } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 1f85219d6..eaedd48c7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -187,8 +187,8 @@ export class WebBox extends ViewBoxAnnotatableComponent
- +
); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 59d43f8d7..bc578f95d 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -713,7 +713,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() }); let tr = state.tr.addMark(sel.from, sel.to, splitter); if (sel.from !== sel.to) { - const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: this._editorView?.state.doc.textBetween(sel.from, sel.to) }); + const anchor = anchorDoc ?? Docs.Create.TextanchorDocument({ title: this._editorView?.state.doc.textBetween(sel.from, sel.to), unrendered: true }); const href = targetHref ?? Doc.localServerPath(anchor); if (anchor !== anchorDoc) this.addDocument(anchor); tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => { -- cgit v1.2.3-70-g09d2 From 64ff849d21273f7440917ef15a4b1c7f1909687c Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 3 Sep 2021 13:16:48 -0400 Subject: fixed warnings. cleaned up link lines a bit more - simplified, and allowed multiple aliases to share a link. fixed link lines to text anchors from flapping around wildly when camera pans --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 12 +++---- src/client/util/DocumentManager.ts | 38 +++++++++++++--------- src/client/views/PropertiesButtons.tsx | 2 +- .../CollectionFreeFormLinkView.tsx | 13 +++++--- .../CollectionFreeFormLinksView.tsx | 19 ++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/LinkAnchorBox.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 10 +++--- src/client/views/nodes/WebBox.tsx | 4 +-- .../views/nodes/button/textButton/TextButton.tsx | 2 +- src/client/views/nodes/button/textButton/index.ts | 2 +- .../views/nodes/button/toggleButton/index.ts | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 +++----- src/client/views/pdf/PDFViewer.tsx | 5 ++- 15 files changed, 60 insertions(+), 67 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 671e27408..9a45da440 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1217,7 +1217,7 @@ export namespace DocUtils { }), icon: Doc.toIcon(dragDoc), })) as ContextMenuProps[]; - documentList.push(math) + documentList.push(math); ContextMenu.Instance.addItem({ description: "Create document", subitems: documentList, diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 56807c63b..f9c55da29 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -832,7 +832,7 @@ export class CurrentUserUtils { await doc.myTrails; if (doc.myTrails === undefined) { const newTrail = ScriptField.MakeScript(`createNewPresentation()`); - const newTrailButton:Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "New trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); + const newTrailButton: Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "New trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Trails", _showTitle: "title", _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", @@ -852,16 +852,16 @@ export class CurrentUserUtils { doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); // doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true }); const newFolder = ScriptField.MakeFunction(`doc.makeFolder()`, { doc: doc.myFilesystem })!; - const newFolderButton:Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); + const newFolderButton: Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], { - title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, + title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." })); - (doc.myTrails as any as Doc).contextMenuScripts = new List([newFolder!]); + (doc.myTrails as any as Doc).contextMenuScripts = new List([newFolder]); (doc.myTrails as any as Doc).contextMenuLabels = new List(["Create new folder"]); } return doc.myFilesystem as any as Doc; @@ -870,7 +870,7 @@ export class CurrentUserUtils { static setupRecentlyClosedDocs(doc: Doc) { if (doc.myRecentlyClosedDocs === undefined) { const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`); - const clearDocsButton:Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); + const clearDocsButton: Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", @@ -1215,7 +1215,7 @@ export class CurrentUserUtils { // Import sidebar is where shared documents are contained static setupUploadSidebar(doc: Doc) { if (doc.myUploadDocs === undefined) { - const newUploadButton:Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true }); + const newUploadButton: Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true }); doc.myUploadDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "My Uploads", _forceActive: true, buttonMenu: true, buttonMenuDoc: newUploadButton, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index b72a3189d..9e190ad02 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,19 +1,21 @@ import { action, observable, runInAction } from 'mobx'; import { Doc, DocListCast, DocListCastAsync, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; -import { Cast, NumCast, StrCast } from '../../fields/Types'; +import { Cast } from '../../fields/Types'; import { returnFalse } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { LightboxView } from '../views/LightboxView'; import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView'; +import { LinkAnchorBox } from '../views/nodes/LinkAnchorBox'; import { Scripting } from './Scripting'; export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) @observable public DocumentViews: DocumentView[] = []; + @observable public LinkAnchorBoxViews: DocumentView[] = []; @observable public RecordingEvent = 0; @observable public LinkedDocumentViews: { a: DocumentView, b: DocumentView, l: Doc }[] = []; @@ -26,23 +28,24 @@ export class DocumentManager { @action public AddView = (view: DocumentView) => { //console.log("MOUNT " + view.props.Document.title + "/" + view.props.LayoutTemplateString); - if (view.props.LayoutTemplateString?.includes("LinkAnchorBox")) { + if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { const viewAnchorIndex = view.props.LayoutTemplateString.includes("anchor2") ? "anchor2" : "anchor1"; - view.props.LayoutTemplateString && DocListCast(view.rootDoc.links).forEach(link => { - DocumentManager.Instance.DocumentViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)). - forEach(otherView => { - this.LinkedDocumentViews.push( - { - a: viewAnchorIndex === "anchor2" ? otherView : view, - b: viewAnchorIndex === "anchor2" ? view : otherView, - l: link - }); - }); + DocListCast(view.rootDoc.links).forEach(link => { + this.LinkAnchorBoxViews?.filter(dv => Doc.AreProtosEqual(dv.rootDoc, link) && !dv.props.LayoutTemplateString?.includes(viewAnchorIndex)). + forEach(otherView => this.LinkedDocumentViews.push( + { + a: viewAnchorIndex === "anchor2" ? otherView : view, + b: viewAnchorIndex === "anchor2" ? view : otherView, + l: link + }) + ); }); + this.LinkAnchorBoxViews.push(view); // this.LinkedDocumentViews.forEach(view => console.log(" LV = " + view.a.props.Document.title + "/" + view.a.props.LayoutTemplateString + " --> " + // view.b.props.Document.title + "/" + view.b.props.LayoutTemplateString)); + } else { + this.DocumentViews.push(view); } - this.DocumentViews.push(view); } public RemoveView = action((view: DocumentView) => { this.LinkedDocumentViews.slice().forEach(action(pair => { @@ -52,8 +55,13 @@ export class DocumentManager { } })); - const index = this.DocumentViews.indexOf(view); - index !== -1 && this.DocumentViews.splice(index, 1); + if (view.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) { + const index = this.LinkAnchorBoxViews.indexOf(view); + this.LinkAnchorBoxViews.splice(index, 1); + } else { + const index = this.DocumentViews.indexOf(view); + index !== -1 && this.DocumentViews.splice(index, 1); + } }); //gets all views diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 9fe2122e6..dd737dc9d 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -156,7 +156,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { ["toggleDetail", "Toggle Detail"], ["linkInPlace", "Follow Link"], ["linkOnRight", "Open Link on Right"] - ] + ]; const currentSelection = this.selectedDoc.onClickBehavior; // Get items to place into the list diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 6fe46bbb2..3b3e069d8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -5,7 +5,6 @@ import { Id } from "../../../../fields/FieldSymbols"; import { List } from "../../../../fields/List"; import { NumCast, StrCast } from "../../../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; -import { DocumentType } from "../../../documents/DocumentTypes"; import { LinkManager } from "../../../util/LinkManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; @@ -69,8 +68,10 @@ export class CollectionFreeFormLinkView extends React.Component= 0 && mpx <= 1) linkDoc.anchor1_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.anchor1_y = mpy * 100; } if (!targetBhyperlink) { if (linkDoc.linkAutoMove) { @@ -80,8 +81,10 @@ export class CollectionFreeFormLinkView extends React.Component= 0 && mpx <= 1) linkDoc.anchor2_x = mpx * 100; + if (mpy >= 0 && mpy <= 1) linkDoc.anchor2_y = mpy * 100; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index e812064b7..dacbb3508 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,30 +1,17 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; -import { Utils } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; -import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); -import { DocumentType } from "../../../documents/DocumentTypes"; -import { LinkManager } from "../../../util/LinkManager"; @observer export class CollectionFreeFormLinksView extends React.Component { @computed get uniqueConnections() { - const connections = DocumentManager.Instance.LinkedDocumentViews - .filter(c => c.a.props.Document.type === DocumentType.LINK || c.b.props.Document.type === DocumentType.LINK) - .reduce((drawnPairs, connection) => { - const matchingPairs = drawnPairs.filter(pair => connection.a === pair.a && connection.b === pair.b); - matchingPairs.forEach(drawnPair => drawnPair.l.add(connection.l)); - if (!matchingPairs.length) drawnPairs.push({ a: connection.a, b: connection.b, l: new Set([connection.l]) }); - return drawnPairs; - }, [] as { a: DocumentView, b: DocumentView, l: Set }[]); - const set = new Map(); - connections.map(c => !set.has(Array.from(c.l)[0]) && set.set(Array.from(c.l)[0], { a: c.a, b: c.b, l: Array.from(c.l) })); - return Array.from(set.values()).map(c => ); + return Array.from(new Set(DocumentManager.Instance.LinkedDocumentViews)).map(c => + + ); } render() { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2deaea823..018c2a895 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1457,7 +1457,7 @@ export class CollectionFreeFormView extends CollectionSubView
- {this.layoutDoc["_backgroundGridShow"] ? this.backgroundGrid : (null)} + {this.layoutDoc._backgroundGridShow ? this.backgroundGrid : (null)} ; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index eaedd48c7..7e46d8433 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as WebRequest from 'web-request'; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; @@ -24,6 +24,7 @@ import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent"; import { DocumentDecorations } from "../DocumentDecorations"; +import { Colors } from "../global/globalEnums"; import { LightboxView } from "../LightboxView"; import { MarqueeAnnotator } from "../MarqueeAnnotator"; import { AnchorMenu } from "../pdf/AnchorMenu"; @@ -33,7 +34,6 @@ import { FieldView, FieldViewProps } from './FieldView'; import { LinkDocPreview } from "./LinkDocPreview"; import "./WebBox.scss"; import React = require("react"); -import { Colors } from "../global/globalEnums"; const _global = (window /* browser */ || global /* node */) as any; const htmlToText = require("html-to-text"); diff --git a/src/client/views/nodes/button/textButton/TextButton.tsx b/src/client/views/nodes/button/textButton/TextButton.tsx index 414b50dcb..e18590a95 100644 --- a/src/client/views/nodes/button/textButton/TextButton.tsx +++ b/src/client/views/nodes/button/textButton/TextButton.tsx @@ -12,6 +12,6 @@ export class TextButton extends Component { return (
{this.props.label} -
) +
); } } \ No newline at end of file diff --git a/src/client/views/nodes/button/textButton/index.ts b/src/client/views/nodes/button/textButton/index.ts index 01fcde54f..01d62eb7e 100644 --- a/src/client/views/nodes/button/textButton/index.ts +++ b/src/client/views/nodes/button/textButton/index.ts @@ -1 +1 @@ -export * from './TextButton' \ No newline at end of file +export * from './TextButton'; \ No newline at end of file diff --git a/src/client/views/nodes/button/toggleButton/index.ts b/src/client/views/nodes/button/toggleButton/index.ts index 48b28fb4c..cdb9c527c 100644 --- a/src/client/views/nodes/button/toggleButton/index.ts +++ b/src/client/views/nodes/button/toggleButton/index.ts @@ -1 +1 @@ -export * from './ToggleButton' \ No newline at end of file +export * from './ToggleButton'; \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index bc578f95d..cad9af2b0 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1448,18 +1448,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const margins = 2 * NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0); const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined; if (children) { - var proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins); - var scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); + const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins); + const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); if (scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation const setScrollHeight = () => this.rootDoc[this.fieldKey + "-scrollHeight"] = scrollHeight; if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) { setScrollHeight(); - // setTimeout(() => { - // proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + Number(getComputedStyle(child).height.replace("px", "")), margins); - // scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.docMaxAutoHeight, proseHeight), proseHeight); - // scrollHeight && setScrollHeight(); - // }, 10); - } else setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... + } else { + setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... + } } } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 02010e123..d953c6b6c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -2,14 +2,13 @@ import { action, computed, IReactionDisposer, observable, ObservableMap, reactio import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; -import { createSchema } from "../../../fields/Schema"; import { Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils, returnFalse, returnEmptyString, returnEmptyFilter } from "../../../Utils"; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, OmitKeys, smoothScroll, Utils } from "../../../Utils"; import { DocUtils } from "../../documents/Documents"; import { Networking } from "../../Network"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -- cgit v1.2.3-70-g09d2 From f097eefd91614d4efa2a89b3d8c7d1071d6c0b6f Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 17 Sep 2021 14:07:09 -0400 Subject: added 'unset' docFilters. changed link doc views to use comparison box with title/caption. fixed linkEditor to write to data doc. generalized comparisonBox rendering to use parameterized fields. fixed pdf/web to honor pointerEvents none prop and fixed textAnnotations to get rendered once as an Annotation. moved filterIcon stuff into DocumentView --- src/Utils.ts | 4 +++- src/client/DocServer.ts | 2 ++ src/client/documents/Documents.ts | 17 +++++++++++------ src/client/views/collections/CollectionView.tsx | 12 ------------ .../collectionFreeForm/CollectionFreeFormLinkView.tsx | 6 +++--- src/client/views/linking/LinkEditor.tsx | 11 ++++++----- src/client/views/nodes/ComparisonBox.tsx | 8 +++++--- src/client/views/nodes/DocumentView.tsx | 19 +++++++++++++++++-- src/client/views/nodes/LinkBox.tsx | 19 ++++++------------- src/client/views/nodes/LinkDescriptionPopup.tsx | 7 ++++--- src/client/views/nodes/PDFBox.tsx | 9 ++++----- src/client/views/nodes/WebBox.tsx | 14 ++++++++------ src/client/views/pdf/Annotation.scss | 3 +++ src/client/views/pdf/PDFViewer.tsx | 13 +++++++------ src/fields/Doc.ts | 2 +- 15 files changed, 80 insertions(+), 66 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 6eacd8296..e11f1154e 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -125,7 +125,9 @@ export namespace Utils { // bcz: isTransparent(__value__) is a hack. it would be nice to have acual functions be parsed, but now Doc.matchFieldValue is hardwired to recognize just this one return `backgroundColor:${isTransparentFunctionHack},${noRecursionHack}:x`;// bcz: hack. noRecursion should probably be either another ':' delimited field, or it should be a modifier to the comparision (eg., check, x, etc) field } - + export function PropUnsetFilter(prop: string) { + return `${prop}:any,${noRecursionHack}:unset`; + } export function toRGBAstr(col: { r: number, g: number, b: number, a?: number }) { return "rgba(" + col.r + "," + col.g + "," + col.b + (col.a !== undefined ? "," + col.a : "") + ")"; diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index e498a7cca..3b376a0e7 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -241,6 +241,7 @@ export namespace DocServer { // the field has been returned from the server const getSerializedField = Utils.EmitCallback(_socket, MessageStore.GetRefField, id); + console.log(id) // when the serialized RefField has been received, go head and begin deserializing it into an object. // Here, once deserialized, we also invoke .proto to 'load' the document's prototype, which ensures that all // future .proto calls on the Doc won't have to go farther than the cache to get their actual value. @@ -264,6 +265,7 @@ export namespace DocServer { } else { delete _cache[id]; } + console.log(id, field); return field; // either way, overwrite or delete any promises cached at this id (that we inserted as flags // to indicate that the field was in the process of being fetched). Now everything diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f50f306a3..e8185400e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -962,13 +962,17 @@ export namespace DocUtils { // metadata facets that exist const exists = Object.keys(facet).filter(value => facet[value] === "exists"); + // metadata facets that exist + const unsets = Object.keys(facet).filter(value => facet[value] === "unset"); + // facets that have an x next to them const xs = Object.keys(facet).filter(value => facet[value] === "x"); - if (!exists.length && !xs.length && !checks.length && !matches.length) return true; + if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined); + const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined); const satisfiesMatchFacets = !matches.length ? true : matches.some(value => { if (facetKey.startsWith("*")) { // fields starting with a '*' are used to match families of related fields. ie, *lastModified will match text-lastModified, data-lastModified, etc const allKeys = Array.from(Object.keys(d)); @@ -980,11 +984,11 @@ export namespace DocUtils { }); // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria if ((parentCollection?.currentFilter as Doc)?.filterBoolean === "OR") { - if (satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; + if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria else { - if (!satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; + if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; } } @@ -1088,10 +1092,11 @@ export namespace DocUtils { "anchor2-useLinkSmallAnchor": target.doc.useLinkSmallAnchor ? true : undefined, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, - layout_linkView: Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null), - linkDisplay: true, hidden: true, + linkDisplay: true, + hidden: true, linkRelationship, - _layoutKey: "layout_linkView", + _showCaption: "description", + _showTitle: "linkRelationship", description }, id), showPopup); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5c9c8063b..38e027fb3 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -246,12 +246,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent this.props.childLayoutTemplate?.() || Cast(this.rootDoc.childLayoutTemplate, Doc, null); @computed get childLayoutString() { return StrCast(this.rootDoc.childLayoutString); } - /** - * Shows the filter icon if it's a user-created collection which isn't a dashboard and has some docFilters applied on it or on the current dashboard. - */ - @computed get showFilterIcon() { - return this.props.Document.viewType !== CollectionViewType.Docking && !Doc.IsSystem(this.props.Document) && this._subView?.IsFiltered(); - } @observable _subView: any = undefined; @@ -280,12 +274,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent {this.showIsTagged()} {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} - {this.showFilterIcon ? - { this.props.select(false); CurrentUserUtils.propertiesWidth = 250; e.stopPropagation(); })} - /> - : (null)} ); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 3b3e069d8..2cb487588 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -1,6 +1,6 @@ import { action, computed, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../fields/Doc"; +import { Doc, Field } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; import { List } from "../../../../fields/List"; import { NumCast, StrCast } from "../../../../fields/Types"; @@ -180,7 +180,7 @@ export class CollectionFreeFormLinkView extends React.Component; const linkColorList = Doc.UserDoc().linkColorList as List; //access stroke color using index of the relationship in the color list (default black) @@ -189,7 +189,7 @@ export class CollectionFreeFormLinkView extends React.Component {textX === undefined ? (null) : - {StrCast(this.props.LinkDocs[0].description)} + {Field.toString(this.props.LinkDocs[0].description as any as Field)} } ); } diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 240a71c3e..219f7d3a2 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -2,13 +2,14 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, StrListCast } from "../../../fields/Doc"; -import { DateCast, StrCast } from "../../../fields/Types"; +import { Doc, StrListCast, Field } from "../../../fields/Doc"; +import { DateCast, StrCast, Cast } from "../../../fields/Types"; import { LinkManager } from "../../util/LinkManager"; import { undoBatch } from "../../util/UndoManager"; import './LinkEditor.scss'; import { LinkRelationshipSearch } from "./LinkRelationshipSearch"; import React = require("react"); +import { ToString } from "../../../fields/FieldSymbols"; interface LinkEditorProps { @@ -20,7 +21,7 @@ interface LinkEditorProps { @observer export class LinkEditor extends React.Component { - @observable description = StrCast(LinkManager.currentLink?.description); + @observable description = Field.toString(LinkManager.currentLink?.description as any as Field); @observable relationship = StrCast(LinkManager.currentLink?.linkRelationship); @observable openDropdown: boolean = false; @observable showInfo: boolean = false; @@ -41,7 +42,7 @@ export class LinkEditor extends React.Component { @undoBatch setRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { - LinkManager.currentLink.linkRelationship = value; + Doc.GetProto(LinkManager.currentLink).linkRelationship = value; const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color @@ -79,7 +80,7 @@ export class LinkEditor extends React.Component { @undoBatch setDescripValue = action((value: string) => { if (LinkManager.currentLink) { - LinkManager.currentLink.description = value; + Doc.GetProto(LinkManager.currentLink).description = value; this.buttonColor = "rgb(62, 133, 55)"; setTimeout(action(() => this.buttonColor = ""), 750); return true; diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 6708a08ee..72c7e4f45 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -15,6 +15,7 @@ import "./ComparisonBox.scss"; import { DocumentView, DocumentViewProps } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import React = require("react"); +import { DocumentType } from '../../documents/DocumentTypes'; export const comparisonSchema = createSchema({}); @@ -87,7 +88,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent; }; const displayDoc = (which: string) => { - const whichDoc = Cast(this.dataDoc[`compareBox-${which}`], Doc, null); + var whichDoc = Cast(this.dataDoc[which], Doc, null); + if (whichDoc.type === DocumentType.MARKER) whichDoc = Cast(whichDoc.annotationOn, Doc, null); return whichDoc ? <> - {displayBox("after", 1, this.props.PanelWidth() - 3)} + {displayBox(this.fieldKey === "data" ? "compareBox-after" : `${this.fieldKey}2`, 1, this.props.PanelWidth() - 3)}
- {displayBox("before", 0, 0)} + {displayBox(this.fieldKey === "data" ? "compareBox-before" : `${this.fieldKey}1`, 0, 0)}
(this.props.PanelWidth() - 5) / this.props.PanelWidth() ? "w-resize" : undefined }} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 46a8b6629..35249c7f4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -13,7 +13,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Ty import { AudioField } from "../../../fields/URLField"; import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { MobileInterface } from '../../../mobile/MobileInterface'; -import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick } from "../../../Utils"; +import { emptyFunction, hasDescendantTarget, OmitKeys, returnTrue, returnVal, Utils, lightOrDark, simulateMouseClick, returnEmptyString } from "../../../Utils"; import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from '../../documents/DocumentTypes'; @@ -802,6 +802,12 @@ export class DocumentViewInternal extends DocComponent StrListCast(this.props.Document._docFilters); + collectionRangeDocFilters = () => StrListCast(this.props.Document._docRangeFilters); + @computed get showFilterIcon() { + return this.collectionFilters().length || this.collectionRangeDocFilters().length ? "hasFilter" : + this.props.docFilters?.().filter(f => Utils.IsRecursiveFilter(f)).length || this.props.docRangeFilters().length ? "inheritsFilter" : undefined + } rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; panelHeight = () => this.props.PanelHeight() - this.headerMargin; screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin); @@ -832,7 +838,7 @@ export class DocumentViewInternal extends DocComponent; return
this.props.PanelHeight() || 1; anchorStyleProvider = (doc: Opt, props: Opt, property: string): any => { switch (property) { + case StyleProp.ShowTitle: return ""; case StyleProp.PointerEvents: return "none"; case StyleProp.LinkSource: return this.props.Document;// pass the LinkSource to the LinkAnchorBox default: return this.props.styleProvider?.(doc, props, property); @@ -901,6 +908,8 @@ export class DocumentViewInternal extends DocComponent } + {this.showFilterIcon ? + { this.props.select(false); CurrentUserUtils.propertiesWidth = 250; e.stopPropagation(); })} + /> + : (null)}
; } } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 55ea45bb8..b82d16677 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -2,10 +2,10 @@ import React = require("react"); import { observer } from "mobx-react"; import { documentSchema } from "../../../fields/documentSchemas"; import { makeInterface } from "../../../fields/Schema"; -import { returnFalse } from "../../../Utils"; -import { CollectionTreeView } from "../collections/CollectionTreeView"; +import { emptyFunction, returnFalse } from "../../../Utils"; import { ViewBoxBaseComponent } from "../DocComponent"; import { StyleProp } from "../StyleProvider"; +import { ComparisonBox } from "./ComparisonBox"; import { FieldView, FieldViewProps } from './FieldView'; import "./LinkBox.scss"; @@ -20,22 +20,15 @@ export class LinkBox extends ViewBoxBaseComponent( if (this.dataDoc.treeViewOpen === undefined) setTimeout(() => this.dataDoc.treeViewOpen = true); return
- - + moveDocument={returnFalse} />
; } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx index b62a4dd56..a9d33f161 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.tsx +++ b/src/client/views/nodes/LinkDescriptionPopup.tsx @@ -1,8 +1,9 @@ import React = require("react"); +import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import "./LinkDescriptionPopup.scss"; -import { observable, action } from "mobx"; +import { Doc } from "../../../fields/Doc"; import { LinkManager } from "../../util/LinkManager"; +import "./LinkDescriptionPopup.scss"; import { TaskCompletionBox } from "./TaskCompletedBox"; @@ -25,7 +26,7 @@ export class LinkDescriptionPopup extends React.Component<{}> { onDismiss = (add: boolean) => { LinkDescriptionPopup.descriptionPopup = false; if (add) { - LinkManager.currentLink && (LinkManager.currentLink.description = this.description); + LinkManager.currentLink && (Doc.GetProto(LinkManager.currentLink).description = this.description); } } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index f0a502e31..30b4dc92a 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -3,9 +3,9 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { Doc, DocListCast, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, Opt, WidthSym, StrListCast } from "../../../fields/Doc"; import { documentSchema } from '../../../fields/documentSchemas'; -import { makeInterface } from "../../../fields/Schema"; +import { makeInterface, listSpec } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from '../../../fields/util'; @@ -25,6 +25,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -249,9 +250,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - return 1; - } + contentScaling = () => 1; @computed get renderPdfView() { TraceMobx(); const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 6a20ca14a..60a83d612 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -532,7 +532,8 @@ export class WebBox extends ViewBoxAnnotatableComponent {this.urlContent}
; @@ -575,10 +576,11 @@ export class WebBox extends ViewBoxAnnotatableComponent this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); scrollXf = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._scrollTop)); anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick; - transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; + basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter("textInlineAnnotations")]; + transparentFilter = () => [Utils.IsTransparentFilter(), ...this.basicFilter()]; + opaqueFilter = () => [Utils.IsOpaqueFilter(), ...this.basicFilter()]; render() { - const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined; + const pointerEvents = this.props.layerProvider?.(this.layoutDoc) === false ? "none" : this.props.pointerEvents ? this.props.pointerEvents as any : undefined; const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1; const scale = previewScale * (this.props.scaling?.() || 1); const renderAnnotations = (docFilters?: () => string[]) => @@ -593,7 +595,7 @@ export class WebBox extends ViewBoxAnnotatableComponent; return (
+ style={{ pointerEvents: this.props.isContentActive() && this.props.pointerEvents !== "none" && !MarqueeOptionsMenu.Instance.isShown() ? "all" : SnappingManager.GetIsDragging() ? undefined : "none" }} >
{ let focusSpeed: Opt; if (doc !== this.props.rootDoc && mainCont) { const windowHeight = this.props.PanelHeight() / (this.props.scaling?.() || 1); - const scrollTo = Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, .1 * windowHeight); + const scrollTo = doc.unrendered ? NumCast(doc.y) : Utils.scrollIntoView(NumCast(doc.y), doc[HeightSym](), NumCast(this.props.layoutDoc._scrollTop), windowHeight, .1 * windowHeight); if (scrollTo !== undefined) { focusSpeed = 500; @@ -502,8 +502,9 @@ export class PDFViewer extends React.Component { overlayTransform = () => this.scrollXf().scale(1 / this._zoomed); panelWidth = () => this.props.PanelWidth() / (this.props.scaling?.() || 1); // (this.Document.scrollHeight || Doc.NativeHeight(this.Document) || 0); panelHeight = () => this.props.PanelHeight() / (this.props.scaling?.() || 1); // () => this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width : Doc.NativeWidth(this.Document); - transparentFilter = () => [...this.props.docFilters(), Utils.IsTransparentFilter()]; - opaqueFilter = () => [...this.props.docFilters(), Utils.IsOpaqueFilter()]; + basicFilter = () => [...this.props.docFilters(), Utils.PropUnsetFilter("textInlineAnnotations")]; + transparentFilter = () => [Utils.IsTransparentFilter(), ...this.basicFilter()]; + opaqueFilter = () => [Utils.IsOpaqueFilter(), ...this.basicFilter()]; @computed get overlayLayer() { const renderAnnotations = (docFilters?: () => string[]) => { select={emptyFunction} ContentScaling={this.contentZoom} bringToFront={emptyFunction} - docFilters={docFilters || this.props.docFilters} + docFilters={docFilters || this.basicFilter} dontRenderDocuments={docFilters ? false : true} CollectionView={undefined} ScreenToLocalTransform={this.overlayTransform} @@ -543,7 +544,7 @@ export class PDFViewer extends React.Component {
; } @computed get pdfViewerDiv() { - return
; + return
; } @computed get contentScaling() { return this.props.ContentScaling?.() || 1; } @computed get standinViews() { @@ -556,7 +557,7 @@ export class PDFViewer extends React.Component { render() { TraceMobx(); return
-
, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists", toggle?: boolean, fieldSuffix?: string, append: boolean = true) { + export function setDocFilter(container: Opt, key: string, value: any, modifiers: "remove" | "match" | "check" | "x" | "exists" | "unset", toggle?: boolean, fieldSuffix?: string, append: boolean = true) { if (!container) return; const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters"; const docFilters = Cast(container[filterField], listSpec("string"), []); -- cgit v1.2.3-70-g09d2 From 0079b81fdd56e8aac4ded4c82ecb013fe06057a2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 22 Sep 2021 12:47:27 -0400 Subject: fixed default color of link lines in dark mode. --- .../collections/collectionFreeForm/CollectionFreeFormLinkView.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 2cb487588..f6c2707da 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -3,9 +3,11 @@ import { observer } from "mobx-react"; import { Doc, Field } from "../../../../fields/Doc"; import { Id } from "../../../../fields/FieldSymbols"; import { List } from "../../../../fields/List"; -import { NumCast, StrCast } from "../../../../fields/Types"; +import { NumCast } from "../../../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import { LinkManager } from "../../../util/LinkManager"; +import { ColorScheme } from "../../../util/SettingsManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { DocumentView } from "../../nodes/DocumentView"; import "./CollectionFreeFormLinkView.scss"; @@ -184,7 +186,7 @@ export class CollectionFreeFormLinkView extends React.Component; const linkColorList = Doc.UserDoc().linkColorList as List; //access stroke color using index of the relationship in the color list (default black) - const strokeColor = linkRelationshipList.indexOf(linkRelationship) === -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; + const strokeColor = linkRelationshipList.indexOf(linkRelationship) === -1 ? (CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "white" : "black") : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> -- cgit v1.2.3-70-g09d2 From 4e6a1d7a37c8c28014a9f7cd0d92f17c8f29454d Mon Sep 17 00:00:00 2001 From: geireann Date: Thu, 23 Sep 2021 19:30:52 +0000 Subject: Revert "Merge pull request #34 from brown-dash/linking-anh" This reverts commit 70d80e30de9963c353636d9780ffb83f3285aac7, reversing changes made to d5f9533d153e11e24d2ab7c03b4561170f0768fe. --- src/client/documents/Documents.ts | 1 - src/client/util/LinkManager.ts | 2 -- .../CollectionFreeFormLinkView.tsx | 15 +++------------ src/client/views/linking/LinkEditor.tsx | 20 ++------------------ src/client/views/linking/LinkMenuItem.tsx | 4 ++-- src/fields/Doc.ts | 1 - 6 files changed, 7 insertions(+), 36 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6fca0b67e..8ac647b99 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -301,7 +301,6 @@ export class DocumentOptions { border?: string; //for searchbox hoverBackgroundColor?: string; // background color of a label when hovered linkRelationshipList?: List; // for storing different link relationships (when set by user in the link editor) - linkRelationshipSizes?: List; //stores number of links contained in each relationship linkColorList?: List; // colors of links corresponding to specific link relationships } export namespace Docs { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 4c24fbafb..64da68f59 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -103,10 +103,8 @@ export class LinkManager { if (!Doc.UserDoc().linkRelationshipList && !Doc.UserDoc().linkColorList) { const linkRelationshipList = new List(); const linkColorList = new List(); - const linkRelationshipSizes = new List(); Doc.UserDoc().linkRelationshipList = linkRelationshipList; Doc.UserDoc().linkColorList = linkColorList; - Doc.UserDoc().linkRelationshipSizes = linkRelationshipSizes; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 88cd0feb3..f6c2707da 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -42,7 +42,7 @@ export class CollectionFreeFormLinkView extends React.Component this._opacity = 0.75), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() + setTimeout(action(() => this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. const acont = A.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); const bcont = B.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); @@ -180,24 +180,15 @@ export class CollectionFreeFormLinkView extends React.Component; const linkColorList = Doc.UserDoc().linkColorList as List; - const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List; - const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); - //access stroke color using index of the relationship in the color list (default black) - const strokeColor = currRelationshipIndex == -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; - - //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) - //thickness varies linearly from 3px to 12px for increasing link count - const strokeWidth: string = currRelationshipIndex == -1 ? "3px" : Math.floor(2 + 10 * (linkRelationshipSizes[currRelationshipIndex] / Math.max(...linkRelationshipSizes))) + "px"; - + const strokeColor = linkRelationshipList.indexOf(linkRelationship) === -1 ? (CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "white" : "black") : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> - {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 58c57a23b..219f7d3a2 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, NumListCast, StrListCast, Field } from "../../../fields/Doc"; +import { Doc, StrListCast, Field } from "../../../fields/Doc"; import { DateCast, StrCast, Cast } from "../../../fields/Types"; import { LinkManager } from "../../util/LinkManager"; import { undoBatch } from "../../util/UndoManager"; @@ -42,28 +42,14 @@ export class LinkEditor extends React.Component { @undoBatch setRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { - const prevRelationship = LinkManager.currentLink.linkRelationship as string; - LinkManager.currentLink.linkRelationship = value; Doc.GetProto(LinkManager.currentLink).linkRelationship = value; const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); - const linkRelationshipSizes = NumListCast(Doc.UserDoc().linkRelationshipSizes); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); - // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color if (linkRelationshipList && !linkRelationshipList.includes(value)) { linkRelationshipList.push(value); - linkRelationshipSizes.push(1); const randColor = "rgb(" + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + ")"; - linkColorList.push(randColor) - // if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes - } else if (linkRelationshipList && value != prevRelationship) { - //increment size of new relationship size - linkRelationshipSizes[linkRelationshipList.indexOf(value)] = linkRelationshipSizes[linkRelationshipList.indexOf(value)] + 1; - //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation) - if (linkRelationshipList.includes(prevRelationship)) { - linkRelationshipSizes[linkRelationshipList.indexOf(prevRelationship)] = linkRelationshipSizes[linkRelationshipList.indexOf(prevRelationship)] - 1; - } - + linkColorList.push(randColor); } this.relationshipButtonColor = "rgb(62, 133, 55)"; setTimeout(action(() => this.relationshipButtonColor = ""), 750); @@ -155,7 +141,6 @@ export class LinkEditor extends React.Component { style={{ width: "100%" }} id="input" value={this.relationship} - autoComplete={"off"} placeholder={"Enter link relationship"} onKeyDown={this.onRelationshipKey} onChange={this.handleRelationshipChange} @@ -184,7 +169,6 @@ export class LinkEditor extends React.Component {
{
{this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}
}>
e.stopPropagation()}> -
+
{!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}
}>
e.stopPropagation()}> -
+
{!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}
}> diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5133da603..57bd0f46f 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -80,7 +80,6 @@ export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) { export async function DocCastAsync(field: FieldResult): Promise> { return Cast(field, Doc); } -export function NumListCast(field: FieldResult) { return Cast(field, listSpec("number"), []); } export function StrListCast(field: FieldResult) { return Cast(field, listSpec("string"), []); } export function DocListCast(field: FieldResult) { return Cast(field, listSpec(Doc), []).filter(d => d instanceof Doc) as Doc[]; } export function DocListCastOrNull(field: FieldResult) { return Cast(field, listSpec(Doc), null)?.filter(d => d instanceof Doc) as Doc[] | undefined; } -- cgit v1.2.3-70-g09d2 From 43496b4cd19a06d2682f2416a4273e25cdcb55a0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 7 Oct 2021 08:47:22 -0400 Subject: Revert "Revert "Merge pull request #34 from brown-dash/linking-anh"" This reverts commit 4e6a1d7a37c8c28014a9f7cd0d92f17c8f29454d. --- src/client/documents/Documents.ts | 1 + src/client/util/LinkManager.ts | 2 ++ .../CollectionFreeFormLinkView.tsx | 15 ++++++++++++--- src/client/views/linking/LinkEditor.tsx | 20 ++++++++++++++++++-- src/client/views/linking/LinkMenuItem.tsx | 4 ++-- src/fields/Doc.ts | 1 + 6 files changed, 36 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e3623c069..6d64b3286 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -302,6 +302,7 @@ export class DocumentOptions { border?: string; //for searchbox hoverBackgroundColor?: string; // background color of a label when hovered linkRelationshipList?: List; // for storing different link relationships (when set by user in the link editor) + linkRelationshipSizes?: List; //stores number of links contained in each relationship linkColorList?: List; // colors of links corresponding to specific link relationships } export namespace Docs { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 53bd13fb3..3f7f16113 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -107,8 +107,10 @@ export class LinkManager { if (!Doc.UserDoc().linkRelationshipList && !Doc.UserDoc().linkColorList) { const linkRelationshipList = new List(); const linkColorList = new List(); + const linkRelationshipSizes = new List(); Doc.UserDoc().linkRelationshipList = linkRelationshipList; Doc.UserDoc().linkColorList = linkColorList; + Doc.UserDoc().linkRelationshipSizes = linkRelationshipSizes; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index f6c2707da..88cd0feb3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -42,7 +42,7 @@ export class CollectionFreeFormLinkView extends React.Component this._opacity = 1), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() + setTimeout(action(() => this._opacity = 0.75), 0); // since the render code depends on querying the Dom through getBoudndingClientRect, we need to delay triggering render() setTimeout(action(() => (!LinkDocs.length || !linkDoc.linkDisplay) && (this._opacity = 0.05)), 750); // this will unhighlight the link line. const acont = A.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); const bcont = B.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); @@ -180,15 +180,24 @@ export class CollectionFreeFormLinkView extends React.Component; const linkColorList = Doc.UserDoc().linkColorList as List; + const linkRelationshipSizes = Doc.UserDoc().linkRelationshipSizes as List; + const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); + //access stroke color using index of the relationship in the color list (default black) - const strokeColor = linkRelationshipList.indexOf(linkRelationship) === -1 ? (CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "white" : "black") : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; + const strokeColor = currRelationshipIndex == -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; + + //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) + //thickness varies linearly from 3px to 12px for increasing link count + const strokeWidth: string = currRelationshipIndex == -1 ? "3px" : Math.floor(2 + 10 * (linkRelationshipSizes[currRelationshipIndex] / Math.max(...linkRelationshipSizes))) + "px"; + return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> - {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 219f7d3a2..58c57a23b 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc, StrListCast, Field } from "../../../fields/Doc"; +import { Doc, NumListCast, StrListCast, Field } from "../../../fields/Doc"; import { DateCast, StrCast, Cast } from "../../../fields/Types"; import { LinkManager } from "../../util/LinkManager"; import { undoBatch } from "../../util/UndoManager"; @@ -42,14 +42,28 @@ export class LinkEditor extends React.Component { @undoBatch setRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { + const prevRelationship = LinkManager.currentLink.linkRelationship as string; + LinkManager.currentLink.linkRelationship = value; Doc.GetProto(LinkManager.currentLink).linkRelationship = value; const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList); + const linkRelationshipSizes = NumListCast(Doc.UserDoc().linkRelationshipSizes); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); + // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color if (linkRelationshipList && !linkRelationshipList.includes(value)) { linkRelationshipList.push(value); + linkRelationshipSizes.push(1); const randColor = "rgb(" + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + ")"; - linkColorList.push(randColor); + linkColorList.push(randColor) + // if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes + } else if (linkRelationshipList && value != prevRelationship) { + //increment size of new relationship size + linkRelationshipSizes[linkRelationshipList.indexOf(value)] = linkRelationshipSizes[linkRelationshipList.indexOf(value)] + 1; + //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation) + if (linkRelationshipList.includes(prevRelationship)) { + linkRelationshipSizes[linkRelationshipList.indexOf(prevRelationship)] = linkRelationshipSizes[linkRelationshipList.indexOf(prevRelationship)] - 1; + } + } this.relationshipButtonColor = "rgb(62, 133, 55)"; setTimeout(action(() => this.relationshipButtonColor = ""), 750); @@ -141,6 +155,7 @@ export class LinkEditor extends React.Component { style={{ width: "100%" }} id="input" value={this.relationship} + autoComplete={"off"} placeholder={"Enter link relationship"} onKeyDown={this.onRelationshipKey} onChange={this.handleRelationshipChange} @@ -169,6 +184,7 @@ export class LinkEditor extends React.Component {
{
{this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}
}>
e.stopPropagation()}> -
+
{!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}
}>
e.stopPropagation()}> -
+
{!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}
}> diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 9490edc2c..a89bdf57a 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -79,6 +79,7 @@ export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) { export async function DocCastAsync(field: FieldResult): Promise> { return Cast(field, Doc); } +export function NumListCast(field: FieldResult) { return Cast(field, listSpec("number"), []); } export function StrListCast(field: FieldResult) { return Cast(field, listSpec("string"), []); } export function DocListCast(field: FieldResult) { return Cast(field, listSpec(Doc), []).filter(d => d instanceof Doc) as Doc[]; } export function DocListCastOrNull(field: FieldResult) { return Cast(field, listSpec(Doc), null)?.filter(d => d instanceof Doc) as Doc[] | undefined; } -- cgit v1.2.3-70-g09d2 From 8f1a6266cf0a728ab2b7df11d45a023de266fae4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 7 Oct 2021 09:43:19 -0400 Subject: link menu ui tweaking. edge case checks for linkrelationship stuff. default links to have linkAutoMove --- src/Utils.ts | 2 +- src/client/documents/Documents.ts | 2 ++ src/client/util/LinkManager.ts | 11 +++-------- .../collectionFreeForm/CollectionFreeFormLinkView.tsx | 8 +++++--- src/client/views/linking/LinkEditor.tsx | 14 +++++++++++--- src/client/views/linking/LinkMenuGroup.tsx | 1 - src/client/views/linking/LinkMenuItem.tsx | 18 +++++++++--------- 7 files changed, 31 insertions(+), 25 deletions(-) (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index 7ec4f69f3..53182cc9c 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -575,7 +575,7 @@ export function simulateMouseClick(element: Element | null | undefined, x: numbe export function DashColor(color: string) { try { - return Color(color.toLowerCase()); + return color ? Color(color.toLowerCase()) : Color("transparent"); } catch (e) { console.log("COLOR error:", e); return Color("red"); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6d64b3286..da5c8efa9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -191,6 +191,7 @@ export class DocumentOptions { opacity?: number; defaultBackgroundColor?: string; _isLinkButton?: boolean; // marks a document as a button that will follow its primary link when clicked + _linkAutoMove?: boolean; // whether link endpoint should move around the edges of a document to make shortest path to other link endpoint isFolder?: boolean; lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide) activeFrame?: number; // the active frame of a document in a frame base collection @@ -1106,6 +1107,7 @@ export namespace DocUtils { "_acl-Public": SharingPermissions.Augment, linkDisplay: true, _hidden: true, + _linkAutoMove: true, linkRelationship, _showCaption: "description", _showTitle: "linkRelationship", diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 3f7f16113..90a8f2737 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -104,14 +104,9 @@ export class LinkManager { public createLinkrelationshipLists = () => { //create new lists for link relations and their associated colors if the lists don't already exist - if (!Doc.UserDoc().linkRelationshipList && !Doc.UserDoc().linkColorList) { - const linkRelationshipList = new List(); - const linkColorList = new List(); - const linkRelationshipSizes = new List(); - Doc.UserDoc().linkRelationshipList = linkRelationshipList; - Doc.UserDoc().linkColorList = linkColorList; - Doc.UserDoc().linkRelationshipSizes = linkRelationshipSizes; - } + !Doc.UserDoc().linkRelationshipList && (Doc.UserDoc().linkRelationshipList = new List()); + !Doc.UserDoc().linkColorList && (Doc.UserDoc().linkColorList = new List()); + !Doc.UserDoc().linkRelationshipSizes && (Doc.UserDoc().linkRelationshipSizes = new List()); } public addLink(linkDoc: Doc, checkExists = false) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 88cd0feb3..bb4cae8c6 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -189,15 +189,17 @@ export class CollectionFreeFormLinkView extends React.Component; const currRelationshipIndex = linkRelationshipList.indexOf(linkRelationship); + const linkSize = currRelationshipIndex === -1 || currRelationshipIndex >= linkRelationshipSizes.length ? -1 : linkRelationshipSizes[currRelationshipIndex]; + //access stroke color using index of the relationship in the color list (default black) - const strokeColor = currRelationshipIndex == -1 ? "black" : linkColorList[linkRelationshipList.indexOf(linkRelationship)]; + const stroke = currRelationshipIndex === -1 || currRelationshipIndex >= linkColorList.length ? "black" : linkColorList[currRelationshipIndex]; //calculate stroke width/thickness based on the relative importance of the relationshipship (i.e. how many links the relationship has) //thickness varies linearly from 3px to 12px for increasing link count - const strokeWidth: string = currRelationshipIndex == -1 ? "3px" : Math.floor(2 + 10 * (linkRelationshipSizes[currRelationshipIndex] / Math.max(...linkRelationshipSizes))) + "px"; + const strokeWidth = linkSize === -1 ? "3px" : Math.floor(2 + 10 * (linkSize / Math.max(...linkRelationshipSizes))) + "px"; return !a.width || !b.width || ((!this.props.LinkDocs[0].linkDisplay) && !aActive && !bActive) ? (null) : (<> - {textX === undefined ? (null) : {Field.toString(this.props.LinkDocs[0].description as any as Field)} diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 58c57a23b..5b5c3cd01 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -50,18 +50,26 @@ export class LinkEditor extends React.Component { const linkColorList = StrListCast(Doc.UserDoc().linkColorList); // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color - if (linkRelationshipList && !linkRelationshipList.includes(value)) { + if (!linkRelationshipList?.includes(value)) { linkRelationshipList.push(value); linkRelationshipSizes.push(1); const randColor = "rgb(" + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + ")"; linkColorList.push(randColor) // if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes } else if (linkRelationshipList && value != prevRelationship) { + const index = linkRelationshipList.indexOf(value); //increment size of new relationship size - linkRelationshipSizes[linkRelationshipList.indexOf(value)] = linkRelationshipSizes[linkRelationshipList.indexOf(value)] + 1; + if (index !== -1 && index < linkRelationshipSizes.length) { + const pvalue = linkRelationshipSizes[index]; + linkRelationshipSizes[index] = (pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1); + } //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation) if (linkRelationshipList.includes(prevRelationship)) { - linkRelationshipSizes[linkRelationshipList.indexOf(prevRelationship)] = linkRelationshipSizes[linkRelationshipList.indexOf(prevRelationship)] - 1; + const pindex = linkRelationshipList.indexOf(prevRelationship); + if (pindex !== -1 && pindex < linkRelationshipSizes.length) { + const pvalue = linkRelationshipSizes[pindex]; + linkRelationshipSizes[pindex] = Math.max(0, (pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue - 1)); + } } } diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index cb6571f92..03377ad4e 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -31,7 +31,6 @@ export class LinkMenuGroup extends React.Component { if (RGBcolor) { //set opacity to 0.25 by modifiying the rgb string color = RGBcolor.slice(0, RGBcolor.length - 1) + ", 0.25)"; - console.log(color); } } return color; diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index e0b20ef6f..f19064e49 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -165,19 +165,19 @@ export class LinkMenuItem extends React.Component {
-
{this.props.linkDoc.hidden ? "Show Anchor" : "Hide Anchor"}
}> -
e.stopPropagation()}> -
+
{this.props.linkDoc.hidden ? "Show Link Anchor" : "Hide Link Anchor"}
}> +
e.stopPropagation()}> +
-
{!this.props.linkDoc.linkDisplay ? "Show link" : "Hide link"}
}> -
e.stopPropagation()}> -
+
{this.props.linkDoc.linkDisplay ? "Hide Link Line" : "Show Link Line"}
}> +
e.stopPropagation()}> +
-
{!this.props.linkDoc.linkAutoMove ? "Auto move dot" : "Freeze dot position"}
}> -
e.stopPropagation()}> -
+
{this.props.linkDoc.linkAutoMove ? "Click to freeze link anchor position" : "Click to auto move link anchor"}
}> +
e.stopPropagation()}> +
Edit Link
}> -- cgit v1.2.3-70-g09d2