aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-03-29 10:58:31 -0400
committerbobzel <zzzman@gmail.com>2022-03-29 10:58:31 -0400
commitcc4a500d6d3c941d139e6c07dbf76c4eed9c3280 (patch)
tree77efb486ed49f03f0e71cf7dcf3395c121ee192e /src
parent2c3264bca271af170b620cfc44ecdfafb77aacc0 (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.tsx46
-rw-r--r--src/client/views/PropertiesDocContextSelector.tsx34
-rw-r--r--src/client/views/PropertiesView.tsx26
-rw-r--r--src/client/views/collections/CollectionDockingView.scss4
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx22
-rw-r--r--src/client/views/nodes/DocumentView.tsx17
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; }