diff options
author | bobzel <zzzman@gmail.com> | 2022-03-29 10:58:31 -0400 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2022-03-29 10:58:31 -0400 |
commit | cc4a500d6d3c941d139e6c07dbf76c4eed9c3280 (patch) | |
tree | 77efb486ed49f03f0e71cf7dcf3395c121ee192e /src | |
parent | 2c3264bca271af170b620cfc44ecdfafb77aacc0 (diff) |
added a backlinks property category. fixed context property category to update without using search. fixed double tap on links button to always show linkpivot doc. fixed dragging docs to a tab to not switch to tab dragging mode.
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/PropertiesDocBacklinksSelector.tsx | 46 | ||||
-rw-r--r-- | src/client/views/PropertiesDocContextSelector.tsx | 34 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 26 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.scss | 4 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 22 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 17 |
6 files changed, 104 insertions, 45 deletions
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx new file mode 100644 index 000000000..5ffa93961 --- /dev/null +++ b/src/client/views/PropertiesDocBacklinksSelector.tsx @@ -0,0 +1,46 @@ +import { computed } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { Doc, DocListCast } from "../../fields/Doc"; +import { Id } from "../../fields/FieldSymbols"; +import { Cast, NumCast, StrCast } from "../../fields/Types"; +import { LinkManager } from "../util/LinkManager"; +import { CollectionDockingView } from "./collections/CollectionDockingView"; +import { CollectionViewType } from "./collections/CollectionView"; +import './PropertiesDocContextSelector.scss'; + +type PropertiesDocBacklinksSelectorProps = { + Document: Doc, + Stack?: any, + hideTitle?: boolean, + addDocTab(doc: Doc, location: string): void +}; + +@observer +export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDocBacklinksSelectorProps> { + @computed get _docs() { + const linkSource = this.props.Document; + const links = DocListCast(linkSource.links); + const collectedLinks = [] as Doc[]; + links.map(link => { + const other = LinkManager.getOppositeAnchor(link, linkSource); + const otherdoc = !other ? undefined : other.annotationOn ? Cast(other.annotationOn, Doc, null) : other; + if (otherdoc && !collectedLinks.some(d => Doc.AreProtosEqual(d, otherdoc))) { + collectedLinks.push(otherdoc); + } + }); + return collectedLinks; + } + + getOnClick = (col: Doc) => { + col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col; + this.props.addDocTab(col, "add:right"); + } + + render() { + return <div> + {this.props.hideTitle ? (null) : <p key="contexts">Contexts:</p>} + {this._docs.map(doc => <p key={doc[Id]}><a onClick={() => this.getOnClick(doc)}>{StrCast(doc.title)}</a></p>)} + </div>; + } +}
\ No newline at end of file diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index 427748fe7..45a8b6bf6 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -1,13 +1,12 @@ -import { IReactionDisposer, observable, reaction, runInAction } from "mobx"; +import { computed } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; -import { Doc } from "../../fields/Doc"; +import { Doc, DocListCast } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; -import { NumCast, StrCast } from "../../fields/Types"; -import { CollectionViewType } from "./collections/CollectionView"; +import { Cast, NumCast, StrCast } from "../../fields/Types"; import { CollectionDockingView } from "./collections/CollectionDockingView"; +import { CollectionViewType } from "./collections/CollectionView"; import './PropertiesDocContextSelector.scss'; -import { SearchUtil } from "../util/SearchUtil"; type PropertiesDocContextSelectorProps = { Document: Doc, @@ -18,24 +17,15 @@ type PropertiesDocContextSelectorProps = { @observer export class PropertiesDocContextSelector extends React.Component<PropertiesDocContextSelectorProps> { - @observable private _docs: { col: Doc, target: Doc }[] = []; - @observable private _otherDocs: { col: Doc, target: Doc }[] = []; - _reaction: IReactionDisposer | undefined; - - componentDidMount() { this._reaction = reaction(() => this.props.Document, () => this.fetchDocuments(), { fireImmediately: true }); } - componentWillUnmount() { this._reaction?.(); } - async fetchDocuments() { - const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - const containerProtoSets = await Promise.all(aliases.map(async alias => ((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs))); - const containerProtos = containerProtoSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>()); - const containerSets = await Promise.all(Array.from(containerProtos.keys()).map(async container => SearchUtil.GetAliasesOfDocument(container))); + @computed get _docs() { + const target = this.props.Document; + const aliases = DocListCast(target.aliases); + const containerProtos = aliases.filter(alias => alias.context).reduce((set, alias) => set.add(Cast(alias.context, Doc, null)), new Set<Doc>()); + const containerSets = Array.from(containerProtos.keys()).map(container => DocListCast(container.aliases)); const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>()); - const doclayoutSets = await Promise.all(Array.from(containers.keys()).map(async (dp) => SearchUtil.GetAliasesOfDocument(dp))); + const doclayoutSets = Array.from(containers.keys()).map(dp => DocListCast(dp.aliases)); const doclayouts = Array.from(doclayoutSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>()).keys()); - runInAction(() => { - this._docs = doclayouts.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).filter(doc => !Doc.IsSystem(doc)).map(doc => ({ col: doc, target: this.props.Document })); - this._otherDocs = []; - }); + return doclayouts.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).filter(doc => !Doc.IsSystem(doc)).map(doc => ({ col: doc, target })); } getOnClick = (col: Doc, target: Doc) => { @@ -51,8 +41,6 @@ export class PropertiesDocContextSelector extends React.Component<PropertiesDocC return <div> {this.props.hideTitle ? (null) : <p key="contexts">Contexts:</p>} {this._docs.map(doc => <p key={doc.col[Id] + doc.target[Id]}><a onClick={() => this.getOnClick(doc.col, doc.target)}>{StrCast(doc.col.title)}</a></p>)} - {this._otherDocs.length ? <hr key="hr" /> : null} - {this._otherDocs.map(doc => <p key={"p" + doc.col[Id] + doc.target[Id]}><a onClick={() => this.getOnClick(doc.col, doc.target)}>{StrCast(doc.col.title)}</a></p>)} </div>; } }
\ No newline at end of file diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 47a5cd07e..92b52ed5b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -34,6 +34,7 @@ import "./PropertiesView.scss"; import { DefaultStyleProvider } from "./StyleProvider"; import { PresBox } from "./nodes/trails"; import { IconLookup } from "@fortawesome/fontawesome-svg-core"; +import { PropertiesDocBacklinksSelector } from "./PropertiesDocBacklinksSelector"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -72,6 +73,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @observable openFields: boolean = true; @observable openLayout: boolean = false; @observable openContexts: boolean = true; + @observable openBacklinks: boolean = true; @observable openAppearance: boolean = true; @observable openTransform: boolean = true; @observable openFilters: boolean = true; // should be false @@ -280,6 +282,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { return !this.selectedDoc ? (null) : <PropertiesDocContextSelector Document={this.selectedDoc} hideTitle={true} addDocTab={(doc, where) => CollectionDockingView.AddSplit(doc, "right")} />; } + @computed get backlinks() { + return !this.selectedDoc ? (null) : <PropertiesDocBacklinksSelector Document={this.selectedDoc} hideTitle={true} addDocTab={(doc, where) => CollectionDockingView.AddSplit(doc, "right")} />; + } + @computed get layoutPreview() { if (SelectionManager.Views().length > 1) { return "-- multiple selected --"; @@ -1080,6 +1086,20 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div>; } + @computed get backlinksSubMenu() { + return <div className="propertiesView-contexts"> + <div className="propertiesView-contexts-title" + onPointerDown={action(() => this.openBacklinks = !this.openBacklinks)} + style={{ backgroundColor: this.openBacklinks ? "black" : "" }}> + Backlinks + <div className="propertiesView-contexts-title-icon"> + <FontAwesomeIcon icon={this.openBacklinks ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openBacklinks ? <div className="propertiesView-contexts-content" >{this.backlinks}</div> : null} + </div>; + } + @computed get layoutSubMenu() { return <div className="propertiesView-layout"> <div className="propertiesView-layout-title" @@ -1331,6 +1351,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {this.editableTitle} </div> + {this.contextsSubMenu} + + {this.backlinksSubMenu} + {this.inkSubMenu} {this.optionsSubMenu} @@ -1341,8 +1365,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { {isNovice ? null : this.fieldsSubMenu} - {isNovice ? null : this.contextsSubMenu} - {isNovice ? null : this.layoutSubMenu} </div>; } diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index b2ee33807..21045a20e 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -39,8 +39,8 @@ padding: 0px; opacity: 0.7; box-shadow: none; - height: 24px; - // border-bottom: 1px black; + height: 25px; + border-bottom: black solid; .collectionDockingView-gear { display: none; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 804e82856..6d96a9ab6 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from "@material-ui/core"; -import { action, computed, observable, runInAction } from "mobx"; +import { action, computed, observable, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, Opt } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; @@ -72,22 +72,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp onLinkMenuOpen = (e: React.PointerEvent): void => { setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => { if (doubleTap) { - const linkSource = this.props.View.rootDoc; - const docid = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + "-pivotish"; - DocServer.GetRefField(docid).then(docx => { - const rootAlias = () => { - const rootAlias = Doc.MakeAlias(linkSource); - rootAlias.x = rootAlias.y = 0; - return rootAlias; - }; - const linkCollection = ((docx instanceof Doc) && docx) || Docs.Create.StackingDocument([/*rootAlias()*/], { title: this.props.View.Document.title + "-pivot", _width: 500, _height: 500, }, docid); - linkCollection.linkSource = linkSource; - if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript("updateLinkCollection(self)"); - LightboxView.SetLightboxDoc(linkCollection); - }); + DocumentView.showBackLinks(this.props.View.rootDoc); } - else DocumentLinksButton.LinkEditorDocView = this.props.View; - })); + }), undefined, undefined, + action(() => DocumentLinksButton.LinkEditorDocView = this.props.View)); } @undoBatch @@ -119,8 +107,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp DocumentLinksButton.StartLinkView = this.props.View; } //action(() => Doc.BrushDoc(this.props.View.Document)); - } else if (!this.props.InMenu) { - DocumentLinksButton.LinkEditorDocView = this.props.View; } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 955698190..c2d2ef13b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -49,6 +49,7 @@ import { RadialMenu } from './RadialMenu'; import { ScriptingBox } from "./ScriptingBox"; import { PresBox } from './trails/PresBox'; import React = require("react"); +import { DocServer } from "../../DocServer"; const { Howl } = require('howler'); interface Window { @@ -225,6 +226,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); } @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); } + componentWillUnmount() { this.cleanupHandlers(true); } componentDidMount() { this.setupHandlers(); } //componentDidUpdate() { this.setupHandlers(); } @@ -1144,6 +1146,21 @@ export class DocumentView extends React.Component<DocumentViewProps> { public ContentRef = React.createRef<HTMLDivElement>(); private _disposers: { [name: string]: IReactionDisposer } = {}; + public static showBackLinks(linkSource: Doc) { + const docid = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + "-pivotish"; + DocServer.GetRefField(docid).then(docx => { + const rootAlias = () => { + const rootAlias = Doc.MakeAlias(linkSource); + rootAlias.x = rootAlias.y = 0; + return rootAlias; + }; + const linkCollection = ((docx instanceof Doc) && docx) || Docs.Create.StackingDocument([/*rootAlias()*/], { title: linkSource.title + "-pivot", _width: 500, _height: 500, }, docid); + linkCollection.linkSource = linkSource; + if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript("updateLinkCollection(self)"); + LightboxView.SetLightboxDoc(linkCollection); + }); + } + @observable public docView: DocumentViewInternal | undefined | null; get Document() { return this.props.Document; } |