From 972f76a34e3c1a1aa5f0be59639fbd5763c9c16f Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Thu, 6 Jun 2019 17:45:26 -0400 Subject: links get saved to global table --- src/client/util/DocumentManager.ts | 54 +++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 65c4b9e4b..712529745 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -9,6 +9,7 @@ import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; import { Id } from '../../new_fields/FieldSymbols'; +import { LinkManager } from '../views/nodes/LinkManager'; export class DocumentManager { @@ -83,12 +84,16 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { - return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { - let linksList = DocListCast(dv.props.Document.linkedToDocs); + let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { + + + let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { - let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); + let destination = (link["linkedTo"] === dv.props.Document) ? link["linkedFrom"] : link["linkedTo"]; + let linkToDoc = FieldValue(Cast(destination, Doc)); + // let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); if (linkToDoc) { DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => pairs.push({ a: dv, b: docView1, l: link })); @@ -97,21 +102,38 @@ export class DocumentManager { return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); } - linksList = DocListCast(dv.props.Document.linkedFromDocs); - if (linksList && linksList.length) { - pairs.push(...linksList.reduce((pairs, link) => { - if (link) { - let linkFromDoc = FieldValue(Cast(link.linkedFrom, Doc)); - if (linkFromDoc) { - DocumentManager.Instance.getDocumentViews(linkFromDoc).map(docView1 => - pairs.push({ a: dv, b: docView1, l: link })); - } - } - return pairs; - }, pairs)); - } + + // let linksList = DocListCast(dv.props.Document.linkedToDocs); + // console.log("to links", linksList.length); + // if (linksList && linksList.length) { + // pairs.push(...linksList.reduce((pairs, link) => { + // if (link) { + // let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); + // if (linkToDoc) { + // DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => + // pairs.push({ a: dv, b: docView1, l: link })); + // } + // } + // return pairs; + // }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); + // } + // linksList = DocListCast(dv.props.Document.linkedFromDocs); + // console.log("from links", linksList.length); + // if (linksList && linksList.length) { + // pairs.push(...linksList.reduce((pairs, link) => { + // if (link) { + // let linkFromDoc = FieldValue(Cast(link.linkedFrom, Doc)); + // if (linkFromDoc) { + // DocumentManager.Instance.getDocumentViews(linkFromDoc).map(docView1 => + // pairs.push({ a: dv, b: docView1, l: link })); + // } + // } + // return pairs; + // }, pairs)); + // } return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); + return linked; } @undoBatch -- cgit v1.2.3-70-g09d2 From 70996f3f19d408e819e081ed03bd7ccf0de44503 Mon Sep 17 00:00:00 2001 From: Vellichora Date: Fri, 7 Jun 2019 17:52:31 -0400 Subject: links can be categorized under a group --- src/client/documents/Documents.ts | 40 +++++++++--- src/client/util/DocumentManager.ts | 5 +- src/client/util/DragManager.ts | 2 +- src/client/util/LinkManager.ts | 84 +++++++++++++++++++++++++ src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/LinkEditor.tsx | 103 +++++++++++++++++++++++++------ src/client/views/nodes/LinkManager.tsx | 51 --------------- src/client/views/nodes/LinkMenu.tsx | 33 ++++++---- 9 files changed, 227 insertions(+), 95 deletions(-) create mode 100644 src/client/util/LinkManager.ts delete mode 100644 src/client/views/nodes/LinkManager.tsx (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 87b831663..5ec19f987 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -35,7 +35,7 @@ import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; -import { LinkManager } from "../views/nodes/LinkManager"; +import { LinkManager } from "../util/LinkManager"; var requestImageSize = require('request-image-size'); var path = require('path'); @@ -69,21 +69,45 @@ export interface DocumentOptions { } const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; +// export interface LinkData { +// anchor1: Doc; +// anchor1Page: number; +// anchor1Tags: Array<{ tag: string, name: string, description: string }>; +// anchor2: Doc; +// anchor2Page: number; +// anchor2Tags: Array<{ tag: string, name: string, description: string }>; +// } + +// export interface TagData { +// tag: string; +// name: string; +// description: string; +// } + export namespace DocUtils { export function MakeLink(source: Doc, target: Doc) { // let protoSrc = source.proto ? source.proto : source; // let protoTarg = target.proto ? target.proto : target; UndoManager.RunInBatch(() => { + let groupDoc = Docs.TextDocument(); + groupDoc.proto!.type = "*"; + let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; - linkDoc.proto!.title = source.proto!.title + " and " + target.proto!.title; - linkDoc.proto!.linkDescription = ""; - linkDoc.proto!.linkTags = "Default"; + // linkDoc.proto!.title = source.proto!.title + " and " + target.proto!.title; + // linkDoc.proto!.linkDescription = ""; + linkDoc.proto!.anchor1 = source; + linkDoc.proto!.anchor1Page = source.curPage; + linkDoc.proto!.anchor1Groups = new List([groupDoc]); + + linkDoc.proto!.anchor2 = target; + linkDoc.proto!.anchor2Page = target.curPage; + linkDoc.proto!.anchor2Groups = new List([groupDoc]); - linkDoc.proto!.linkedTo = target; - linkDoc.proto!.linkedToPage = target.curPage; - linkDoc.proto!.linkedFrom = source; - linkDoc.proto!.linkedFromPage = source.curPage; + // linkDoc.proto!.linkedTo = target; + // linkDoc.proto!.linkedToPage = target.curPage; + // linkDoc.proto!.linkedFrom = source; + // linkDoc.proto!.linkedFromPage = source.curPage; // let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); // if (!linkedFrom) { diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 712529745..52f0fe3f6 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -9,7 +9,7 @@ import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; import { Id } from '../../new_fields/FieldSymbols'; -import { LinkManager } from '../views/nodes/LinkManager'; +import { LinkManager } from './LinkManager'; export class DocumentManager { @@ -91,7 +91,8 @@ export class DocumentManager { if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { - let destination = (link["linkedTo"] === dv.props.Document) ? link["linkedFrom"] : link["linkedTo"]; + // let destination = (link["linkedTo"] === dv.props.Document) ? link["linkedFrom"] : link["linkedTo"]; + let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); let linkToDoc = FieldValue(Cast(destination, Doc)); // let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); if (linkToDoc) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7854cc080..809368aff 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -4,7 +4,7 @@ import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; -import { LinkManager } from "../views/nodes/LinkManager"; +import { LinkManager } from "./LinkManager"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts new file mode 100644 index 000000000..a6d649395 --- /dev/null +++ b/src/client/util/LinkManager.ts @@ -0,0 +1,84 @@ +import { observable, computed, action } from "mobx"; +import React = require("react"); +import { SelectionManager } from "./SelectionManager"; +import { observer } from "mobx-react"; +import { props } from "bluebird"; +import { DocumentView } from "../views/nodes/DocumentView"; +import { link } from "fs"; +import { StrCast, Cast } from "../../new_fields/Types"; +import { Doc } from "../../new_fields/Doc"; +import { listSpec } from "../../new_fields/Schema"; +import { List } from "../../new_fields/List"; + + +export class LinkManager { + private static _instance: LinkManager; + public static get Instance(): LinkManager { + return this._instance || (this._instance = new this()); + } + private constructor() { + } + + @observable + public allLinks: Array = []; + + public findAllRelatedLinks(source: Doc): Array { + let related = LinkManager.Instance.allLinks.filter( + link => Doc.AreProtosEqual(source, Cast(link.anchor1, Doc, new Doc)) || Doc.AreProtosEqual(source, Cast(link.anchor2, Doc, new Doc))); + return related; + } + + public findRelatedGroupedLinks(source: Doc): Map> { + let related = this.findAllRelatedLinks(source); + + let categories = new Map(); + related.forEach(link => { + // get groups of given doc + let groups = (Doc.AreProtosEqual(source, Cast(link.anchor1, Doc, new Doc))) ? Cast(link.anchor1Groups, listSpec(Doc), []) : Cast(link.anchor2Groups, listSpec(Doc), []); + if (groups) { + if (groups.length > 0) { + groups.forEach(groupDoc => { + if (groupDoc instanceof Doc) { + let groupType = StrCast(groupDoc.proto!.type); + let group = categories.get(groupType); // TODO: clean this up lol + if (group) group.push(link); + else group = [link]; + categories.set(groupType, group); + } else { + // promise doc + } + + }) + } + else { + // if link is in no groups then put it in default group + let group = categories.get("*"); + if (group) group.push(link); + else group = [link]; + categories.set("*", group); + } + } + + + // let anchor = this.findOppositeAnchor(link, source); + // let group = categories.get(link.linkTags); + // if (group) group.push(link); + // else group = [link]; + // categories.set(link.linkTags, group); + }) + return categories; + } + + public findOppositeAnchor(link: Doc, source: Doc): Doc { + if (Doc.AreProtosEqual(source, Cast(link.anchor1, Doc, new Doc))) { + return Cast(link.anchor2, Doc, new Doc); + } else { + return Cast(link.anchor1, Doc, new Doc); + } + } + + // public findAnchorTags(link: Doc, source: Doc): Doc[] { + // if (source) + // } + +} \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2aae9bce6..eb45c770e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -28,7 +28,7 @@ import { CollectionView } from "./collections/CollectionView"; import { DocumentManager } from "../util/DocumentManager"; import { FormattedTextBox } from "./nodes/FormattedTextBox"; import { FieldView } from "./nodes/FieldView"; -import { LinkManager } from "./nodes/LinkManager"; +import { LinkManager } from "../util/LinkManager"; library.add(faLink); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0baa061ab..fc6974e6c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -52,7 +52,7 @@ library.add(faDesktop); const linkSchema = createSchema({ title: "string", linkDescription: "string", - linkTags: listSpec("string"), + linkTags: "string", linkedTo: Doc, linkedFrom: Doc }); diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 71a423338..2ab8c3460 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -6,52 +6,115 @@ import './LinkEditor.scss'; import { props } from "bluebird"; import { DocumentView } from "./DocumentView"; import { link } from "fs"; -import { StrCast } from "../../../new_fields/Types"; +import { StrCast, Cast } from "../../../new_fields/Types"; import { Doc } from "../../../new_fields/Doc"; +import { List } from "../../../new_fields/List"; +import { listSpec } from "../../../new_fields/Schema"; +import { LinkManager } from "../../util/LinkManager"; interface Props { + sourceDoc: Doc; linkDoc: Doc; + groups: Map; showLinks: () => void; } @observer export class LinkEditor extends React.Component { - @observable private _nameInput: string = StrCast(this.props.linkDoc.title); - @observable private _descriptionInput: string = StrCast(this.props.linkDoc.linkDescription); + // @observable private _title: string = StrCast(this.props.linkDoc.title); + // @observable private _description: string = StrCast(this.props.linkDoc.linkDescription); + // @observable private _tags: Array = Cast(this.props.linkDoc.linkTags, List); + // @action + // onTitleChanged = (e: React.ChangeEvent) => { + // this._title = e.target.value; + // } - onSaveButtonPressed = (e: React.PointerEvent): void => { - e.stopPropagation(); + // @action + // onDescriptionChanged = (e: React.ChangeEvent) => { + // this._description = e.target.value; + // } + + // renderTags() { + // return this._tags.map(tag => { + // if (tag === "") { + // return ; + // } else { + // return ; + // } + // }) + // } + + // addTag = (): void => { + // this._tags.push(""); + // } + @action + editGroup(groupId: number, value: string) { let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; - linkDoc.title = this._nameInput; - linkDoc.linkDescription = this._descriptionInput; + let groupDoc = this.props.groups.get(groupId); + if (groupDoc) { + groupDoc.proto!.type = value; + if (Doc.AreProtosEqual(this.props.sourceDoc, Cast(linkDoc.anchor1, Doc, new Doc))) { + // let groups = Cast(linkDoc.anchor1Groups, listSpec(Doc), []); + // groups.push(groupDoc); + linkDoc.anchor1Groups = new List([groupDoc]); + + } else { + linkDoc.anchor2Groups = new List([groupDoc]); + } + } - this.props.showLinks(); } + renderGroup(groupId: number, groupDoc: Doc) { + return ( +
+

type:

+ this.editGroup(groupId, e.target.value)}> +
+ ) + } + renderGroups() { + let groups: Array = []; + this.props.groups.forEach((groupDoc, groupId) => { + groups.push( +
+ {this.renderGroup(groupId, groupDoc)} +
+ ) + }); + return groups; + } + + onSaveButtonPressed = (e: React.PointerEvent): void => { + e.stopPropagation(); + + // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; + // // linkDoc.title = this._title; + // // linkDoc.linkDescription = this._description; + + this.props.showLinks(); + } render() { + let destination = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); return (
- - +

linked to: {destination.proto!.title}

+ Groups: + {this.renderGroups()} + + {/* + */} + {/* {this.renderTags()} + */}
SAVE
); } - - @action - onNameChanged = (e: React.ChangeEvent) => { - this._nameInput = e.target.value; - } - - @action - onDescriptionChanged = (e: React.ChangeEvent) => { - this._descriptionInput = e.target.value; - } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkManager.tsx b/src/client/views/nodes/LinkManager.tsx deleted file mode 100644 index 1064eaa22..000000000 --- a/src/client/views/nodes/LinkManager.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { observable, computed, action } from "mobx"; -import React = require("react"); -import { SelectionManager } from "../../util/SelectionManager"; -import { observer } from "mobx-react"; -import './LinkEditor.scss'; -import { props } from "bluebird"; -import { DocumentView } from "./DocumentView"; -import { link } from "fs"; -import { StrCast, Cast } from "../../../new_fields/Types"; -import { Doc } from "../../../new_fields/Doc"; -import { listSpec } from "../../../new_fields/Schema"; - - -export class LinkManager { - private static _instance: LinkManager; - public static get Instance(): LinkManager { - return this._instance || (this._instance = new this()); - } - private constructor() { - } - - @observable - public allLinks: Array = []; - - public findAllRelatedLinks(source: Doc): Array { - let related = LinkManager.Instance.allLinks.filter( - link => Doc.AreProtosEqual(source, Cast(link.linkedFrom, Doc, new Doc)) || Doc.AreProtosEqual(source, Cast(link.linkedTo, Doc, new Doc))); - return related; - } - - public findRelatedGroupedLinks(source: Doc): Map> { - let related = this.findAllRelatedLinks(source); - let categories = new Map(); - related.forEach(link => { - let group = categories.get(link.linkTags); - if (group) group.push(link); - else group = [link]; - categories.set(link.linkTags, group); - }) - return categories; - } - - public findOppositeAnchor(link: Doc, source: Doc): Doc { - if (Doc.AreProtosEqual(source, Cast(link.linkedFrom, Doc, new Doc))) { - return Cast(link.linkedTo, Doc, new Doc); - } else { - return Cast(link.linkedFrom, Doc, new Doc); - } - } - -} \ No newline at end of file diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 6dc5623d1..affe35e2a 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -8,7 +8,9 @@ import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; -import { LinkManager } from "./LinkManager"; +import { LinkManager } from "../../util/LinkManager"; +import { number } from "prop-types"; +import { listSpec } from "../../../new_fields/Schema"; interface Props { docView: DocumentView; @@ -29,23 +31,20 @@ export class LinkMenu extends React.Component { // }); // } - renderLinkGroup(links: Doc[]) { - console.log("render link group"); + renderLinkGroupItems(links: Doc[]) { let source = this.props.docView.Document; - console.log("num links", links.length, typeof links); return links.map(link => { - let destination = (link["linkedTo"] === source) ? link["linkedFrom"] : link["linkedTo"]; + // let destination = (link["linkedTo"] === source) ? link["linkedFrom"] : link["linkedTo"]; + let destination = LinkManager.Instance.findOppositeAnchor(link, source); let doc = FieldValue(Cast(destination, Doc)); if (doc) { console.log(doc[Id] + source[Id], "source is", source[Id]); - return this._editingLink = link)} type={""} />; + return this._editingLink = link)} type={""} />; } }); } - renderLinkItems(links: Map>) { - console.log("render link items"); - + renderLinkItems = (links: Map>): Array => { let linkItems: Array = []; links.forEach((links, group) => { @@ -54,7 +53,7 @@ export class LinkMenu extends React.Component {

{group}:

- {this.renderLinkGroup(links)} + {this.renderLinkGroupItems(links)}
) @@ -80,8 +79,20 @@ export class LinkMenu extends React.Component { ); } else { + let counter = 0; + let groups = new Map(); + let groupList = (Doc.AreProtosEqual(this.props.docView.props.Document, Cast(this._editingLink.anchor1, Doc, new Doc))) ? + Cast(this._editingLink.anchor1Groups, listSpec(Doc), []) : Cast(this._editingLink.anchor2Groups, listSpec(Doc), []); + groupList.forEach(group => { + if (group instanceof Doc) { + console.log(counter); + groups.set(counter, group); + counter++; + } + }) + return ( - this._editingLink = undefined)}> + this._editingLink = undefined)}> ); } -- cgit v1.2.3-70-g09d2 From d429898b5337331450e46c223380e5d00967b2d6 Mon Sep 17 00:00:00 2001 From: Fawn Date: Mon, 10 Jun 2019 20:02:32 -0400 Subject: added set up for metadata on links --- src/client/documents/Documents.ts | 1 + src/client/util/DocumentManager.ts | 5 +- src/client/util/DragManager.ts | 4 +- src/client/util/LinkManager.ts | 81 ++++++++---- src/client/views/nodes/LinkEditor.scss | 42 ++++++ src/client/views/nodes/LinkEditor.tsx | 229 +++++++++++++++++++++++++++------ src/client/views/nodes/LinkMenu.tsx | 34 +++-- 7 files changed, 313 insertions(+), 83 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5ec19f987..731490d97 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -91,6 +91,7 @@ export namespace DocUtils { UndoManager.RunInBatch(() => { let groupDoc = Docs.TextDocument(); groupDoc.proto!.type = "*"; + groupDoc.proto!.metadata = new List([]); let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 52f0fe3f6..2acbb3ad4 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -9,7 +9,7 @@ import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; import { Id } from '../../new_fields/FieldSymbols'; -import { LinkManager } from './LinkManager'; +import { LinkManager, LinkUtils } from './LinkManager'; export class DocumentManager { @@ -92,7 +92,8 @@ export class DocumentManager { pairs.push(...linksList.reduce((pairs, link) => { if (link) { // let destination = (link["linkedTo"] === dv.props.Document) ? link["linkedFrom"] : link["linkedTo"]; - let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); + + let destination = LinkUtils.findOppositeAnchor(link, dv.props.Document); let linkToDoc = FieldValue(Cast(destination, Doc)); // let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); if (linkToDoc) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 809368aff..9ac421fbf 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -4,7 +4,7 @@ import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; -import { LinkManager } from "./LinkManager"; +import { LinkManager, LinkUtils } from "./LinkManager"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { @@ -48,7 +48,7 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n // let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); let linkDocs = LinkManager.Instance.findAllRelatedLinks(srcTarg); if (linkDocs) draggedDocs = linkDocs.map(link => { - return LinkManager.Instance.findOppositeAnchor(link, sourceDoc); + return LinkUtils.findOppositeAnchor(link, sourceDoc); }); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index a6d649395..5e8e0475b 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -10,6 +10,43 @@ import { Doc } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; import { List } from "../../new_fields/List"; +export namespace LinkUtils { + export function findOppositeAnchor(link: Doc, anchor: Doc): Doc { + if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { + return Cast(link.anchor2, Doc, new Doc); + } else { + return Cast(link.anchor1, Doc, new Doc); + } + } + + // export function getAnchorGroups(link: Doc, anchor: Doc): Doc[] { + // let groups; + // if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { + // groups = Cast(link.anchor1Groups, listSpec(Doc), []); + // } else { + // groups = Cast(link.anchor2Groups, listSpec(Doc), []); + // } + + // if (groups instanceof Doc[]) { + // return groups; + // } else { + // return []; + // } + // // if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { + // // returnCast(link.anchor1Groups, listSpec(Doc), []); + // // } else { + // // return Cast(link.anchor2Groups, listSpec(Doc), []); + // // } + // } + + export function setAnchorGroups(link: Doc, anchor: Doc, groups: Doc[]) { + if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { + link.anchor1Groups = new List(groups); + } else { + link.anchor2Groups = new List(groups); + } + } +} export class LinkManager { private static _instance: LinkManager; @@ -19,31 +56,30 @@ export class LinkManager { private constructor() { } - @observable - public allLinks: Array = []; + @observable public allLinks: Array = []; + @observable public allGroups: Map = new Map(); - public findAllRelatedLinks(source: Doc): Array { - let related = LinkManager.Instance.allLinks.filter( - link => Doc.AreProtosEqual(source, Cast(link.anchor1, Doc, new Doc)) || Doc.AreProtosEqual(source, Cast(link.anchor2, Doc, new Doc))); - return related; + public findAllRelatedLinks(anchor: Doc): Array { + return LinkManager.Instance.allLinks.filter( + link => Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)) || Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, new Doc))); } - public findRelatedGroupedLinks(source: Doc): Map> { - let related = this.findAllRelatedLinks(source); + public findRelatedGroupedLinks(anchor: Doc): Map> { + let related = this.findAllRelatedLinks(anchor); - let categories = new Map(); + let anchorGroups = new Map(); related.forEach(link => { // get groups of given doc - let groups = (Doc.AreProtosEqual(source, Cast(link.anchor1, Doc, new Doc))) ? Cast(link.anchor1Groups, listSpec(Doc), []) : Cast(link.anchor2Groups, listSpec(Doc), []); - if (groups) { - if (groups.length > 0) { - groups.forEach(groupDoc => { + let oppGroups = (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) ? Cast(link.anchor1Groups, listSpec(Doc), []) : Cast(link.anchor2Groups, listSpec(Doc), []); + if (oppGroups) { + if (oppGroups.length > 0) { + oppGroups.forEach(groupDoc => { if (groupDoc instanceof Doc) { let groupType = StrCast(groupDoc.proto!.type); - let group = categories.get(groupType); // TODO: clean this up lol + let group = anchorGroups.get(groupType); // TODO: clean this up lol if (group) group.push(link); else group = [link]; - categories.set(groupType, group); + anchorGroups.set(groupType, group); } else { // promise doc } @@ -52,10 +88,10 @@ export class LinkManager { } else { // if link is in no groups then put it in default group - let group = categories.get("*"); + let group = anchorGroups.get("*"); if (group) group.push(link); else group = [link]; - categories.set("*", group); + anchorGroups.set("*", group); } } @@ -66,16 +102,11 @@ export class LinkManager { // else group = [link]; // categories.set(link.linkTags, group); }) - return categories; + return anchorGroups; } - public findOppositeAnchor(link: Doc, source: Doc): Doc { - if (Doc.AreProtosEqual(source, Cast(link.anchor1, Doc, new Doc))) { - return Cast(link.anchor2, Doc, new Doc); - } else { - return Cast(link.anchor1, Doc, new Doc); - } - } + + // public findAnchorTags(link: Doc, source: Doc): Doc[] { // if (source) diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 9629585d7..52ed26442 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -39,4 +39,46 @@ .save-button:hover { background: $main-accent; cursor: pointer; +} + +.linkEditor { + font-size: 12px; // TODO + + .linkEditor-back { + // background-color: $dark-color; + // color: $light-color; + margin-bottom: 6px; + } + + .linkEditor-groupsLabel { + display: flex; + justify-content: space-between; + button { + width: 20px; + height: 20px; + margin-left: 6px; + padding: 0; + font-size: 14px; + } + } + .linkEditor-linkedTo { + border-bottom: 0.5px solid $light-color-secondary; + padding-bottom: 6px; + margin-bottom: 6px; + } + .linkEditor-group { + background-color: $light-color-secondary; + padding: 6px; + margin: 3px 0; + border-radius: 3px; + } + .linkEditor-group-row { + display: flex; + .linkEditor-group-row-label { + margin-right: 6px; + } + } + .linkEditor-metadata-row { + display: flex; + } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 2ab8c3460..14fdd26df 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -10,17 +10,57 @@ import { StrCast, Cast } from "../../../new_fields/Types"; import { Doc } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; -import { LinkManager } from "../../util/LinkManager"; +import { LinkManager, LinkUtils } from "../../util/LinkManager"; +import { Docs } from "../../documents/Documents"; +import { Utils } from "../../../Utils"; +import { faArrowLeft, faEllipsisV } from '@fortawesome/free-solid-svg-icons'; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { string } from "prop-types"; -interface Props { +library.add(faArrowLeft); +library.add(faEllipsisV); + +interface LinkEditorProps { sourceDoc: Doc; linkDoc: Doc; - groups: Map; + groups: Map; + metadata: Map>; showLinks: () => void; } @observer -export class LinkEditor extends React.Component { +export class LinkEditor extends React.Component { + + // @observable private _groups: Map = new Map(); + // @observable private _metadata: Map> = new Map(); + + // // componentDidMount() { + + // // } + // constructor(props: LinkEditorProps) { + // super(props); + + // let groups = new Map(); + // let metadata: Map> = new Map(); + // let groupList = (Doc.AreProtosEqual(props.docView.props.Document, Cast(this._editingLink.anchor1, Doc, new Doc))) ? + // Cast(this._editingLink.anchor1Groups, listSpec(Doc), []) : Cast(this._editingLink.anchor2Groups, listSpec(Doc), []); + // groupList.forEach(groupDoc => { + // if (groupDoc instanceof Doc) { + // let id = Utils.GenerateGuid(); + // groups.set(id, groupDoc); + + // let metadataMap = new Map(); + // let metadataDocs = Cast(groupDoc.proto!.metadata, listSpec(Doc), []); + // metadataDocs.forEach(mdDoc => { + // if (mdDoc && mdDoc instanceof Doc) { // TODO: handle promise doc + // metadataMap.set(Utils.GenerateGuid(), mdDoc); + // } + // }) + // metadata.set(id, metadataMap); + // } + // }) + // } // @observable private _title: string = StrCast(this.props.linkDoc.title); // @observable private _description: string = StrCast(this.props.linkDoc.linkDescription); @@ -51,68 +91,175 @@ export class LinkEditor extends React.Component { // } @action - editGroup(groupId: number, value: string) { + editGroup(groupId: string, value: string) { let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; let groupDoc = this.props.groups.get(groupId); if (groupDoc) { groupDoc.proto!.type = value; - if (Doc.AreProtosEqual(this.props.sourceDoc, Cast(linkDoc.anchor1, Doc, new Doc))) { - // let groups = Cast(linkDoc.anchor1Groups, listSpec(Doc), []); - // groups.push(groupDoc); - linkDoc.anchor1Groups = new List([groupDoc]); - - } else { - linkDoc.anchor2Groups = new List([groupDoc]); - } + LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, [groupDoc]); } + } + + @action + addGroup = (e: React.MouseEvent): void => { + // create new document for group + let groupDoc = Docs.TextDocument(); + groupDoc.proto!.title = ""; + groupDoc.proto!.metadata = new List([]); + this.props.groups.set(Utils.GenerateGuid(), groupDoc); + + let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; + LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this.props.groups.values())); } - renderGroup(groupId: number, groupDoc: Doc) { + renderGroup(groupId: string, groupDoc: Doc) { + // let metadata = this.props.metadata.get(groupId); + // if (!metadata) { + // metadata = new Map(); + // } return ( -
-

type:

- this.editGroup(groupId, e.target.value)}> + //
+
+

type:

+ this.editGroup(groupId, e.target.value)}>
+ // {/* {this.renderMetadata(groupId)} */ } + // {/* */ } + // //
) } + @action + addMetadata = (groupId: string): void => { + // create new metadata doc + let mdDoc = Docs.TextDocument(); + mdDoc.proto!.title = ""; + mdDoc.proto!.value = ""; + + // append to map + let mdMap = this.props.metadata.get(groupId); + if (mdMap) { + mdMap.set(Utils.GenerateGuid(), mdDoc); + } else { + mdMap = new Map(); + mdMap.set(Utils.GenerateGuid(), mdDoc); + } + + // add to internal representation of metadata + this.props.metadata.set(groupId, mdMap); + + // add to internatal representation of group + let groupDoc = this.props.groups.get(groupId); + if (groupDoc) { + groupDoc.proto!.metadata = new List(Array.from(mdMap.values())); + this.props.groups.set(groupId, groupDoc); + } + + // add to link doc + let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; + LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this.props.groups.values())); + + } + + // @action + // addMetadata = (groupId: string): void => { + // let groupDoc = this.props.groups.get(groupId); + // if (groupDoc) { + // // create new document for metadata row + // let metadata = Cast(groupDoc.metadata, listSpec(Doc), []); + // let metadataDoc = Docs.TextDocument(); + // metadataDoc.proto!.title = ""; + // metadataDoc.proto!.value = ""; + // let metadataMap = new Map([metadataDoc]); // TODO: append to metadata + // } + // } + + // @action + // editMetadataTitle = (groupId: string, mdId: string, value: string) => { + // let group = this.props.metadata.get(groupId); + // if (group) { + // let mdDoc = group.get(mdId); + // if (mdDoc) { + // mdDoc.proto!.title = value; + // } + // } + // } + + // @action + // editMetadataValue = (groupId: string, mdId: string, value: string) => { + // let group = this.props.metadata.get(groupId); + // if (group) { + // let mdDoc = group.get(mdId); + // if (mdDoc) { + // mdDoc.proto!.value = value; + // } + // } + // } + + @action + editMetadataTitle(groupId: string, mdId: string, value: string) { + + } + + @action + editMetadataValue(groupId: string, mdId: string, value: string) { + + } + + renderMetadata(groupId: string) { + let metadata: Array = []; + let metadataMap = this.props.metadata.get(groupId); + if (metadataMap) { + metadataMap.forEach((mdDoc, mdId) => { + metadata.push( +
+ this.editMetadataTitle(groupId, mdId, e.target.value)}> + : + this.editMetadataValue(groupId, mdId, e.target.value)}> +
+ ) + }) + } + + return metadata; + + // let metadataList: Array = []; + // metadata.forEach((mdDoc, mdId) => { + // metadataList.push( + //
+ // this.editMetadataTitle(groupId, mdId, e.target.value)}>: + // this.editMetadataValue(groupId, mdId, e.target.value)}> + //
+ // ) + // }) + } + renderGroups() { let groups: Array = []; this.props.groups.forEach((groupDoc, groupId) => { - groups.push( -
- {this.renderGroup(groupId, groupDoc)} -
- ) + groups.push(this.renderGroup(groupId, groupDoc)) }); return groups; } - onSaveButtonPressed = (e: React.PointerEvent): void => { - e.stopPropagation(); - - // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; - // // linkDoc.title = this._title; - // // linkDoc.linkDescription = this._description; - - this.props.showLinks(); - } - render() { - let destination = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + let destination = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); return ( -
-

linked to: {destination.proto!.title}

- Groups: +
+ +

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

+
+ Groups: + +
{this.renderGroups()} - {/* - */} - {/* {this.renderTags()} - */} -
SAVE
); diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index affe35e2a..ab478feae 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -8,9 +8,10 @@ import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; -import { LinkManager } from "../../util/LinkManager"; -import { number } from "prop-types"; +import { LinkManager, LinkUtils } from "../../util/LinkManager"; +import { number, string } from "prop-types"; import { listSpec } from "../../../new_fields/Schema"; +import { Utils } from "../../../Utils"; interface Props { docView: DocumentView; @@ -34,12 +35,11 @@ export class LinkMenu extends React.Component { renderLinkGroupItems(links: Doc[]) { let source = this.props.docView.Document; return links.map(link => { - // let destination = (link["linkedTo"] === source) ? link["linkedFrom"] : link["linkedTo"]; - let destination = LinkManager.Instance.findOppositeAnchor(link, source); + let destination = LinkUtils.findOppositeAnchor(link, source); let doc = FieldValue(Cast(destination, Doc)); if (doc) { console.log(doc[Id] + source[Id], "source is", source[Id]); - return this._editingLink = link)} type={""} />; + return this._editingLink = link)} type={""} />; } }); } @@ -79,20 +79,28 @@ export class LinkMenu extends React.Component {
); } else { - let counter = 0; - let groups = new Map(); + let groups = new Map(); + let metadata: Map> = new Map(); let groupList = (Doc.AreProtosEqual(this.props.docView.props.Document, Cast(this._editingLink.anchor1, Doc, new Doc))) ? Cast(this._editingLink.anchor1Groups, listSpec(Doc), []) : Cast(this._editingLink.anchor2Groups, listSpec(Doc), []); - groupList.forEach(group => { - if (group instanceof Doc) { - console.log(counter); - groups.set(counter, group); - counter++; + groupList.forEach(groupDoc => { + if (groupDoc instanceof Doc) { + let id = Utils.GenerateGuid(); + groups.set(id, groupDoc); + + let metadataMap = new Map(); + let metadataDocs = Cast(groupDoc.proto!.metadata, listSpec(Doc), []); + metadataDocs.forEach(mdDoc => { + if (mdDoc && mdDoc instanceof Doc) { // TODO: handle promise doc + metadataMap.set(Utils.GenerateGuid(), mdDoc); + } + }) + metadata.set(id, metadataMap); } }) return ( - this._editingLink = undefined)}> + this._editingLink = undefined)}> ); } -- cgit v1.2.3-70-g09d2 From 05f0f145269fffc5dfada98a5f20bbc8e204bd28 Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 14 Jun 2019 15:30:22 -0400 Subject: cleaned up more link code --- src/client/util/DocumentManager.ts | 42 ++++--------------------------------- src/client/util/DragManager.ts | 17 ++++++--------- src/client/views/nodes/LinkMenu.tsx | 4 ++-- 3 files changed, 12 insertions(+), 51 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 2acbb3ad4..6271220e4 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -9,7 +9,7 @@ import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; import { Id } from '../../new_fields/FieldSymbols'; -import { LinkManager, LinkUtils } from './LinkManager'; +import { LinkManager } from './LinkManager'; export class DocumentManager { @@ -86,53 +86,19 @@ export class DocumentManager { public get LinkedDocumentViews() { let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { - let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { - // let destination = (link["linkedTo"] === dv.props.Document) ? link["linkedFrom"] : link["linkedTo"]; - - let destination = LinkUtils.findOppositeAnchor(link, dv.props.Document); - let linkToDoc = FieldValue(Cast(destination, Doc)); - // let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); - if (linkToDoc) { - DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => + let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); + if (destination) { + DocumentManager.Instance.getDocumentViews(destination).map(docView1 => pairs.push({ a: dv, b: docView1, l: link })); } } return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); } - - // let linksList = DocListCast(dv.props.Document.linkedToDocs); - // console.log("to links", linksList.length); - // if (linksList && linksList.length) { - // pairs.push(...linksList.reduce((pairs, link) => { - // if (link) { - // let linkToDoc = FieldValue(Cast(link.linkedTo, Doc)); - // if (linkToDoc) { - // DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => - // pairs.push({ a: dv, b: docView1, l: link })); - // } - // } - // return pairs; - // }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); - // } - // linksList = DocListCast(dv.props.Document.linkedFromDocs); - // console.log("from links", linksList.length); - // if (linksList && linksList.length) { - // pairs.push(...linksList.reduce((pairs, link) => { - // if (link) { - // let linkFromDoc = FieldValue(Cast(link.linkedFrom, Doc)); - // if (linkFromDoc) { - // DocumentManager.Instance.getDocumentViews(linkFromDoc).map(docView1 => - // pairs.push({ a: dv, b: docView1, l: link })); - // } - // } - // return pairs; - // }, pairs)); - // } return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); return linked; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 9ac421fbf..b4acbcffa 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -4,7 +4,7 @@ import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; -import { LinkManager, LinkUtils } from "./LinkManager"; +import { LinkManager } from "./LinkManager"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { @@ -42,18 +42,13 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; - // let draggedFromDocs: Doc[] = []; if (srcTarg) { - // let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); - // let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); let linkDocs = LinkManager.Instance.findAllRelatedLinks(srcTarg); - if (linkDocs) draggedDocs = linkDocs.map(link => { - return LinkUtils.findOppositeAnchor(link, sourceDoc); - }); - - - // if (linkToDocs) draggedDocs = linkToDocs.map(linkDoc => Cast(linkDoc.linkedTo, Doc) as Doc); - // if (linkFromDocs) draggedFromDocs = linkFromDocs.map(linkDoc => Cast(linkDoc.linkedFrom, Doc) as Doc); + if (linkDocs) { + draggedDocs = linkDocs.map(link => { + return LinkManager.Instance.findOppositeAnchor(link, sourceDoc); + }); + } } // draggedDocs.push(...draggedFromDocs); if (draggedDocs.length) { diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index ebca54c92..2fcbd25fa 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -7,7 +7,7 @@ import './LinkMenu.scss'; import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; -import { LinkManager, LinkUtils } from "../../util/LinkManager"; +import { LinkManager } from "../../util/LinkManager"; interface Props { docView: DocumentView; @@ -22,7 +22,7 @@ export class LinkMenu extends React.Component { renderGroup = (group: Doc[]): Array => { let source = this.props.docView.Document; return group.map(linkDoc => { - let destination = LinkUtils.findOppositeAnchor(linkDoc, source); + let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, source); return this._editingLink = linkDoc)} />; }); } -- cgit v1.2.3-70-g09d2 From 218c8b6476621ef0ffe151014f77bb1d506705a3 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 14 Jun 2019 18:24:01 -0400 Subject: Zooming added to presentation, and done --- src/client/util/DocumentManager.ts | 31 +++++++- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/views/MainOverlayTextBox.tsx | 2 +- src/client/views/MainView.tsx | 5 +- src/client/views/SearchItem.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 6 +- .../views/collections/CollectionSchemaView.tsx | 4 +- .../views/collections/CollectionStackingView.tsx | 2 + .../views/collections/CollectionTreeView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 31 +++++--- src/client/views/nodes/DocumentView.tsx | 10 ++- src/client/views/nodes/FieldView.tsx | 5 +- .../views/presentationview/PresentationElement.tsx | 31 +++++++- .../views/presentationview/PresentationView.tsx | 93 +++++++++++++++++++--- 14 files changed, 184 insertions(+), 42 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 65c4b9e4b..a613625cb 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,4 +1,4 @@ -import { computed, observable } from 'mobx'; +import { computed, observable, action } from 'mobx'; import { DocumentView } from '../views/nodes/DocumentView'; import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types'; @@ -115,7 +115,7 @@ export class DocumentManager { } @undoBatch - public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number): Promise => { + public jumpToDocument = async (docDelegate: Doc, willZoom: boolean, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number): Promise => { let doc = Doc.GetProto(docDelegate); const contextDoc = await Cast(doc.annotationOn, Doc); if (contextDoc) { @@ -128,7 +128,7 @@ export class DocumentManager { if (!forceDockFunc && (docView = DocumentManager.Instance.getDocumentView(doc))) { docView.props.Document.libraryBrush = true; if (linkPage !== undefined) docView.props.Document.curPage = linkPage; - docView.props.focus(docView.props.Document); + docView.props.focus(docView.props.Document, willZoom); } else { if (!contextDoc) { const actualDoc = Doc.MakeAlias(docDelegate); @@ -140,11 +140,34 @@ export class DocumentManager { docDelegate.libraryBrush = true; if (!forceDockFunc && (contextView = DocumentManager.Instance.getDocumentView(contextDoc))) { contextDoc.panTransformType = "Ease"; - contextView.props.focus(contextDoc); + contextView.props.focus(contextDoc, willZoom); } else { (dockFunc || CollectionDockingView.Instance.AddRightSplit)(contextDoc); } } } } + + @action + zoomIntoScale = (docDelegate: Doc, scale: number) => { + let doc = Doc.GetProto(docDelegate); + + let docView: DocumentView | null; + docView = DocumentManager.Instance.getDocumentView(doc); + if (docView) { + docView.props.zoomToScale(scale); + } + } + + getScaleOfDocView = (docDelegate: Doc) => { + let doc = Doc.GetProto(docDelegate); + + let docView: DocumentView | null; + docView = DocumentManager.Instance.getDocumentView(doc); + if (docView) { + return docView.props.getScale(); + } else { + return 1; + } + } } \ No newline at end of file diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index f517f757a..34785446b 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -192,7 +192,7 @@ export class TooltipTextMenu { DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { if (DocumentManager.Instance.getDocumentView(f)) { - DocumentManager.Instance.getDocumentView(f)!.props.focus(f); + DocumentManager.Instance.getDocumentView(f)!.props.focus(f, false); } else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f); } diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 24327b995..d1224febe 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -102,6 +102,6 @@ export class MainOverlayTextBox extends React.Component
; } - else return (null); Z + else return (null); } } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 3d772916e..f78879efe 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -199,7 +199,10 @@ export class MainView extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} - ContainingCollectionView={undefined} />; + ContainingCollectionView={undefined} + zoomToScale={emptyFunction} + getScale={returnOne} + />; let castRes = mainCont ? FieldValue(Cast(mainCont.presentationView, Doc)) : undefined; console.log("GETTING mainContent()"); console.log(castRes instanceof Promise); diff --git a/src/client/views/SearchItem.tsx b/src/client/views/SearchItem.tsx index 01c7316d6..101d893de 100644 --- a/src/client/views/SearchItem.tsx +++ b/src/client/views/SearchItem.tsx @@ -24,7 +24,7 @@ library.add(faFilm); export class SearchItem extends React.Component { onClick = () => { - DocumentManager.Instance.jumpToDocument(this.props.doc); + DocumentManager.Instance.jumpToDocument(this.props.doc, false); } //needs help diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index dcc1bd95d..81f574a6c 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -9,7 +9,7 @@ import { Doc, Field, Opt, DocListCast } from "../../../new_fields/Doc"; import { FieldId } from "../../../new_fields/RefField"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { emptyFunction, returnTrue, Utils } from "../../../Utils"; +import { emptyFunction, returnTrue, Utils, returnOne } from "../../../Utils"; import { DocServer } from "../../DocServer"; import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; import { Transform } from '../../util/Transform'; @@ -483,7 +483,9 @@ export class DockedFrameRenderer extends React.Component { whenActiveChanged={emptyFunction} focus={emptyFunction} addDocTab={this.addDocTab} - ContainingCollectionView={undefined} /> + ContainingCollectionView={undefined} + zoomToScale={emptyFunction} + getScale={returnOne} /> ); } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 11d71d023..715faafd0 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -7,7 +7,7 @@ import { observer } from "mobx-react"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'; import "react-table/react-table.css"; -import { emptyFunction, returnFalse, returnZero } from "../../../Utils"; +import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; import { SetupDrag } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; @@ -451,6 +451,8 @@ export class CollectionSchemaPreview extends React.Component )} {input} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index da7ea50c6..e1453c658 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -146,6 +146,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { bringToFront={emptyFunction} whenActiveChanged={this.props.whenActiveChanged} collapseToPoint={this.collapseToPoint} + zoomToScale={emptyFunction} + getScale={returnOne} /> ); }) diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2814c0502..c80bd8fce 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -147,7 +147,7 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab"), icon: "folder" }); ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight"), icon: "caret-square-right" }); if (DocumentManager.Instance.getDocumentViews(this.props.document).length) { - ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.props.document).map(view => view.props.focus(this.props.document)) }); + ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.props.document).map(view => view.props.focus(this.props.document, false)) }); } ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); } else { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 5d26cb0c2..419d95b5f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -244,7 +244,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { doc.zIndex = docs.length + 1; } - focusDocument = (doc: Doc) => { + focusDocument = (doc: Doc, willZoom: boolean) => { const panX = this.Document.panX; const panY = this.Document.panY; const id = this.Document[Id]; @@ -271,9 +271,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { newState.initializers[id] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); this.setPan(newPanX, newPanY); + this.props.Document.panTransformType = "Ease"; this.props.focus(this.props.Document); - //this.setScaleToZoom(doc); + if (willZoom) { + this.setScaleToZoom(doc); + } } @@ -281,21 +284,29 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let p = this.props; let PanelHeight = p.PanelHeight(); let panelWidth = p.PanelWidth(); - // let heightDif: number = PanelHeight - NumCast(doc.height); - // let widthDif: number = panelWidth - NumCast(doc.width); + let docHeight = NumCast(doc.height); let docWidth = NumCast(doc.width); - let targetHeight = 0.8 * PanelHeight; - let targetWidth = 0.8 * panelWidth; + let targetHeight = 0.5 * PanelHeight; + let targetWidth = 0.5 * panelWidth; let maxScaleX: number = targetWidth / docWidth; let maxScaleY: number = targetHeight / docHeight; - // let maxScaleX: number = NumCast(doc.width) / (panelWidth - 10); - // let maxScaleY: number = NumCast(doc.height) / (PanelHeight - 10); let maxApplicableScale = Math.min(maxScaleX, maxScaleY); this.Document.scale = maxApplicableScale; } + zoomToScale = (scale: number) => { + this.Document.scale = scale; + } + + getScale = () => { + if (this.Document.scale) { + return this.Document.scale; + } + return 1; + } + getDocumentViewProps(document: Doc): DocumentViewProps { return { @@ -315,6 +326,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { whenActiveChanged: this.props.whenActiveChanged, bringToFront: this.bringToFront, addDocTab: this.props.addDocTab, + zoomToScale: this.zoomToScale, + getScale: this.getScale }; } @@ -346,7 +359,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private childViews = () => [ , ...this.views - ]; + ] render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 449fa76a7..fb7657b68 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -69,13 +69,15 @@ export interface DocumentViewProps { ContentScaling: () => number; PanelWidth: () => number; PanelHeight: () => number; - focus: (doc: Doc) => void; + focus: (doc: Doc, willZoom: boolean) => void; selectOnLoad: boolean; parentActive: () => boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc) => void; addDocTab: (doc: Doc, where: string) => void; collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void; + zoomToScale: (scale: number) => void; + getScale: () => number; } const schema = createSchema({ @@ -302,8 +304,8 @@ export class DocumentView extends DocComponent(Docu this._lastTap = Date.now(); } - deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); } - fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") }; + deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); }; + fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"); }; makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); doc.isButton = !BoolCast(doc.isButton, false); @@ -422,7 +424,7 @@ export class DocumentView extends DocComponent(Docu this.props.addDocTab && this.props.addDocTab(Docs.SchemaDocument(["title"], aliases, {}), "onRight"); }, icon: "search" }); - cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" }); + cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" }); cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 7b642b299..3047d55a3 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -103,7 +103,10 @@ export class FieldView extends React.Component { ContainingCollectionView={this.props.ContainingCollectionView} parentActive={this.props.active} whenActiveChanged={this.props.whenActiveChanged} - bringToFront={emptyFunction} /> + bringToFront={emptyFunction} + zoomToScale={emptyFunction} + getScale={returnOne} + /> ); } else if (field instanceof List) { diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index c58570798..00dc07921 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -12,6 +12,7 @@ import { faFile as fileSolid, faLocationArrow, faArrowUp, faSearch } from '@fort import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; +import { DocumentManager } from "../../util/DocumentManager"; @@ -27,7 +28,7 @@ interface PresentationElementProps { document: Doc; index: number; deleteDocument(index: number): void; - gotoDocument(index: number): void; + gotoDocument(index: number, fromDoc: number): Promise; allListElements: Doc[]; groupMappings: Map; presStatus: boolean; @@ -300,6 +301,9 @@ export default class PresentationElement extends React.Component { + e.stopPropagation(); + if (this.selectedButtons[buttonIndex.Show]) { + this.selectedButtons[buttonIndex.Show] = false; + this.props.document.viewScale = 1; + + } else { + if (this.selectedButtons[buttonIndex.Navigate]) { + this.selectedButtons[buttonIndex.Navigate] = false; + } + this.selectedButtons[buttonIndex.Show] = true; + } + + this.autoSaveButtonChange(buttonIndex.Show); + + } + render() { let p = this.props; @@ -330,13 +355,13 @@ export default class PresentationElement extends React.Component { p.gotoDocument(p.index); e.stopPropagation(); }}> + onClick={e => { p.gotoDocument(p.index, NumCast(this.props.mainDocument.selectedDoc)); e.stopPropagation(); }}> {`${p.index + 1}. ${title}`}

- + diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index d3365725b..6cf5fad7e 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -26,7 +26,7 @@ export interface PresViewProps { interface PresListProps extends PresViewProps { deleteDocument(index: number): void; - gotoDocument(index: number): void; + gotoDocument(index: number, fromDoc: number): Promise; groupMappings: Map; presElementsMappings: Map; setChildrenDocs: (docList: Doc[]) => void; @@ -71,9 +71,24 @@ class PresentationViewList extends React.Component { }); } + /** + * Initially every document starts with a viewScale 1, which means + * that they will be displayed in a canvas with scale 1. + */ + @action + initializeScaleViews = (docList: Doc[]) => { + docList.forEach((doc: Doc) => { + let curScale = NumCast(doc.viewScale, null); + if (curScale === undefined) { + doc.viewScale = 1; + } + }); + } + render() { const children = DocListCast(this.props.Document.data); this.initializeGroupIds(children); + this.initializeScaleViews(children); this.props.setChildrenDocs(children); return ( @@ -102,7 +117,6 @@ export class PresentationView extends React.Component { @observable presButtonBackUp: Doc = new Doc(); - componentDidMount() { //getting both backUp documents let castedGroupBackUp = Cast(this.props.Document.presGroupBackUp, Doc); @@ -195,7 +209,7 @@ export class PresentationView extends React.Component { if (nextSelected === current) nextSelected = current + 1; } - this.gotoDocument(nextSelected); + this.gotoDocument(nextSelected, current); } back = async () => { @@ -209,6 +223,7 @@ export class PresentationView extends React.Component { //asking for its presentation id. let curPresId = StrCast(docAtCurrent.presentId); let prevSelected = current - 1; + let zoomOut: boolean = false; //checking if this presentation id is mapped to a group, if so chosing the first element in group if (this.groupMappings.has(curPresId)) { @@ -217,11 +232,29 @@ export class PresentationView extends React.Component { //end of grup so go beyond if (prevSelected === current) prevSelected = current - 1; + //checking if any of the group members had used zooming in + currentsArray.forEach((doc: Doc) => { + if (this.presElementsMappings.get(doc)!.selected[buttonIndex.Show]) { + zoomOut = true; + return; + } + }); } + // if a group set that flag to zero or a single element + //If so making sure to zoom out, which goes back to state before zooming action + if (zoomOut || this.presElementsMappings.get(docAtCurrent)!.selected[buttonIndex.Show]) { + let prevScale = NumCast(this.childrenDocs[prevSelected].viewScale, null); + let curScale = DocumentManager.Instance.getScaleOfDocView(this.childrenDocs[current]); + if (prevScale !== undefined) { + if (prevScale !== curScale) { + DocumentManager.Instance.zoomIntoScale(docAtCurrent, prevScale); + } + } + } + this.gotoDocument(prevSelected, current); - this.gotoDocument(prevSelected); } /** @@ -285,9 +318,10 @@ export class PresentationView extends React.Component { * has the option open and last in the group. If not in the group, and it has * te option open, navigates to that element. */ - navigateToElement = (curDoc: Doc) => { + navigateToElement = async (curDoc: Doc, fromDoc: number) => { let docToJump: Doc = curDoc; let curDocPresId = StrCast(curDoc.presentId, null); + let willZoom: boolean = false; //checking if in group if (curDocPresId !== undefined) { @@ -297,6 +331,11 @@ export class PresentationView extends React.Component { let selectedButtons: boolean[] = this.presElementsMappings.get(doc)!.selected; if (selectedButtons[buttonIndex.Navigate]) { docToJump = doc; + willZoom = false; + } + if (selectedButtons[buttonIndex.Show]) { + docToJump = doc; + willZoom = true; } }); } @@ -305,13 +344,35 @@ export class PresentationView extends React.Component { //docToJump stayed same meaning, it was not in the group or was the last element in the group if (docToJump === curDoc) { //checking if curDoc has navigation open - if (this.presElementsMappings.get(curDoc)!.selected[buttonIndex.Navigate]) { - DocumentManager.Instance.jumpToDocument(curDoc); - } else { - return; + let curDocButtons = this.presElementsMappings.get(curDoc)!.selected; + if (curDocButtons[buttonIndex.Navigate]) { + DocumentManager.Instance.jumpToDocument(curDoc, false); + } else if (curDocButtons[buttonIndex.Show]) { + let curScale = DocumentManager.Instance.getScaleOfDocView(this.childrenDocs[fromDoc]); + //awaiting jump so that new scale can be found, since jumping is async + await DocumentManager.Instance.jumpToDocument(curDoc, true); + let newScale = DocumentManager.Instance.getScaleOfDocView(curDoc); + curDoc.viewScale = newScale; + + //saving the scale user was on before zooming in + if (curScale !== 1) { + this.childrenDocs[fromDoc].viewScale = curScale; + } + } + return; + } + let curScale = DocumentManager.Instance.getScaleOfDocView(this.childrenDocs[fromDoc]); + + //awaiting jump so that new scale can be found, since jumping is async + await DocumentManager.Instance.jumpToDocument(docToJump, willZoom); + let newScale = DocumentManager.Instance.getScaleOfDocView(curDoc); + curDoc.viewScale = newScale; + //saving the scale that user was on + if (curScale !== 1) { + this.childrenDocs[fromDoc].viewScale = curScale; } - DocumentManager.Instance.jumpToDocument(docToJump); + } /** @@ -340,7 +401,7 @@ export class PresentationView extends React.Component { } } @action - public gotoDocument = async (index: number) => { + public gotoDocument = async (index: number, fromDoc: number) => { const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); if (!list) { return; @@ -357,7 +418,7 @@ export class PresentationView extends React.Component { const doc = await list[index]; if (this.presStatus) { - this.navigateToElement(doc); + this.navigateToElement(doc, fromDoc); this.hideIfNotPresented(index); this.showAfterPresented(index); } @@ -407,7 +468,8 @@ export class PresentationView extends React.Component { } else { this.presStatus = true; this.startPresentation(0); - this.gotoDocument(0); + const current = NumCast(this.props.Document.selectedDoc); + this.gotoDocument(0, current); } this.props.Document.presStatus = this.presStatus; } @@ -423,6 +485,11 @@ export class PresentationView extends React.Component { doc.opacity = 1; }); this.props.Document.selectedDoc = 0; + if (this.childrenDocs.length === 0) { + return; + } + DocumentManager.Instance.zoomIntoScale(this.childrenDocs[0], 1); + this.childrenDocs[0].viewScale = 1; } -- cgit v1.2.3-70-g09d2 From d91e7eec9a62363b383b929166cdf600b124334c Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 18 Jun 2019 15:09:21 -0400 Subject: links to nodes in different contexts render as a circle --- src/client/util/DocumentManager.ts | 16 ++- .../CollectionFreeFormLinkView.tsx | 97 +++++++++------ .../CollectionFreeFormLinksView.tsx | 135 +++++++++++++++++---- src/client/views/nodes/DocumentView.tsx | 4 +- 4 files changed, 181 insertions(+), 71 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index fc78993b8..85f8bf751 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,7 +1,7 @@ import { computed, observable } from 'mobx'; import { DocumentView } from '../views/nodes/DocumentView'; import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; -import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types'; +import { FieldValue, Cast, NumCast, BoolCast, StrCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; import { undoBatch } from './UndoManager'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; @@ -85,22 +85,26 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { - + // console.log("FINDING LINKED DVs FOR", StrCast(dv.props.Document.title)); let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); if (destination) { - DocumentManager.Instance.getDocumentViews(destination).map(docView1 => - pairs.push({ a: dv, b: docView1, l: link })); + DocumentManager.Instance.getDocumentViews(destination).map(docView1 => { + // console.log("PUSHING LINK BETWEEN", StrCast(dv.props.Document.title), StrCast(docView1.props.Document.title)); + // TODO: if any docviews are not in the same context, draw a proxy + // let sameContent = dv.props.ContainingCollectionView === docView1.props.ContainingCollectionView; + pairs.push({ anchor1View: dv, anchor2View: docView1, linkDoc: link }); + }); } } return pairs; - }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); + }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[])); } return pairs; - }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); + }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[]); return linked; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index ddde8ece8..36ffac9c8 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -5,58 +5,81 @@ import { InkingControl } from "../../InkingControl"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import v5 = require("uuid/v5"); +import { DocumentView } from "../../nodes/DocumentView"; export interface CollectionFreeFormLinkViewProps { - A: Doc; - B: Doc; - LinkDocs: Doc[]; - addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; - removeDocument: (document: Doc) => boolean; + // anchor1: Doc; + // anchor2: Doc; + // LinkDocs: Doc[]; + // addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; + // removeDocument: (document: Doc) => boolean; + // sameContext: boolean; + + sourceView: DocumentView; + targetView: DocumentView; + sameContext: boolean; } @observer export class CollectionFreeFormLinkView extends React.Component { - onPointerDown = (e: React.PointerEvent) => { - if (e.button === 0 && !InkingControl.Instance.selectedTool) { - let a = this.props.A; - let b = this.props.B; - let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2); - let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2); - let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2); - let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2); - this.props.LinkDocs.map(l => { - let width = l[WidthSym](); - l.x = (x1 + x2) / 2 - width / 2; - l.y = (y1 + y2) / 2 + 10; - if (!this.props.removeDocument(l)) this.props.addDocument(l, false); - }); - e.stopPropagation(); - e.preventDefault(); - } - } + // onPointerDown = (e: React.PointerEvent) => { + // if (e.button === 0 && !InkingControl.Instance.selectedTool) { + // let a = this.props.A; + // let b = this.props.B; + // let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2); + // let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2); + // let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2); + // let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2); + // this.props.LinkDocs.map(l => { + // let width = l[WidthSym](); + // l.x = (x1 + x2) / 2 - width / 2; + // l.y = (y1 + y2) / 2 + 10; + // if (!this.props.removeDocument(l)) this.props.addDocument(l, false); + // }); + // e.stopPropagation(); + // e.preventDefault(); + // } + // } + render() { - let l = this.props.LinkDocs; - let a = this.props.A; - let b = this.props.B; - let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / NumCast(a.zoomBasis, 1) / 2); - let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / NumCast(a.zoomBasis, 1) / 2); - let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / NumCast(b.zoomBasis, 1) / 2); - let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / NumCast(b.zoomBasis, 1) / 2); - let text = ""; - this.props.LinkDocs.map(l => text += StrCast(l.title) + "(" + StrCast(l.linkDescription) + "), "); - text = ""; + // let l = this.props.LinkDocs; + // let a = this.props.A; + // let b = this.props.B; + let a1 = this.props.sourceView; + let a2 = this.props.targetView; + let x1 = NumCast(a1.Document.x) + (BoolCast(a1.Document.isMinimized, false) ? 5 : NumCast(a1.Document.width) / NumCast(a1.Document.zoomBasis, 1) / 2); + let y1 = NumCast(a1.Document.y) + (BoolCast(a1.Document.isMinimized, false) ? 5 : NumCast(a1.Document.height) / NumCast(a1.Document.zoomBasis, 1) / 2); + + let x2 = NumCast(a2.Document.x) + (BoolCast(a2.Document.isMinimized, false) ? 5 : NumCast(a2.Document.width) / NumCast(a2.Document.zoomBasis, 1) / 2); + let y2 = NumCast(a2.Document.y) + (BoolCast(a2.Document.isMinimized, false) ? 5 : NumCast(a2.Document.height) / NumCast(a2.Document.zoomBasis, 1) / 2); + if (!this.props.sameContext) { + x2 = x1 + 300; + y2 = y1 - 300; + } + + // if (!this.props.sameContext) { + // console.log("not same context", StrCast(a1.title), StrCast(a2.title)); + // x2 = x1 + 300; + // y2 = y2 + 300; + // } else { + // console.log("same context", StrCast(a1.title), StrCast(a2.title)); + // } + // let text = ""; + // this.props.LinkDocs.map(l => text += StrCast(l.title) + "(" + StrCast(l.linkDescription) + "), "); + // text = ""; return ( <> - + {!this.props.sameContext ? : <>} {/* */} - + {/* {text} - + */} ); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index c4dd534ed..fc92c81d5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -92,40 +92,123 @@ export class CollectionFreeFormLinksView extends React.Component sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document); } - @computed - get uniqueConnections() { - let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { - let srcViews = this.documentAnchors(connection.a); - let targetViews = this.documentAnchors(connection.b); - let possiblePairs: { a: Doc, b: Doc, }[] = []; - srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }))); - possiblePairs.map(possiblePair => { - if (!drawnPairs.reduce((found, drawnPair) => { - let match1 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.a) && Doc.AreProtosEqual(possiblePair.b, drawnPair.b)); - let match2 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.b) && Doc.AreProtosEqual(possiblePair.b, drawnPair.a)); - let match = match1 || match2; - if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { - drawnPair.l.push(connection.l); - } - return match || found; - }, false)) { - drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] }) + // @computed + // get uniqueConnections() { + // // console.log("\n"); + // let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { + // // console.log("CONNECTION BETWEEN", StrCast(connection.anchor1View.props.Document.title), StrCast(connection.anchor2View.props.Document.title)); + // let srcViews = this.documentAnchors(connection.anchor1View); + // // srcViews.forEach(sv => { + // // console.log("DOCANCHORS SRC", StrCast(connection.anchor1View.Document.title), StrCast(sv.Document.title)); + // // }); + + // let targetViews = this.documentAnchors(connection.anchor2View); + // // targetViews.forEach(sv => { + // // console.log("DOCANCHORS TARG", StrCast(connection.anchor2View.Document.title), StrCast(sv.Document.title)); + // // }); + + // // console.log("lengths", srcViews.length, targetViews.length); + + // // srcViews.forEach(v => { + // // console.log("SOURCE VIEW", StrCast(v.props.Document.title)); + // // }); + // // targetViews.forEach(v => { + // // console.log("TARGET VIEW", StrCast(v.Document.title)); + // // }); + + // let possiblePairs: { anchor1: Doc, anchor2: Doc }[] = []; + // // srcViews.map(sv => { + // // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); + // // targetViews.map(tv => { + // // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); + // // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); + // // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); + // // }); + // // console.log("END\n"); + // // }); + // srcViews.forEach(sv => { + // // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); + // targetViews.forEach(tv => { + // // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); + // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); + // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); + // }); + // // console.log("END\n"); + // }); + // // console.log("POSSIBLE PAIRS LENGTH", possiblePairs.length); + // possiblePairs.map(possiblePair => { + // // console.log("POSSIBLEPAIR", StrCast(possiblePair.anchor1.title), StrCast(possiblePair.anchor2.title)); + // if (!drawnPairs.reduce((found, drawnPair) => { + // let match1 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor1) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor2)); + // let match2 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor2) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor1)); + // let match = match1 || match2; + // if (match && !drawnPair.linkDocs.reduce((found, link) => found || link[Id] === connection.linkDoc[Id], false)) { + // drawnPair.linkDocs.push(connection.linkDoc); + // } + // return match || found; + // }, false)) { + // drawnPairs.push({ anchor1: possiblePair.anchor1, anchor2: possiblePair.anchor2, linkDocs: [connection.linkDoc] }); + // } + // }); + // return drawnPairs; + // }, [] as { anchor1: Doc, anchor2: Doc, linkDocs: Doc[] }[]); + // return connections.map(c => { + // let x = c.linkDocs.reduce((p, l) => p + l[Id], ""); + // return ; + // }); + // } + + findUniquePairs = (): JSX.Element[] => { + // console.log("FIND UNIQUE PAIRS"); + let connections = DocumentManager.Instance.LinkedDocumentViews; + + let unique: Array<{ sourceView: DocumentView, targetView: DocumentView, sameContext: boolean }> = []; + connections.forEach(c => { + let match1Index = unique.findIndex(u => (c.anchor1View === u.sourceView) && (c.anchor2View === u.targetView)); + let match2Index = unique.findIndex(u => (c.anchor1View === u.targetView) && (c.anchor2View === u.sourceView)); + let sameContext = c.anchor1View.props.ContainingCollectionView === c.anchor2View.props.ContainingCollectionView; + + if (!(match1Index > -1 || match2Index > -1)) { + // if docview pair does not already exist in unique, push + unique.push({ sourceView: c.anchor1View, targetView: c.anchor2View, sameContext: sameContext }); + } else { + // if docview pair exists in unique, push if not in same context + if (!sameContext) { + match1Index > -1 ? unique.push({ sourceView: c.anchor2View, targetView: c.anchor1View, sameContext: sameContext }) + : unique.push({ sourceView: c.anchor1View, targetView: c.anchor2View, sameContext: sameContext }); } - }); - return drawnPairs; - }, [] as { a: Doc, b: Doc, l: Doc[] }[]); - return connections.map(c => { - let x = c.l.reduce((p, l) => p + l[Id], ""); - return ; + } + }); + + console.log("\n UNIQUE"); + unique.forEach(u => { + console.log(StrCast(u.sourceView.Document.title), StrCast(u.targetView.Document.title), u.sameContext); + }); + + // console.log("\n"); + + return unique.map(u => { + // TODO: make better key + let key = StrCast(u.sourceView.Document[Id]) + "-link-" + StrCast(u.targetView.Document[Id]) + "-" + Date.now() + Math.random(); + let sourceIn = u.sourceView.props.ContainingCollectionView!.props.Document === this.props.Document; + let targetIn = u.targetView.props.ContainingCollectionView!.props.Document === this.props.Document; + let inContainer = u.sameContext ? sourceIn || targetIn : sourceIn; + if (inContainer) { + // console.log("key", key, StrCast(u.sourceView.Document.title), StrCast(u.targetView.Document.title)); + return ; + } else { + return
; + } }); } render() { + this.findUniquePairs(); return (
- {this.uniqueConnections} + {/* {this.uniqueConnections} */} + {this.findUniquePairs()} {this.props.children}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c998b8ea6..e98392a18 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -319,8 +319,8 @@ export class DocumentView extends DocComponent(Docu this._lastTap = Date.now(); } - deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); } - fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") }; + deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); }; + fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"); }; makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); doc.isButton = !BoolCast(doc.isButton, false); -- cgit v1.2.3-70-g09d2 From 4360287e6cafcb59af1ae62fc31ddc161bcf2e51 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 20 Jun 2019 12:56:13 -0400 Subject: styling of link proxy --- src/client/util/DocumentManager.ts | 17 +++++++++++++---- .../collectionFreeForm/CollectionFreeFormLinkView.scss | 6 ++++-- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index bb87d09ec..84f4d7fa2 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -89,17 +89,26 @@ export class DocumentManager { let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { - if (link) { - let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); - if (destination) { - DocumentManager.Instance.getDocumentViews(destination).map(docView1 => { + // if (link) { + let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); + // console.log("FINDING FOR", StrCast(dv.Document.title), StrCast(destination.title)); + + if (destination) { + let dvs = DocumentManager.Instance.getDocumentViews(destination); + if (dvs.length > 0) { + dvs.map(docView1 => { // console.log("PUSHING LINK BETWEEN", StrCast(dv.props.Document.title), StrCast(docView1.props.Document.title)); // TODO: if any docviews are not in the same context, draw a proxy // let sameContent = dv.props.ContainingCollectionView === docView1.props.ContainingCollectionView; pairs.push({ anchor1View: dv, anchor2View: docView1, linkDoc: link }); + // console.log("PUSHED", StrCast(dv.props.Document.title), StrCast(docView1.Document.title)); }); + } else { + let dv = DocumentManager.Instance.getDocumentView(destination); + dv ? console.log(StrCast(dv.props.Document.title)) : console.log("cant find"); } } + // } return pairs; }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[])); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index d8d518147..0cd4338e5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -33,14 +33,16 @@ width: 200px; height: 100px; border-radius: 5px; + border: 2px solid black; padding: 10px; position: relative; - background-color: black; + background-color: white; + text-align: center; cursor: pointer; p { width: calc(100% - 20px); - color: white; + color: black; position: absolute; top: 50%; left: 50%; -- cgit v1.2.3-70-g09d2 From d78c651322ad228152b862eaa378946fe65cc9f9 Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 21 Jun 2019 13:32:23 -0400 Subject: dragged links from menu are aliases --- src/client/util/DocumentManager.ts | 13 + src/client/util/DragManager.ts | 12 +- .../CollectionFreeFormLinkView.tsx | 14 +- .../CollectionFreeFormLinksView.tsx | 267 ++++++++++----------- 4 files changed, 163 insertions(+), 143 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 84f4d7fa2..325f4894d 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -10,6 +10,7 @@ import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; import { Id } from '../../new_fields/FieldSymbols'; import { LinkManager } from './LinkManager'; +import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; export class DocumentManager { @@ -84,6 +85,18 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { + // console.log("linked"); + // let docs = DocListCast(CurrentUserUtils.UserDocument.data); + // docs.forEach(d => { + // console.log("d", StrCast(d.title)); + + // }); + + // let d = Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc, new Doc); + // console.log("DOC", StrCast(d.title)); + + + let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { // console.log("FINDING LINKED DVs FOR", StrCast(dv.props.Document.title)); let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 01193cab5..78cae4ff7 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,6 +1,6 @@ import { action, runInAction, observable } from "mobx"; import { Doc, DocListCastAsync } from "../../new_fields/Doc"; -import { Cast } from "../../new_fields/Types"; +import { Cast, StrCast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; @@ -52,6 +52,7 @@ export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: num let moddrag = await Cast(draggeddoc.annotationOn, Doc); let dragData = new DragManager.DocumentDragData(moddrag ? [moddrag] : [draggeddoc]); + dragData.dropAction = "alias" as dropActionType; DragManager.StartDocumentDrag([dragEle], dragData, x, y, { handlers: { dragComplete: action(emptyFunction), @@ -82,6 +83,7 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n if (doc) moddrag.push(doc); } let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); + dragData.dropAction = "alias" as dropActionType; // dragData.moveDocument = (document, targetCollection, addDocument) => { // return false; // }; @@ -201,14 +203,18 @@ export namespace DragManager { export let StartDragFunctions: (() => void)[] = []; export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + console.log("outside", dragData.userDropAction, dragData.dropAction); runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, - (dropData: { [id: string]: any }) => + (dropData: { [id: string]: any }) => { + console.log("DRAG", dragData.userDropAction, dragData.dropAction); (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : - dragData.draggedDocuments)); + dragData.draggedDocuments + ); + }); } export function StartAnnotationDrag(eles: HTMLElement[], dragData: AnnotationDragData, downX: number, downY: number, options?: DragOptions) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index ca55b0ff0..65d5ac474 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -16,8 +16,10 @@ export interface CollectionFreeFormLinkViewProps { // removeDocument: (document: Doc) => boolean; // sameContext: boolean; - sourceView: DocumentView; - targetView: DocumentView; + // sourceView: DocumentView; + // targetView: DocumentView; + sourceView: Doc; + targetView: Doc; } @observer @@ -49,11 +51,11 @@ export class CollectionFreeFormLinkView extends React.Component diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 6868e8187..9d2f8946b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -96,153 +96,152 @@ export class CollectionFreeFormLinksView extends React.Component sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === this.props.Document); } - // @computed - // get uniqueConnections() { - // // console.log("\n"); - // let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { - // // console.log("CONNECTION BETWEEN", StrCast(connection.anchor1View.props.Document.title), StrCast(connection.anchor2View.props.Document.title)); - // let srcViews = this.documentAnchors(connection.anchor1View); - // // srcViews.forEach(sv => { - // // console.log("DOCANCHORS SRC", StrCast(connection.anchor1View.Document.title), StrCast(sv.Document.title)); - // // }); - - // let targetViews = this.documentAnchors(connection.anchor2View); - // // targetViews.forEach(sv => { - // // console.log("DOCANCHORS TARG", StrCast(connection.anchor2View.Document.title), StrCast(sv.Document.title)); - // // }); - - // // console.log("lengths", srcViews.length, targetViews.length); - - // // srcViews.forEach(v => { - // // console.log("SOURCE VIEW", StrCast(v.props.Document.title)); - // // }); - // // targetViews.forEach(v => { - // // console.log("TARGET VIEW", StrCast(v.Document.title)); - // // }); - - // let possiblePairs: { anchor1: Doc, anchor2: Doc }[] = []; - // // srcViews.map(sv => { - // // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); - // // targetViews.map(tv => { - // // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); - // // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); - // // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); - // // }); - // // console.log("END\n"); - // // }); - // srcViews.forEach(sv => { - // // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); - // targetViews.forEach(tv => { - // // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); - // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); - // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); - // }); - // // console.log("END\n"); - // }); - // // console.log("POSSIBLE PAIRS LENGTH", possiblePairs.length); - // possiblePairs.map(possiblePair => { - // // console.log("POSSIBLEPAIR", StrCast(possiblePair.anchor1.title), StrCast(possiblePair.anchor2.title)); - // if (!drawnPairs.reduce((found, drawnPair) => { - // let match1 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor1) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor2)); - // let match2 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor2) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor1)); - // let match = match1 || match2; - // if (match && !drawnPair.linkDocs.reduce((found, link) => found || link[Id] === connection.linkDoc[Id], false)) { - // drawnPair.linkDocs.push(connection.linkDoc); - // } - // return match || found; - // }, false)) { - // drawnPairs.push({ anchor1: possiblePair.anchor1, anchor2: possiblePair.anchor2, linkDocs: [connection.linkDoc] }); - // } - // }); - // return drawnPairs; - // }, [] as { anchor1: Doc, anchor2: Doc, linkDocs: Doc[] }[]); - // return connections.map(c => { - // let x = c.linkDocs.reduce((p, l) => p + l[Id], ""); - // return ; - // }); - // } + @computed + get uniqueConnections() { + // console.log("\n"); + let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { + // console.log("CONNECTION BETWEEN", StrCast(connection.anchor1View.props.Document.title), StrCast(connection.anchor2View.props.Document.title)); + let srcViews = this.documentAnchors(connection.anchor1View); + // srcViews.forEach(sv => { + // console.log("DOCANCHORS SRC", StrCast(connection.anchor1View.Document.title), StrCast(sv.Document.title)); + // }); + + let targetViews = this.documentAnchors(connection.anchor2View); + // targetViews.forEach(sv => { + // console.log("DOCANCHORS TARG", StrCast(connection.anchor2View.Document.title), StrCast(sv.Document.title)); + // }); + + // console.log("lengths", srcViews.length, targetViews.length); + + // srcViews.forEach(v => { + // console.log("SOURCE VIEW", StrCast(v.props.Document.title)); + // }); + // targetViews.forEach(v => { + // console.log("TARGET VIEW", StrCast(v.Document.title)); + // }); + + let possiblePairs: { anchor1: Doc, anchor2: Doc }[] = []; + // srcViews.map(sv => { + // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); + // targetViews.map(tv => { + // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); + // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); + // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); + // }); + // console.log("END\n"); + // }); + srcViews.forEach(sv => { + // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); + targetViews.forEach(tv => { + // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); + // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); + possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); + }); + // console.log("END\n"); + }); + // console.log("POSSIBLE PAIRS LENGTH", possiblePairs.length); + possiblePairs.map(possiblePair => { + // console.log("POSSIBLEPAIR", StrCast(possiblePair.anchor1.title), StrCast(possiblePair.anchor2.title)); + if (!drawnPairs.reduce((found, drawnPair) => { + let match1 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor1) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor2)); + let match2 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor2) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor1)); + let match = match1 || match2; + if (match && !drawnPair.linkDocs.reduce((found, link) => found || link[Id] === connection.linkDoc[Id], false)) { + drawnPair.linkDocs.push(connection.linkDoc); + } + return match || found; + }, false)) { + drawnPairs.push({ anchor1: possiblePair.anchor1, anchor2: possiblePair.anchor2, linkDocs: [connection.linkDoc] }); + } + }); + return drawnPairs; + }, [] as { anchor1: Doc, anchor2: Doc, linkDocs: Doc[] }[]); + return connections.map(c => { + let x = c.linkDocs.reduce((p, l) => p + l[Id], ""); + return ; + }); + } - findUniquePairs = (): JSX.Element[] => { - let connections = DocumentManager.Instance.LinkedDocumentViews; + // findUniquePairs = (): JSX.Element[] => { + // let connections = DocumentManager.Instance.LinkedDocumentViews; - // console.log("CONNECTIONS"); - // connections.forEach(c => console.log(StrCast(c.anchor1View.Document.title), StrCast(c.anchor2View.Document.title))); + // // console.log("CONNECTIONS"); + // // connections.forEach(c => console.log(StrCast(c.anchor1View.Document.title), StrCast(c.anchor2View.Document.title))); - let unique: Set<{ sourceView: DocumentView, targetView: DocumentView, linkDoc: Doc }> = new Set(); - connections.forEach(c => { + // let unique: Set<{ sourceView: DocumentView, targetView: DocumentView, linkDoc: Doc }> = new Set(); + // connections.forEach(c => { - // let match1Index = unique.findIndex(u => (c.anchor1View === u.sourceView) && (c.anchor2View === u.targetView)); - // let match2Index = unique.findIndex(u => (c.anchor1View === u.targetView) && (c.anchor2View === u.sourceView)); - let match1 = unique.has({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); - let match2 = unique.has({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); - let sameContext = c.anchor1View.props.ContainingCollectionView === c.anchor2View.props.ContainingCollectionView; + // // let match1Index = unique.findIndex(u => (c.anchor1View === u.sourceView) && (c.anchor2View === u.targetView)); + // // let match2Index = unique.findIndex(u => (c.anchor1View === u.targetView) && (c.anchor2View === u.sourceView)); + // let match1 = unique.has({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); + // let match2 = unique.has({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); + // let sameContext = c.anchor1View.props.ContainingCollectionView === c.anchor2View.props.ContainingCollectionView; - // console.log("CONNECTION", StrCast(c.anchor1View.props.Document.title), StrCast(c.anchor2View.props.Document.title), match1, match2); + // // console.log("CONNECTION", StrCast(c.anchor1View.props.Document.title), StrCast(c.anchor2View.props.Document.title), match1, match2); - // if in same context, push if docview pair does not already exist - // else push both directions of pair - if (sameContext) { - if (!(match1 || match2)) unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); - } else { - unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); - unique.add({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); - } - }); + // // if in same context, push if docview pair does not already exist + // // else push both directions of pair + // if (sameContext) { + // if (!(match1 || match2)) unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); + // } else { + // unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); + // unique.add({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); + // } + // }); - let uniqueList: JSX.Element[] = []; - unique.forEach(u => { - // TODO: make better key - let key = StrCast(u.sourceView.Document[Id]) + "-link-" + StrCast(u.targetView.Document[Id]) + "-" + Date.now() + Math.random(); - let sourceIn = u.sourceView.props.ContainingCollectionView ? u.sourceView.props.ContainingCollectionView.props.Document === this.props.Document : false; - let targetIn = u.targetView.props.ContainingCollectionView ? u.targetView.props.ContainingCollectionView.props.Document === this.props.Document : false; - let sameContext = u.sourceView.props.ContainingCollectionView === u.targetView.props.ContainingCollectionView; - let inContainer = sameContext ? sourceIn || targetIn : sourceIn; - - if (inContainer) { - // let alias = Doc.MakeAlias(proxy); - if (sameContext) { - uniqueList.push(); - } else { - let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); - if (!proxy) { - proxy = Docs.LinkButtonDocument( - { sourceViewId: StrCast(u.sourceView.props.Document[Id]), targetViewId: StrCast(u.targetView.props.Document[Id]) }, - { width: 200, height: 100, borderRounding: 0 }); - let proxy1Proto = Doc.GetProto(proxy); - proxy1Proto.sourceViewId = StrCast(u.sourceView.props.Document[Id]); - proxy1Proto.targetViewId = StrCast(u.targetView.props.Document[Id]); - proxy1Proto.isLinkButton = true; - - // LinkManager.Instance.linkProxies.push(proxy); - LinkManager.Instance.addLinkProxy(proxy); - } - uniqueList.push(); - - // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); - // if (proxy) { - // this.props.addDocument(proxy, false); - // uniqueList.push(); - // } - // let proxyKey = Doc.AreProtosEqual(u.sourceView.Document, Cast(u.linkDoc.anchor1, Doc, new Doc)) ? "proxy1" : "proxy2"; - // let proxy = Cast(u.linkDoc[proxyKey], Doc, new Doc); - // this.props.addDocument(proxy, false); - - // uniqueList.push(); - } - } - }); - return uniqueList; - } + // let uniqueList: JSX.Element[] = []; + // unique.forEach(u => { + // // TODO: make better key + // let key = StrCast(u.sourceView.Document[Id]) + "-link-" + StrCast(u.targetView.Document[Id]) + "-" + Date.now() + Math.random(); + // let sourceIn = u.sourceView.props.ContainingCollectionView ? u.sourceView.props.ContainingCollectionView.props.Document === this.props.Document : false; + // let targetIn = u.targetView.props.ContainingCollectionView ? u.targetView.props.ContainingCollectionView.props.Document === this.props.Document : false; + // let sameContext = u.sourceView.props.ContainingCollectionView === u.targetView.props.ContainingCollectionView; + // let inContainer = sameContext ? sourceIn || targetIn : sourceIn; + + // if (inContainer) { + // // let alias = Doc.MakeAlias(proxy); + // if (sameContext) { + // uniqueList.push(); + // } else { + // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); + // if (!proxy) { + // proxy = Docs.LinkButtonDocument( + // { sourceViewId: StrCast(u.sourceView.props.Document[Id]), targetViewId: StrCast(u.targetView.props.Document[Id]) }, + // { width: 200, height: 100, borderRounding: 0 }); + // let proxy1Proto = Doc.GetProto(proxy); + // proxy1Proto.sourceViewId = StrCast(u.sourceView.props.Document[Id]); + // proxy1Proto.targetViewId = StrCast(u.targetView.props.Document[Id]); + // proxy1Proto.isLinkButton = true; + + // // LinkManager.Instance.linkProxies.push(proxy); + // LinkManager.Instance.addLinkProxy(proxy); + // } + // uniqueList.push(); + + // // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); + // // if (proxy) { + // // this.props.addDocument(proxy, false); + // // uniqueList.push(); + // // } + // // let proxyKey = Doc.AreProtosEqual(u.sourceView.Document, Cast(u.linkDoc.anchor1, Doc, new Doc)) ? "proxy1" : "proxy2"; + // // let proxy = Cast(u.linkDoc[proxyKey], Doc, new Doc); + // // this.props.addDocument(proxy, false); + + // // uniqueList.push(); + // } + // } + // }); + // return uniqueList; + // } render() { - this.findUniquePairs(); return (
- {/* {this.uniqueConnections} */} - {this.findUniquePairs()} + {this.uniqueConnections} + {/* {this.findUniquePairs()} */} {this.props.children}
-- cgit v1.2.3-70-g09d2 From a4b34adcb34184728be0b69b33a561f6d10f0a98 Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 21 Jun 2019 16:27:03 -0400 Subject: can drag just a group of links on a doc --- src/client/documents/Documents.ts | 4 +- src/client/util/DocumentManager.ts | 46 ++----- src/client/util/DragManager.ts | 47 ++++++- .../CollectionFreeFormLinkView.scss | 38 +++--- .../CollectionFreeFormLinkView.tsx | 88 ++++++------ .../CollectionFreeFormLinksView.tsx | 148 +++------------------ src/client/views/nodes/DocumentView.tsx | 2 + src/client/views/nodes/LinkMenu.scss | 15 ++- src/client/views/nodes/LinkMenu.tsx | 18 +-- src/client/views/nodes/LinkMenuGroup.tsx | 74 +++++++++++ src/client/views/nodes/LinkMenuItem.tsx | 8 +- src/new_fields/Doc.ts | 16 ++- 12 files changed, 243 insertions(+), 261 deletions(-) create mode 100644 src/client/views/nodes/LinkMenuGroup.tsx (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index df5c39562..7cef48b98 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -91,7 +91,9 @@ export namespace DocUtils { // let protoSrc = source.proto ? source.proto : source; // let protoTarg = target.proto ? target.proto : target; export function MakeLink(source: Doc, target: Doc, targetContext?: Doc) { - if (LinkManager.Instance.doesLinkExist(source, target)) return; + if (LinkManager.Instance.doesLinkExist(source, target)) { + console.log("LINK EXISTS"); return; + } UndoManager.RunInBatch(() => { diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 325f4894d..c4cb6721a 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -85,51 +85,25 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { - // console.log("linked"); - // let docs = DocListCast(CurrentUserUtils.UserDocument.data); - // docs.forEach(d => { - // console.log("d", StrCast(d.title)); - - // }); - - // let d = Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc, new Doc); - // console.log("DOC", StrCast(d.title)); - - - - let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { - // console.log("FINDING LINKED DVs FOR", StrCast(dv.props.Document.title)); + return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); + // let linksList = DocListCast(dv.props.Document.linkedToDocs); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { - // if (link) { - let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); - // console.log("FINDING FOR", StrCast(dv.Document.title), StrCast(destination.title)); - - if (destination) { - let dvs = DocumentManager.Instance.getDocumentViews(destination); - if (dvs.length > 0) { - dvs.map(docView1 => { - // console.log("PUSHING LINK BETWEEN", StrCast(dv.props.Document.title), StrCast(docView1.props.Document.title)); - // TODO: if any docviews are not in the same context, draw a proxy - // let sameContent = dv.props.ContainingCollectionView === docView1.props.ContainingCollectionView; - pairs.push({ anchor1View: dv, anchor2View: docView1, linkDoc: link }); - // console.log("PUSHED", StrCast(dv.props.Document.title), StrCast(docView1.Document.title)); - }); - } else { - let dv = DocumentManager.Instance.getDocumentView(destination); - dv ? console.log(StrCast(dv.props.Document.title)) : console.log("cant find"); - } + if (link) { + let linkToDoc = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); + // console.log("FOUND ", DocumentManager.Instance.getDocumentViews(linkToDoc).length, "DOCVIEWS FOR", StrCast(linkToDoc.title), "WITH SOURCE", StrCast(dv.props.Document.title)); + DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => + pairs.push({ a: dv, b: docView1, l: link })); } - // } return pairs; - }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[])); + }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); } return pairs; - }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[]); - return linked; + }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); } + @undoBatch public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number, docContext?: Doc): Promise => { let doc = Doc.GetProto(docDelegate); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 11530ef09..2abcff4f7 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -48,12 +48,10 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: number, linkDoc: Doc, sourceDoc: Doc) { let draggeddoc = LinkManager.Instance.findOppositeAnchor(linkDoc, sourceDoc); - // TODO: if not in same context then don't drag - let moddrag = await Cast(draggeddoc.annotationOn, Doc); let dragData = new DragManager.DocumentDragData(moddrag ? [moddrag] : [draggeddoc]); dragData.dropAction = "alias" as dropActionType; - DragManager.StartDocumentDrag([dragEle], dragData, x, y, { + DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { handlers: { dragComplete: action(emptyFunction), }, @@ -83,11 +81,21 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n if (doc) moddrag.push(doc); } let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); - dragData.dropAction = "alias" as dropActionType; // dragData.moveDocument = (document, targetCollection, addDocument) => { // return false; // }; - DragManager.StartDocumentDrag([dragEle], dragData, x, y, { + + // runInAction(() => StartDragFunctions.map(func => func())); + // (eles, dragData, downX, downY, options, + // (dropData: { [id: string]: any }) => { + // (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? + // dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : + // dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? + // dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : + // dragData.draggedDocuments + // ); + // }); + DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { handlers: { dragComplete: action(emptyFunction), }, @@ -215,6 +223,35 @@ export namespace DragManager { }); } + export function StartLinkedDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + + runInAction(() => StartDragFunctions.map(func => func())); + StartDrag(eles, dragData, downX, downY, options, + (dropData: { [id: string]: any }) => { + dropData.droppedDocuments = dragData.draggedDocuments.map(d => { + let dv = DocumentManager.Instance.getDocumentView(d); + // console.log("DRAG", StrCast(d.title)); + + if (dv) { + console.log("DRAG", StrCast(d.title), "has view"); + if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { + console.log("DRAG", StrCast(d.title), "same"); + return d; + } else { + console.log("DRAG", StrCast(d.title), "diff"); + return Doc.MakeAlias(d); + } + } else { + console.log("DRAG", StrCast(d.title), "has no view"); + return Doc.MakeAlias(d); + } + // return (dv && dv.props.ContainingCollectionView !== SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) || !dv ? + // Doc.MakeAlias(d) : d; + }); + + }); + } + export function StartAnnotationDrag(eles: HTMLElement[], dragData: AnnotationDragData, downX: number, downY: number, options?: DragOptions) { StartDrag(eles, dragData, downX, downY, options); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index d8d518147..239c2ce56 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -1,22 +1,22 @@ -// .collectionfreeformlinkview-linkLine { -// stroke: black; -// transform: translate(10000px,10000px); -// opacity: 0.5; -// pointer-events: all; -// } -// .collectionfreeformlinkview-linkCircle { -// stroke: rgb(0,0,0); -// opacity: 0.5; -// transform: translate(10000px,10000px); -// pointer-events: all; -// cursor: pointer; -// } -// .collectionfreeformlinkview-linkText { -// stroke: rgb(0,0,0); -// opacity: 0.5; -// transform: translate(10000px,10000px); -// pointer-events: all; -// } +.collectionfreeformlinkview-linkLine { + stroke: black; + transform: translate(10000px,10000px); + opacity: 0.5; + pointer-events: all; +} +.collectionfreeformlinkview-linkCircle { + stroke: rgb(0,0,0); + opacity: 0.5; + transform: translate(10000px,10000px); + pointer-events: all; + cursor: pointer; +} +.collectionfreeformlinkview-linkText { + stroke: rgb(0,0,0); + opacity: 0.5; + transform: translate(10000px,10000px); + pointer-events: all; +} .linkview-ele { transform: translate(10000px,10000px); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 65d5ac474..5c7f080e0 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -5,70 +5,60 @@ import { InkingControl } from "../../InkingControl"; import "./CollectionFreeFormLinkView.scss"; import React = require("react"); import v5 = require("uuid/v5"); -import { DocumentView } from "../../nodes/DocumentView"; -import { Docs } from "../../../documents/Documents"; export interface CollectionFreeFormLinkViewProps { - // anchor1: Doc; - // anchor2: Doc; - // LinkDocs: Doc[]; - // addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; - // removeDocument: (document: Doc) => boolean; - // sameContext: boolean; - - // sourceView: DocumentView; - // targetView: DocumentView; - sourceView: Doc; - targetView: Doc; + A: Doc; + B: Doc; + LinkDocs: Doc[]; + addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; + removeDocument: (document: Doc) => boolean; } @observer export class CollectionFreeFormLinkView extends React.Component { - // onPointerDown = (e: React.PointerEvent) => { - // if (e.button === 0 && !InkingControl.Instance.selectedTool) { - // let a = this.props.A; - // let b = this.props.B; - // let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2); - // let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2); - // let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2); - // let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2); - // this.props.LinkDocs.map(l => { - // let width = l[WidthSym](); - // l.x = (x1 + x2) / 2 - width / 2; - // l.y = (y1 + y2) / 2 + 10; - // if (!this.props.removeDocument(l)) this.props.addDocument(l, false); - // }); - // e.stopPropagation(); - // e.preventDefault(); - // } - // } - - + onPointerDown = (e: React.PointerEvent) => { + if (e.button === 0 && !InkingControl.Instance.selectedTool) { + let a = this.props.A; + let b = this.props.B; + let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2); + let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2); + let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2); + let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2); + this.props.LinkDocs.map(l => { + let width = l[WidthSym](); + l.x = (x1 + x2) / 2 - width / 2; + l.y = (y1 + y2) / 2 + 10; + if (!this.props.removeDocument(l)) this.props.addDocument(l, false); + }); + e.stopPropagation(); + e.preventDefault(); + } + } render() { - // let l = this.props.LinkDocs; - // let a = this.props.A; - // let b = this.props.B; - let a1 = this.props.sourceView; - let a2 = this.props.targetView; - let x1 = NumCast(a1.x) + (BoolCast(a1.isMinimized, false) ? 5 : NumCast(a1.width) / NumCast(a1.zoomBasis, 1) / 2); - let y1 = NumCast(a1.y) + (BoolCast(a1.isMinimized, false) ? 5 : NumCast(a1.height) / NumCast(a1.zoomBasis, 1) / 2); - - let x2 = NumCast(a2.x) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2); - let y2 = NumCast(a2.y) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.height) / NumCast(a2.zoomBasis, 1) / 2); - + let l = this.props.LinkDocs; + let a = this.props.A; + let b = this.props.B; + let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / NumCast(a.zoomBasis, 1) / 2); + let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / NumCast(a.zoomBasis, 1) / 2); + let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / NumCast(b.zoomBasis, 1) / 2); + let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / NumCast(b.zoomBasis, 1) / 2); + let text = ""; + let first = this.props.LinkDocs[0]; + if (this.props.LinkDocs.length === 1) text += first.title + (first.linkDescription ? "(" + StrCast(first.linkDescription) + ")" : ""); + else text = "-multiple-"; + text = ""; return ( <> - - {/* */} - {/* + {text} - */} + ); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 9d2f8946b..854122592 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -1,4 +1,4 @@ -import { computed, IReactionDisposer, reaction, action } from "mobx"; +import { computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; @@ -11,10 +11,6 @@ import { CollectionViewProps } from "../CollectionSubView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); -import { CollectionFreeFormLinkWithProxyView } from "./CollectionFreeFormLinkWithProxyView"; -import { Docs } from "../../../documents/Documents"; -import { LinkButtonField } from "../../../../new_fields/LinkButtonField"; -import { LinkManager } from "../../../util/LinkManager"; @observer export class CollectionFreeFormLinksView extends React.Component { @@ -98,150 +94,42 @@ export class CollectionFreeFormLinksView extends React.Component { - // console.log("CONNECTION BETWEEN", StrCast(connection.anchor1View.props.Document.title), StrCast(connection.anchor2View.props.Document.title)); - let srcViews = this.documentAnchors(connection.anchor1View); - // srcViews.forEach(sv => { - // console.log("DOCANCHORS SRC", StrCast(connection.anchor1View.Document.title), StrCast(sv.Document.title)); - // }); - - let targetViews = this.documentAnchors(connection.anchor2View); - // targetViews.forEach(sv => { - // console.log("DOCANCHORS TARG", StrCast(connection.anchor2View.Document.title), StrCast(sv.Document.title)); - // }); - - // console.log("lengths", srcViews.length, targetViews.length); + // DocumentManager.Instance.LinkedDocumentViews.forEach(d => { + // console.log("CONNECTION", StrCast(d.a.props.Document.title), StrCast(d.b.props.Document.title)); + // }); - // srcViews.forEach(v => { - // console.log("SOURCE VIEW", StrCast(v.props.Document.title)); - // }); - // targetViews.forEach(v => { - // console.log("TARGET VIEW", StrCast(v.Document.title)); - // }); - - let possiblePairs: { anchor1: Doc, anchor2: Doc }[] = []; - // srcViews.map(sv => { - // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); - // targetViews.map(tv => { - // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); - // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); - // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); - // }); - // console.log("END\n"); - // }); - srcViews.forEach(sv => { - // console.log("SOURCE VIEW", StrCast(sv.props.Document.title)); - targetViews.forEach(tv => { - // console.log("TARGET VIEW", StrCast(tv.props.Document.title)); - // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title)); - possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document }); - }); - // console.log("END\n"); - }); - // console.log("POSSIBLE PAIRS LENGTH", possiblePairs.length); + let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { + let srcViews = this.documentAnchors(connection.a); + let targetViews = this.documentAnchors(connection.b); + let possiblePairs: { a: Doc, b: Doc, }[] = []; + srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }))); possiblePairs.map(possiblePair => { - // console.log("POSSIBLEPAIR", StrCast(possiblePair.anchor1.title), StrCast(possiblePair.anchor2.title)); if (!drawnPairs.reduce((found, drawnPair) => { - let match1 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor1) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor2)); - let match2 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor2) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor1)); + let match1 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.a) && Doc.AreProtosEqual(possiblePair.b, drawnPair.b)); + let match2 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.b) && Doc.AreProtosEqual(possiblePair.b, drawnPair.a)); let match = match1 || match2; - if (match && !drawnPair.linkDocs.reduce((found, link) => found || link[Id] === connection.linkDoc[Id], false)) { - drawnPair.linkDocs.push(connection.linkDoc); + if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) { + drawnPair.l.push(connection.l); } return match || found; }, false)) { - drawnPairs.push({ anchor1: possiblePair.anchor1, anchor2: possiblePair.anchor2, linkDocs: [connection.linkDoc] }); + drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] }); } }); return drawnPairs; - }, [] as { anchor1: Doc, anchor2: Doc, linkDocs: Doc[] }[]); + }, [] as { a: Doc, b: Doc, l: Doc[] }[]); return connections.map(c => { - let x = c.linkDocs.reduce((p, l) => p + l[Id], ""); - return ; + let x = c.l.reduce((p, l) => p + l[Id], ""); + return ; }); } - // findUniquePairs = (): JSX.Element[] => { - // let connections = DocumentManager.Instance.LinkedDocumentViews; - - // // console.log("CONNECTIONS"); - // // connections.forEach(c => console.log(StrCast(c.anchor1View.Document.title), StrCast(c.anchor2View.Document.title))); - - // let unique: Set<{ sourceView: DocumentView, targetView: DocumentView, linkDoc: Doc }> = new Set(); - // connections.forEach(c => { - - // // let match1Index = unique.findIndex(u => (c.anchor1View === u.sourceView) && (c.anchor2View === u.targetView)); - // // let match2Index = unique.findIndex(u => (c.anchor1View === u.targetView) && (c.anchor2View === u.sourceView)); - // let match1 = unique.has({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); - // let match2 = unique.has({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); - // let sameContext = c.anchor1View.props.ContainingCollectionView === c.anchor2View.props.ContainingCollectionView; - - // // console.log("CONNECTION", StrCast(c.anchor1View.props.Document.title), StrCast(c.anchor2View.props.Document.title), match1, match2); - - - // // if in same context, push if docview pair does not already exist - // // else push both directions of pair - // if (sameContext) { - // if (!(match1 || match2)) unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); - // } else { - // unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); - // unique.add({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); - // } - // }); - - // let uniqueList: JSX.Element[] = []; - // unique.forEach(u => { - // // TODO: make better key - // let key = StrCast(u.sourceView.Document[Id]) + "-link-" + StrCast(u.targetView.Document[Id]) + "-" + Date.now() + Math.random(); - // let sourceIn = u.sourceView.props.ContainingCollectionView ? u.sourceView.props.ContainingCollectionView.props.Document === this.props.Document : false; - // let targetIn = u.targetView.props.ContainingCollectionView ? u.targetView.props.ContainingCollectionView.props.Document === this.props.Document : false; - // let sameContext = u.sourceView.props.ContainingCollectionView === u.targetView.props.ContainingCollectionView; - // let inContainer = sameContext ? sourceIn || targetIn : sourceIn; - - // if (inContainer) { - // // let alias = Doc.MakeAlias(proxy); - // if (sameContext) { - // uniqueList.push(); - // } else { - // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); - // if (!proxy) { - // proxy = Docs.LinkButtonDocument( - // { sourceViewId: StrCast(u.sourceView.props.Document[Id]), targetViewId: StrCast(u.targetView.props.Document[Id]) }, - // { width: 200, height: 100, borderRounding: 0 }); - // let proxy1Proto = Doc.GetProto(proxy); - // proxy1Proto.sourceViewId = StrCast(u.sourceView.props.Document[Id]); - // proxy1Proto.targetViewId = StrCast(u.targetView.props.Document[Id]); - // proxy1Proto.isLinkButton = true; - - // // LinkManager.Instance.linkProxies.push(proxy); - // LinkManager.Instance.addLinkProxy(proxy); - // } - // uniqueList.push(); - - // // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); - // // if (proxy) { - // // this.props.addDocument(proxy, false); - // // uniqueList.push(); - // // } - // // let proxyKey = Doc.AreProtosEqual(u.sourceView.Document, Cast(u.linkDoc.anchor1, Doc, new Doc)) ? "proxy1" : "proxy2"; - // // let proxy = Cast(u.linkDoc[proxyKey], Doc, new Doc); - // // this.props.addDocument(proxy, false); - - // // uniqueList.push(); - // } - // } - // }); - // return uniqueList; - // } - render() { return (
{this.uniqueConnections} - {/* {this.findUniquePairs()} */} {this.props.children}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index dbbae2d59..1fc2cf770 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -161,7 +161,9 @@ export class DocumentView extends DocComponent(Docu this._animateToIconDisposer = reaction(() => this.props.Document.isIconAnimating, (values) => (values instanceof List) && this.animateBetweenIcon(values, values[2], values[3] ? true : false) , { fireImmediately: true }); + // console.log("CREATED NEW DOC VIEW", StrCast(this.props.Document.title), DocumentManager.Instance.DocumentViews.length); DocumentManager.Instance.DocumentViews.push(this); + // console.log("ADDED TO DOC MAN", StrCast(this.props.Document.title), DocumentManager.Instance.DocumentViews.length); } animateBetweenIcon = (iconPos: number[], startTime: number, maximizing: boolean) => { diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index d2e411c3d..c01ed23c4 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -18,8 +18,19 @@ } .linkMenu-group-name { - border-bottom: 0.5px solid lightgray; - margin-bottom: 4px; + padding: 4px 6px; + line-height: 12px; + border-radius: 5px; + margin-bottom: 2px; + + &:hover { + background-color: lightgray; + } + } + + .linkMenu-group-wrapper { + border-top: 0.5px solid lightgray; + padding-top: 4px; } } diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 8aca130a5..f96c7d2e4 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -8,6 +8,9 @@ import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { LinkManager } from "../../util/LinkManager"; +import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; +import { emptyFunction } from "../../../Utils"; +import { LinkMenuGroup } from "./LinkMenuGroup"; interface Props { docView: DocumentView; @@ -19,24 +22,11 @@ export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; - renderGroup = (group: Doc[], groupType: string): Array => { - let source = this.props.docView.Document; - return group.map(linkDoc => { - let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, source); - return this._editingLink = linkDoc)} />; - }); - } - renderAllGroups = (groups: Map>): Array => { let linkItems: Array = []; groups.forEach((group, groupType) => { linkItems.push( -
-

{groupType}:

-
- {this.renderGroup(group, groupType)} -
-
+ this._editingLink = linkDoc)} /> ); }); diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx new file mode 100644 index 000000000..229143d99 --- /dev/null +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -0,0 +1,74 @@ +import { action, observable } from "mobx"; +import { observer } from "mobx-react"; +import { DocumentView } from "./DocumentView"; +import { LinkMenuItem } from "./LinkMenuItem"; +import { LinkEditor } from "./LinkEditor"; +import './LinkMenu.scss'; +import React = require("react"); +import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { LinkManager } from "../../util/LinkManager"; +import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; +import { emptyFunction } from "../../../Utils"; + +interface LinkMenuGroupProps { + sourceDoc: Doc; + group: Doc[]; + groupType: string; + showEditor: (linkDoc: Doc) => void; +} + +@observer +export class LinkMenuGroup extends React.Component { + + private _drag = React.createRef(); + + onLinkButtonDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.addEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); + document.addEventListener("pointerup", this.onLinkButtonUp); + } + + onLinkButtonUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); + e.stopPropagation(); + } + + onLinkButtonMoved = async (e: PointerEvent) => { + if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) { + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); + + let draggedDocs = this.props.group.map(linkDoc => LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc)); + let dragData = new DragManager.DocumentDragData(draggedDocs); + + DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, { + handlers: { + dragComplete: action(emptyFunction), + }, + hideSource: false + }); + } + e.stopPropagation(); + } + + render() { + let groupItems = this.props.group.map(linkDoc => { + let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc); + return ; + }); + + return ( +
+

{this.props.groupType}:

+
+ {groupItems} +
+
+ ) + } +} \ No newline at end of file diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index 1ef4690b0..42ef353b7 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -21,7 +21,7 @@ interface LinkMenuItemProps { linkDoc: Doc; sourceDoc: Doc; destinationDoc: Doc; - showEditor: () => void; + showEditor: (linkDoc: Doc) => void; } @observer @@ -42,7 +42,7 @@ export class LinkMenuItem extends React.Component { onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); - this.props.showEditor(); + this.props.showEditor(this.props.linkDoc); } renderMetadata = (): JSX.Element => { @@ -95,12 +95,12 @@ export class LinkMenuItem extends React.Component {
-

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

+

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

{canExpand ?
this.toggleShowMore()}>
: <>}
-
+
{this._showMore ? this.renderMetadata() : <>} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1b0ff812f..5ce47fc2f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -3,11 +3,13 @@ import { serializable, primitive, map, alias, list } from "serializr"; import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper"; import { DocServer } from "../client/DocServer"; import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; -import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types"; +import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast, StrCast } from "./Types"; import { listSpec } from "./Schema"; import { ObjectField } from "./ObjectField"; import { RefField, FieldId } from "./RefField"; import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; +import { LinkManager } from "../client/util/LinkManager"; +import { DocUtils } from "../client/documents/Documents"; export namespace Field { export function toScriptString(field: Field): string { @@ -247,6 +249,18 @@ export namespace Doc { } } }); + console.log("COPY", StrCast(doc.title)); + let links = LinkManager.Instance.findAllRelatedLinks(doc); + links.forEach(linkDoc => { + let opp = LinkManager.Instance.findOppositeAnchor(linkDoc, doc); + console.log("OPP", StrCast(opp.title)); + DocUtils.MakeLink(opp, copy); + }); + + LinkManager.Instance.allLinks.forEach(l => { + console.log("LINK", StrCast(Cast(l.anchor1, Doc, new Doc).title), StrCast(Cast(l.anchor2, Doc, new Doc).title)); + }); + return copy; } -- cgit v1.2.3-70-g09d2 From 522970375fe0227f9221a7e8be02875afd74ca63 Mon Sep 17 00:00:00 2001 From: Fawn Date: Mon, 24 Jun 2019 14:01:29 -0400 Subject: link menu styling --- src/client/util/DocumentManager.ts | 23 ++++++----- src/client/util/DragManager.ts | 12 ++---- src/client/util/LinkManager.ts | 6 +-- .../CollectionFreeFormLinkView.tsx | 24 +++++------ .../CollectionFreeFormLinksView.tsx | 19 ++++++++- src/client/views/nodes/LinkEditor.scss | 2 +- src/client/views/nodes/LinkEditor.tsx | 46 +++++++++++++--------- 7 files changed, 77 insertions(+), 55 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index c4cb6721a..89e6183d6 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -85,20 +85,19 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { + console.log("link"); return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); - // let linksList = DocListCast(dv.props.Document.linkedToDocs); - if (linksList && linksList.length) { - pairs.push(...linksList.reduce((pairs, link) => { - if (link) { - let linkToDoc = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); - // console.log("FOUND ", DocumentManager.Instance.getDocumentViews(linkToDoc).length, "DOCVIEWS FOR", StrCast(linkToDoc.title), "WITH SOURCE", StrCast(dv.props.Document.title)); - DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => - pairs.push({ a: dv, b: docView1, l: link })); - } - return pairs; - }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); - } + pairs.push(...linksList.reduce((pairs, link) => { + if (link) { + let linkToDoc = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); + DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => { + pairs.push({ a: dv, b: docView1, l: link }); + }); + } + return pairs; + }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); + // } return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 2abcff4f7..f4c8adc8e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -7,7 +7,7 @@ import * as globalCssVariables from "../views/globalCssVariables.scss"; import { LinkManager } from "./LinkManager"; import { URLField } from "../../new_fields/URLField"; import { SelectionManager } from "./SelectionManager"; -import { Docs } from "../documents/Documents"; +import { Docs, DocUtils } from "../documents/Documents"; import { DocumentManager } from "./DocumentManager"; export type dropActionType = "alias" | "copy" | undefined; @@ -51,7 +51,7 @@ export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: num let moddrag = await Cast(draggeddoc.annotationOn, Doc); let dragData = new DragManager.DocumentDragData(moddrag ? [moddrag] : [draggeddoc]); dragData.dropAction = "alias" as dropActionType; - DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { + DragManager.StartLinkedDocumentDrag([dragEle], sourceDoc, dragData, x, y, { handlers: { dragComplete: action(emptyFunction), }, @@ -95,7 +95,7 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n // dragData.draggedDocuments // ); // }); - DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, { + DragManager.StartLinkedDocumentDrag([dragEle], sourceDoc, dragData, x, y, { handlers: { dragComplete: action(emptyFunction), }, @@ -223,7 +223,7 @@ export namespace DragManager { }); } - export function StartLinkedDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + export function StartLinkedDocumentDrag(eles: HTMLElement[], sourceDoc: Doc, dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, @@ -233,16 +233,12 @@ export namespace DragManager { // console.log("DRAG", StrCast(d.title)); if (dv) { - console.log("DRAG", StrCast(d.title), "has view"); if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { - console.log("DRAG", StrCast(d.title), "same"); return d; } else { - console.log("DRAG", StrCast(d.title), "diff"); return Doc.MakeAlias(d); } } else { - console.log("DRAG", StrCast(d.title), "has no view"); return Doc.MakeAlias(d); } // return (dv && dv.props.ContainingCollectionView !== SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) || !dv ? diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index fef996bb9..745255f31 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -40,9 +40,9 @@ export class LinkManager { return LinkManager.Instance.allLinks.filter(link => { let protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)); let protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, new Doc)); - let idmatch1 = StrCast(anchor[Id]) === StrCast(Cast(link.anchor1, Doc, new Doc)[Id]); - let idmatch2 = StrCast(anchor[Id]) === StrCast(Cast(link.anchor2, Doc, new Doc)[Id]); - return protomatch1 || protomatch2 || idmatch1 || idmatch2; + // let idmatch1 = StrCast(anchor[Id]) === StrCast(Cast(link.anchor1, Doc, new Doc)[Id]); + // let idmatch2 = StrCast(anchor[Id]) === StrCast(Cast(link.anchor2, Doc, new Doc)[Id]); + return protomatch1 || protomatch2;// || idmatch1 || idmatch2; }); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 5c7f080e0..5dc3b5c16 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -9,6 +9,7 @@ import v5 = require("uuid/v5"); export interface CollectionFreeFormLinkViewProps { A: Doc; B: Doc; + // LinkDoc: Doc; LinkDocs: Doc[]; addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; removeDocument: (document: Doc) => boolean; @@ -25,18 +26,18 @@ export class CollectionFreeFormLinkView extends React.Component { - let width = l[WidthSym](); - l.x = (x1 + x2) / 2 - width / 2; - l.y = (y1 + y2) / 2 + 10; - if (!this.props.removeDocument(l)) this.props.addDocument(l, false); - }); + // this.props.LinkDocs.map(l => { + // let width = l[WidthSym](); + // l.x = (x1 + x2) / 2 - width / 2; + // l.y = (y1 + y2) / 2 + 10; + // if (!this.props.removeDocument(l)) this.props.addDocument(l, false); + // }); e.stopPropagation(); e.preventDefault(); } } render() { - let l = this.props.LinkDocs; + // let l = this.props.LinkDocs; let a = this.props.A; let b = this.props.B; let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / NumCast(a.zoomBasis, 1) / 2); @@ -44,14 +45,13 @@ export class CollectionFreeFormLinkView extends React.Component {/* { let srcViews = this.documentAnchors(connection.a); let targetViews = this.documentAnchors(connection.b); + + console.log(srcViews.length, targetViews.length); let possiblePairs: { a: Doc, b: Doc, }[] = []; - srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }))); + srcViews.map(sv => { + targetViews.map(tv => { + console.log("PUSH", StrCast(sv.props.Document.title), StrCast(sv.props.Document.id), StrCast(tv.props.Document.title), StrCast(tv.props.Document.id)); + possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }); + }); + }); possiblePairs.map(possiblePair => { if (!drawnPairs.reduce((found, drawnPair) => { let match1 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.a) && Doc.AreProtosEqual(possiblePair.b, drawnPair.b)); @@ -123,9 +132,17 @@ export class CollectionFreeFormLinksView extends React.Component; }); + + // return DocumentManager.Instance.LinkedDocumentViews.map(c => { + // // let x = c.l.reduce((p, l) => p + l[Id], ""); + // let x = c.a.Document[Id] + c.b.Document[Id]; + // return ; + // }); } render() { + console.log("\n"); return (
diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 760887fa2..2602b8816 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -30,7 +30,7 @@ height: 20px; margin-left: 6px; padding: 0; - font-size: 12px; + // font-size: 12px; border-radius: 10px; &:disabled { diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 0d13c6cc8..95199bae2 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -7,13 +7,13 @@ import { Doc } from "../../../new_fields/Doc"; import { LinkManager } from "../../util/LinkManager"; import { Docs } from "../../documents/Documents"; import { Utils } from "../../../Utils"; -import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog } from '@fortawesome/free-solid-svg-icons'; +import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SetupDrag } from "../../util/DragManager"; import { anchorPoints, Flyout } from "../DocumentDecorations"; -library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog); +library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); interface GroupTypesDropdownProps { @@ -131,7 +131,7 @@ class LinkMetadataEditor extends React.Component {
this.setMetadataKey(e.target.value)}>: this.setMetadataValue(e.target.value)}> - +
); } @@ -266,6 +266,29 @@ export class LinkEditor extends React.Component { renderGroup = (groupId: string, groupDoc: Doc): JSX.Element => { let type = StrCast(groupDoc.type); if ((type && LinkManager.Instance.groupMetadataKeys.get(type)) || type === "New Group") { + let buttons; + if (type === "New Group") { + buttons = ( + <> + + + + + + + ); + } else { + buttons = ( + <> + + + + + {this.viewGroupAsTable(groupId, type)} + + ); + } + return (
@@ -274,20 +297,7 @@ export class LinkEditor extends React.Component {
{this.renderMetadata(groupId)}
- {groupDoc.type === "New Group" ? : - } - {this.viewGroupAsTable(groupId, type)} - - - - - - }> - - + {buttons}
); @@ -345,7 +355,7 @@ export class LinkEditor extends React.Component {
Relationships: - +
{groups.length > 0 ? groups :
There are currently no relationships associated with this link.
}
-- cgit v1.2.3-70-g09d2 From 41cf1e8536964764f18ab752140e484e36cbe464 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 25 Jun 2019 17:09:36 -0400 Subject: links can save --- src/client/documents/Documents.ts | 58 +--- src/client/util/DocumentManager.ts | 14 +- src/client/util/DragManager.ts | 24 +- src/client/util/LinkManager.ts | 239 +++++++++++---- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainView.tsx | 7 + .../views/collections/CollectionDockingView.tsx | 4 +- .../views/collections/CollectionTreeView.tsx | 18 +- .../CollectionFreeFormLinksView.tsx | 7 +- src/client/views/nodes/DocumentView.tsx | 8 +- src/client/views/nodes/LinkButtonBox.scss | 34 +-- src/client/views/nodes/LinkButtonBox.tsx | 126 ++++---- src/client/views/nodes/LinkEditor.tsx | 323 +++++++++------------ src/client/views/nodes/LinkMenu.tsx | 2 +- src/client/views/nodes/LinkMenuGroup.tsx | 8 +- src/client/views/nodes/LinkMenuItem.tsx | 6 +- src/new_fields/Doc.ts | 9 +- src/new_fields/LinkButtonField.ts | 58 ++-- 18 files changed, 503 insertions(+), 444 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 64032e096..fbd96fb66 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -35,8 +35,8 @@ import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; import { LinkManager } from "../util/LinkManager"; -import { LinkButtonBox } from "../views/nodes/LinkButtonBox"; -import { LinkButtonField, LinkButtonData } from "../../new_fields/LinkButtonField"; +// import { LinkButtonBox } from "../views/nodes/LinkButtonBox"; +// import { LinkButtonField, LinkButtonData } from "../../new_fields/LinkButtonField"; import { DocumentManager } from "../util/DocumentManager"; import { Id } from "../../new_fields/FieldSymbols"; var requestImageSize = require('request-image-size'); @@ -100,6 +100,7 @@ export namespace DocUtils { let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); let linkDocProto = Doc.GetProto(linkDoc); + linkDocProto.context = targetContext; linkDocProto.title = title; //=== "" ? source.title + " to " + target.title : title; linkDocProto.linkDescription = description; linkDocProto.linkTags = tags; @@ -111,36 +112,7 @@ export namespace DocUtils { linkDocProto.anchor2Page = target.curPage; linkDocProto.anchor2Groups = new List([]); - linkDocProto.context = targetContext; - - let sourceViews = DocumentManager.Instance.getDocumentViews(source); - let targetViews = DocumentManager.Instance.getDocumentViews(target); - sourceViews.forEach(sv => { - targetViews.forEach(tv => { - - // TODO: do only for when diff contexts - let proxy1 = Docs.LinkButtonDocument( - { sourceViewId: StrCast(sv.props.Document[Id]), targetViewId: StrCast(tv.props.Document[Id]) }, - { width: 200, height: 100, borderRounding: 0 }); - let proxy1Proto = Doc.GetProto(proxy1); - proxy1Proto.sourceViewId = StrCast(sv.props.Document[Id]); - proxy1Proto.targetViewId = StrCast(tv.props.Document[Id]); - proxy1Proto.isLinkButton = true; - - let proxy2 = Docs.LinkButtonDocument( - { sourceViewId: StrCast(tv.props.Document[Id]), targetViewId: StrCast(sv.props.Document[Id]) }, - { width: 200, height: 100, borderRounding: 0 }); - let proxy2Proto = Doc.GetProto(proxy2); - proxy2Proto.sourceViewId = StrCast(tv.props.Document[Id]); - proxy2Proto.targetViewId = StrCast(sv.props.Document[Id]); - proxy2Proto.isLinkButton = true; - - LinkManager.Instance.linkProxies.push(proxy1); - LinkManager.Instance.linkProxies.push(proxy2); - }); - }); - - LinkManager.Instance.allLinks.push(linkDoc); + LinkManager.Instance.addLink(linkDoc); return linkDoc; }, "make link"); @@ -160,7 +132,7 @@ export namespace Docs { let audioProto: Doc; let pdfProto: Doc; let iconProto: Doc; - let linkProto: Doc; + // let linkProto: Doc; const textProtoId = "textProto"; const histoProtoId = "histoProto"; const pdfProtoId = "pdfProto"; @@ -171,7 +143,7 @@ export namespace Docs { const videoProtoId = "videoProto"; const audioProtoId = "audioProto"; const iconProtoId = "iconProto"; - const linkProtoId = "linkProto"; + // const linkProtoId = "linkProto"; export function initProtos(): Promise { return DocServer.GetRefFields([textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId]).then(fields => { @@ -185,7 +157,7 @@ export namespace Docs { audioProto = fields[audioProtoId] as Doc || CreateAudioPrototype(); pdfProto = fields[pdfProtoId] as Doc || CreatePdfPrototype(); iconProto = fields[iconProtoId] as Doc || CreateIconPrototype(); - linkProto = fields[linkProtoId] as Doc || CreateLinkPrototype(); + // linkProto = fields[linkProtoId] as Doc || CreateLinkPrototype(); }); } @@ -218,11 +190,11 @@ export namespace Docs { { x: 0, y: 0, width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE) }); return iconProto; } - function CreateLinkPrototype(): Doc { - let linkProto = setupPrototypeOptions(linkProtoId, "LINK_PROTO", LinkButtonBox.LayoutString(), - { x: 0, y: 0, width: 300 }); - return linkProto; - } + // function CreateLinkPrototype(): Doc { + // let linkProto = setupPrototypeOptions(linkProtoId, "LINK_PROTO", LinkButtonBox.LayoutString(), + // { x: 0, y: 0, width: 300 }); + // return linkProto; + // } function CreateTextPrototype(): Doc { let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), { x: 0, y: 0, width: 300, backgroundColor: "#f1efeb" }); @@ -309,9 +281,9 @@ export namespace Docs { export function IconDocument(icon: string, options: DocumentOptions = {}) { return CreateInstance(iconProto, new IconField(icon), options); } - export function LinkButtonDocument(data: LinkButtonData, options: DocumentOptions = {}) { - return CreateInstance(linkProto, new LinkButtonField(data), options); - } + // export function LinkButtonDocument(data: LinkButtonData, options: DocumentOptions = {}) { + // return CreateInstance(linkProto, new LinkButtonField(data), options); + // } export function PdfDocument(url: string, options: DocumentOptions = {}) { return CreateInstance(pdfProto, new PdfField(new URL(url)), options); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 89e6183d6..767abe63f 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -85,12 +85,11 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { - console.log("link"); - return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { - let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document); + let pairs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { + let linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document); pairs.push(...linksList.reduce((pairs, link) => { if (link) { - let linkToDoc = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document); + let linkToDoc = LinkManager.Instance.getOppositeAnchor(link, dv.props.Document); DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => { pairs.push({ a: dv, b: docView1, l: link }); }); @@ -100,6 +99,13 @@ export class DocumentManager { // } return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); + + // console.log("LINKED DOCUMENT VIEWS"); + // pairs.forEach(p => { + // console.log(StrCast(p.a.Document.title), p.a.props.Document[Id], StrCast(p.b.Document.title), p.b.props.Document[Id]); + // }); + + return pairs; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index f4c8adc8e..1aacf2c53 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -46,7 +46,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () } export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: number, linkDoc: Doc, sourceDoc: Doc) { - let draggeddoc = LinkManager.Instance.findOppositeAnchor(linkDoc, sourceDoc); + let draggeddoc = LinkManager.Instance.getOppositeAnchor(linkDoc, sourceDoc); let moddrag = await Cast(draggeddoc.annotationOn, Doc); let dragData = new DragManager.DocumentDragData(moddrag ? [moddrag] : [draggeddoc]); @@ -66,10 +66,10 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n // TODO: if not in same context then don't drag if (srcTarg) { - let linkDocs = LinkManager.Instance.findAllRelatedLinks(srcTarg); + let linkDocs = LinkManager.Instance.getAllRelatedLinks(srcTarg); if (linkDocs) { draggedDocs = linkDocs.map(link => { - return LinkManager.Instance.findOppositeAnchor(link, sourceDoc); + return LinkManager.Instance.getOppositeAnchor(link, sourceDoc); }); } } @@ -236,10 +236,16 @@ export namespace DragManager { if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { return d; } else { - return Doc.MakeAlias(d); + // return d; + let r = Doc.MakeAlias(d); + // DocUtils.MakeLink(sourceDoc, r); + return r; } } else { - return Doc.MakeAlias(d); + // return d; + let r = Doc.MakeAlias(d); + // DocUtils.MakeLink(sourceDoc, r); + return r; } // return (dv && dv.props.ContainingCollectionView !== SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) || !dv ? // Doc.MakeAlias(d) : d; @@ -282,10 +288,10 @@ export namespace DragManager { StartDrag([ele], dragData, downX, downY, options); } - export function StartLinkProxyDrag(ele: HTMLElement, dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { - runInAction(() => StartDragFunctions.map(func => func())); - StartDrag([ele], dragData, downX, downY, options); - } + // export function StartLinkProxyDrag(ele: HTMLElement, dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + // runInAction(() => StartDragFunctions.map(func => func())); + // StartDrag([ele], dragData, downX, downY, options); + // } export let AbortDrag: () => void = emptyFunction; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 745255f31..82c3a9acd 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -1,9 +1,10 @@ import { observable, action } from "mobx"; -import { StrCast, Cast } from "../../new_fields/Types"; +import { StrCast, Cast, FieldValue } from "../../new_fields/Types"; import { Doc, DocListCast } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; import { List } from "../../new_fields/List"; import { Id } from "../../new_fields/FieldSymbols"; +import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; /* @@ -23,6 +24,11 @@ import { Id } from "../../new_fields/FieldSymbols"; * - user defined kvps */ export class LinkManager { + // static Instance: LinkManager; + // private constructor() { + // LinkManager.Instance = this; + // } + private static _instance: LinkManager; public static get Instance(): LinkManager { return this._instance || (this._instance = new this()); @@ -30,25 +36,138 @@ export class LinkManager { private constructor() { } - @observable public allLinks: Array = []; // list of link docs - @observable public groupMetadataKeys: Map> = new Map(); - // map of group type to list of its metadata keys; serves as a dictionary of groups to what kind of metadata it hodls - @observable public linkProxies: Array = []; // list of linkbutton docs - used to visualize link when an anchors are not in the same context + public get LinkManagerDoc(): Doc | undefined { + return FieldValue(Cast(CurrentUserUtils.UserDocument.linkManagerDoc, Doc)); + } + // @observable public allLinks: Array = []; //List = new List([]); // list of link docs + // @observable public groupMetadataKeys: Map> = new Map(); + // map of group type to list of its metadata keys; serves as a dictionary of groups to what kind of metadata it holds + + public getAllLinks(): Doc[] { + return LinkManager.Instance.LinkManagerDoc ? LinkManager.Instance.LinkManagerDoc.allLinks ? DocListCast(LinkManager.Instance.LinkManagerDoc.allLinks) : [] : []; + } + + public addLink(linkDoc: Doc): boolean { + let linkList = LinkManager.Instance.getAllLinks(); + linkList.push(linkDoc); + console.log("link man doc", LinkManager.Instance.LinkManagerDoc); + if (LinkManager.Instance.LinkManagerDoc) { + LinkManager.Instance.LinkManagerDoc.allLinks = new List(linkList); + return true; + } + return false; + } + + public deleteLink(linkDoc: Doc): boolean { + let linkList = LinkManager.Instance.getAllLinks(); + let index = LinkManager.Instance.getAllLinks().indexOf(linkDoc); + if (index > -1) { + linkList.splice(index, 1); + if (LinkManager.Instance.LinkManagerDoc) { + LinkManager.Instance.LinkManagerDoc.allLinks = new List(linkList); + return true; + } + } + return false; + } // finds all links that contain the given anchor - public findAllRelatedLinks(anchor: Doc): Array { - return LinkManager.Instance.allLinks.filter(link => { + public getAllRelatedLinks(anchor: Doc): Doc[] {//List { + let related = LinkManager.Instance.getAllLinks().filter(link => { let protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)); let protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, new Doc)); - // let idmatch1 = StrCast(anchor[Id]) === StrCast(Cast(link.anchor1, Doc, new Doc)[Id]); - // let idmatch2 = StrCast(anchor[Id]) === StrCast(Cast(link.anchor2, Doc, new Doc)[Id]); - return protomatch1 || protomatch2;// || idmatch1 || idmatch2; + return protomatch1 || protomatch2; }); + return related; + } + + public addGroupType(groupType: string): boolean { + if (LinkManager.Instance.LinkManagerDoc) { + LinkManager.Instance.LinkManagerDoc[groupType] = new List([]); + let groupTypes = LinkManager.Instance.getAllGroupTypes(); + groupTypes.push(groupType); + LinkManager.Instance.LinkManagerDoc.allGroupTypes = new List(groupTypes); + return true; + } + return false; + } + + // removes all group docs from all links with the given group type + public deleteGroupType(groupType: string): boolean { + if (LinkManager.Instance.LinkManagerDoc) { + if (LinkManager.Instance.LinkManagerDoc[groupType]) { + LinkManager.Instance.LinkManagerDoc[groupType] = undefined; + LinkManager.Instance.getAllLinks().forEach(linkDoc => { + LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType); + LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc), groupType); + }); + } + return true; + } else return false; + } + + public getAllGroupTypes(): string[] { + if (LinkManager.Instance.LinkManagerDoc) { + if (LinkManager.Instance.LinkManagerDoc.allGroupTypes) { + return Cast(LinkManager.Instance.LinkManagerDoc.allGroupTypes, listSpec("string"), []); + } else { + LinkManager.Instance.LinkManagerDoc.allGroupTypes = new List([]); + return []; + } + } + return []; + } + + // gets the groups associates with an anchor in a link + public getAnchorGroups(linkDoc: Doc, anchor: Doc): Array { + if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { + return DocListCast(linkDoc.anchor1Groups); + } else { + return DocListCast(linkDoc.anchor2Groups); + } + } + + // sets the groups of the given anchor in the given link + public setAnchorGroups(linkDoc: Doc, anchor: Doc, groups: Doc[]) { + if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { + linkDoc.anchor1Groups = new List(groups); + } else { + linkDoc.anchor2Groups = new List(groups); + } + } + + public addGroupToAnchor(linkDoc: Doc, anchor: Doc, groupDoc: Doc, replace: boolean = false) { + let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); + let index = groups.findIndex(gDoc => { + return StrCast(groupDoc.type).toUpperCase() === StrCast(gDoc.type).toUpperCase(); + }); + if (index > -1 && replace) { + groups[index] = groupDoc; + } + if (index === -1) { + groups.push(groupDoc); + } + LinkManager.Instance.setAnchorGroups(linkDoc, anchor, groups); + } + + // removes group doc of given group type only from given anchor on given link + public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) { + let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); + let newGroups = groups.filter(groupDoc => StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase()); + LinkManager.Instance.setAnchorGroups(linkDoc, anchor, newGroups); } + // public doesAnchorHaveGroup(linkDoc: Doc, anchor: Doc, groupDoc: Doc): boolean { + // let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); + // let index = groups.findIndex(gDoc => { + // return StrCast(groupDoc.type).toUpperCase() === StrCast(gDoc.type).toUpperCase(); + // }); + // return index > -1; + // } + // returns map of group type to anchor's links in that group type - public findRelatedGroupedLinks(anchor: Doc): Map> { - let related = this.findAllRelatedLinks(anchor); + public getRelatedGroupedLinks(anchor: Doc): Map> { + let related = this.getAllRelatedLinks(anchor); let anchorGroups = new Map>(); related.forEach(link => { let groups = LinkManager.Instance.getAnchorGroups(link, anchor); @@ -73,10 +192,41 @@ export class LinkManager { return anchorGroups; } + // public addMetadataKeyToGroup(groupType: string, key: string): boolean { + // if (LinkManager.Instance.LinkManagerDoc) { + // if (LinkManager.Instance.LinkManagerDoc[groupType]) { + // let keyList = LinkManager.Instance.findMetadataKeysInGroup(groupType); + // keyList.push(key); + // LinkManager.Instance.LinkManagerDoc[groupType] = new List(keyList); + // return true; + // } + // return false; + // } + // return false; + // } + + public getMetadataKeysInGroup(groupType: string): string[] { + if (LinkManager.Instance.LinkManagerDoc) { + return LinkManager.Instance.LinkManagerDoc[groupType] ? Cast(LinkManager.Instance.LinkManagerDoc[groupType], listSpec("string"), []) : []; + } + return []; + } + + public setMetadataKeysForGroup(groupType: string, keys: string[]): boolean { + if (LinkManager.Instance.LinkManagerDoc) { + // if (LinkManager.Instance.LinkManagerDoc[groupType]) { + LinkManager.Instance.LinkManagerDoc[groupType] = new List(keys); + return true; + // } + // return false; + } + return false; + } + // returns a list of all metadata docs associated with the given group type - public findAllMetadataDocsInGroup(groupType: string): Array { + public getAllMetadataDocsInGroup(groupType: string): Array { let md: Doc[] = []; - let allLinks = LinkManager.Instance.allLinks; + let allLinks = LinkManager.Instance.getAllLinks(); allLinks.forEach(linkDoc => { let anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc)); let anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc)); @@ -86,27 +236,9 @@ export class LinkManager { return md; } - // removes all group docs from all links with the given group type - public deleteGroup(groupType: string): void { - let deleted = LinkManager.Instance.groupMetadataKeys.delete(groupType); - if (deleted) { - LinkManager.Instance.allLinks.forEach(linkDoc => { - LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType); - LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc), groupType); - }); - } - } - - // removes group doc of given group type only from given anchor on given link - public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) { - let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); - let newGroups = groups.filter(groupDoc => StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase()); - LinkManager.Instance.setAnchorGroups(linkDoc, anchor, newGroups); - } - // checks if a link with the given anchors exists - public doesLinkExist(anchor1: Doc, anchor2: Doc) { - let allLinks = LinkManager.Instance.allLinks; + public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean { + let allLinks = LinkManager.Instance.getAllLinks(); let index = allLinks.findIndex(linkDoc => { return (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, new Doc), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, new Doc), anchor2)) || (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, new Doc), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, new Doc), anchor1)); @@ -115,7 +247,7 @@ export class LinkManager { } // finds the opposite anchor of a given anchor in a link - public findOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc { + public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc { if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { return Cast(linkDoc.anchor2, Doc, new Doc); } else { @@ -123,34 +255,17 @@ export class LinkManager { } } - // gets the groups associates with an anchor in a link - public getAnchorGroups(linkDoc: Doc, anchor: Doc): Array { - if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { - return DocListCast(linkDoc.anchor1Groups); - } else { - return DocListCast(linkDoc.anchor2Groups); - } - } - // sets the groups of the given anchor in the given link - public setAnchorGroups(linkDoc: Doc, anchor: Doc, groups: Doc[]) { - if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { - linkDoc.anchor1Groups = new List(groups); - } else { - linkDoc.anchor2Groups = new List(groups); - } - } - - @action - public addLinkProxy(proxy: Doc) { - LinkManager.Instance.linkProxies.push(proxy); - } + // @action + // public addLinkProxy(proxy: Doc) { + // LinkManager.Instance.linkProxies.push(proxy); + // } - public findLinkProxy(sourceViewId: string, targetViewId: string): Doc | undefined { - let index = LinkManager.Instance.linkProxies.findIndex(p => { - return StrCast(p.sourceViewId) === sourceViewId && StrCast(p.targetViewId) === targetViewId; - }); - return index > -1 ? LinkManager.Instance.linkProxies[index] : undefined; - } + // public findLinkProxy(sourceViewId: string, targetViewId: string): Doc | undefined { + // let index = LinkManager.Instance.linkProxies.findIndex(p => { + // return StrCast(p.sourceViewId) === sourceViewId && StrCast(p.targetViewId) === targetViewId; + // }); + // return index > -1 ? LinkManager.Instance.linkProxies[index] : undefined; + // } } \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 926273633..3a2752d7e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -573,7 +573,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let linkButton = null; if (SelectionManager.SelectedDocuments().length > 0) { let selFirst = SelectionManager.SelectedDocuments()[0]; - let linkCount = LinkManager.Instance.findAllRelatedLinks(selFirst.props.Document).length; + let linkCount = LinkManager.Instance.getAllRelatedLinks(selFirst.props.Document).length; linkButton = (([]); + CurrentUserUtils.UserDocument.linkManagerDoc = linkManagerDoc; + } list.push(mainDoc); // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) setTimeout(() => { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index c82027da5..4140f8029 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -354,9 +354,9 @@ export class CollectionDockingView extends React.Component [LinkManager.Instance.findAllRelatedLinks(doc), doc.title], + tab.reactionDisposer = reaction(() => [LinkManager.Instance.getAllRelatedLinks(doc), doc.title], () => { - counter.innerHTML = LinkManager.Instance.findAllRelatedLinks(doc).length; + counter.innerHTML = LinkManager.Instance.getAllRelatedLinks(doc).length; tab.titleElement[0].textContent = doc.title; }, { fireImmediately: true }); tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 0b922b3c4..7bc3ad124 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -73,7 +73,7 @@ class TreeView extends React.Component { @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight"); - onPointerDown = (e: React.PointerEvent) => e.stopPropagation() + onPointerDown = (e: React.PointerEvent) => e.stopPropagation(); onPointerEnter = (e: React.PointerEvent): void => { this.props.active() && (this.props.document.libraryBrush = true); if (e.buttons === 1 && SelectionManager.GetIsDragging()) { @@ -115,7 +115,7 @@ class TreeView extends React.Component { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); } @action - indent = () => this.props.addDocument(this.props.document) && this.delete(); + indent = () => this.props.addDocument(this.props.document) && this.delete() renderBullet() { let docList = Cast(this.props.document["data"], listSpec(Doc)); @@ -167,7 +167,7 @@ class TreeView extends React.Component { keyList.push(key); } }); - if (LinkManager.Instance.findAllRelatedLinks(this.props.document).length > 0) keyList.push("links"); + if (LinkManager.Instance.getAllRelatedLinks(this.props.document).length > 0) keyList.push("links"); if (keyList.indexOf("data") !== -1) { keyList.splice(keyList.indexOf("data"), 1); } @@ -281,9 +281,9 @@ class TreeView extends React.Component { let ele: JSX.Element[] = []; let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey); let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before); - let groups = LinkManager.Instance.findRelatedGroupedLinks(this.props.document); + let groups = LinkManager.Instance.getRelatedGroupedLinks(this.props.document); groups.forEach((groupLinkDocs, groupType) => { - let destLinks = groupLinkDocs.map(d => LinkManager.Instance.findOppositeAnchor(d, this.props.document)); + let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document)); ele.push(
{groupType}:
@@ -325,7 +325,7 @@ class TreeView extends React.Component { addDocTab={this.props.addDocTab} setPreviewScript={emptyFunction}> -
+
; } } return
@@ -364,14 +364,14 @@ class TreeView extends React.Component { TreeView.AddDocToList(docList[i - 1], fieldKey, child); remove(child); } - } + }; let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => { return add(doc, relativeTo ? relativeTo : docList[i], before !== undefined ? before : false); - } + }; let rowHeight = () => { let aspect = NumCast(child.nativeWidth, 0) / NumCast(child.nativeHeight, 0); return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym](); - } + }; return { let srcViews = this.documentAnchors(connection.a); let targetViews = this.documentAnchors(connection.b); - console.log(srcViews.length, targetViews.length); + // console.log(srcViews.length, targetViews.length); let possiblePairs: { a: Doc, b: Doc, }[] = []; srcViews.map(sv => { targetViews.map(tv => { - console.log("PUSH", StrCast(sv.props.Document.title), StrCast(sv.props.Document.id), StrCast(tv.props.Document.title), StrCast(tv.props.Document.id)); + // console.log("PUSH", StrCast(sv.props.Document.title), StrCast(sv.props.Document.id), StrCast(tv.props.Document.title), StrCast(tv.props.Document.id)); possiblePairs.push({ a: sv.props.Document, b: tv.props.Document }); }); }); @@ -142,7 +142,6 @@ export class CollectionFreeFormLinksView extends React.Component diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1fc2cf770..7b185336b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -285,7 +285,7 @@ export class DocumentView extends DocComponent(Docu let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs); let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs); - let linkedDocs = LinkManager.Instance.findAllRelatedLinks(this.props.Document); + let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document); let expandedDocs: Doc[] = []; expandedDocs = subBulletDocs ? [...subBulletDocs, ...expandedDocs] : expandedDocs; expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; @@ -536,11 +536,6 @@ export class DocumentView extends DocComponent(Docu onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; - onDragOver = (e: React.DragEvent): void => { - this.props.Document.libraryBrush = true; - console.log("dragOver"); - }; - onDragLeave = (e: React.DragEvent): void => { this.props.Document.libraryBrush = false; }; isSelected = () => SelectionManager.IsSelected(this); @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; @@ -585,7 +580,6 @@ export class DocumentView extends DocComponent(Docu // display: display ? "block" : "none" }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} - onDragOver={this.onDragOver} onDragLeave={this.onDragLeave} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} > {this.contents} diff --git a/src/client/views/nodes/LinkButtonBox.scss b/src/client/views/nodes/LinkButtonBox.scss index 24bfd2c9f..6be2dcf60 100644 --- a/src/client/views/nodes/LinkButtonBox.scss +++ b/src/client/views/nodes/LinkButtonBox.scss @@ -1,18 +1,18 @@ -.linkBox-cont { - width: 200px; - height: 100px; - background-color: black; - text-align: center; - color: white; - padding: 10px; - border-radius: 5px; - position: relative; +// .linkBox-cont { +// width: 200px; +// height: 100px; +// background-color: black; +// text-align: center; +// color: white; +// padding: 10px; +// border-radius: 5px; +// position: relative; - .linkBox-cont-wrapper { - width: calc(100% - 20px); - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - } -} \ No newline at end of file +// .linkBox-cont-wrapper { +// width: calc(100% - 20px); +// position: absolute; +// left: 50%; +// top: 50%; +// transform: translate(-50%, -50%); +// } +// } \ No newline at end of file diff --git a/src/client/views/nodes/LinkButtonBox.tsx b/src/client/views/nodes/LinkButtonBox.tsx index 8a7c1ed8b..440847ead 100644 --- a/src/client/views/nodes/LinkButtonBox.tsx +++ b/src/client/views/nodes/LinkButtonBox.tsx @@ -1,63 +1,63 @@ -import React = require("react"); -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { computed, observable, runInAction } from "mobx"; -import { observer } from "mobx-react"; -import { FieldView, FieldViewProps } from './FieldView'; -import "./LinkButtonBox.scss"; -import { DocumentView } from "./DocumentView"; -import { Doc } from "../../../new_fields/Doc"; -import { LinkButtonField } from "../../../new_fields/LinkButtonField"; -import { Cast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { DocumentManager } from "../../util/DocumentManager"; -import { Id } from "../../../new_fields/FieldSymbols"; - -library.add(faCaretUp); -library.add(faObjectGroup); -library.add(faStickyNote); -library.add(faFilePdf); -library.add(faFilm); - -@observer -export class LinkButtonBox extends React.Component { - public static LayoutString() { return FieldView.LayoutString(LinkButtonBox); } - - followLink = (): void => { - console.log("follow link???"); - let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" })); - let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId); - if (targetView && targetView.props.ContainingCollectionView) { - CollectionDockingView.Instance.AddRightSplit(targetView.props.ContainingCollectionView.props.Document); - } - } - - render() { - - let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" })); - let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId); - - let text = "Could not find link"; - if (targetView) { - let context = targetView.props.ContainingCollectionView ? (" in the context of " + StrCast(targetView.props.ContainingCollectionView.props.Document.title)) : ""; - text = "Link to " + StrCast(targetView.props.Document.title) + context; - } - - let activeDvs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)); - let display = activeDvs.reduce((found, dv) => { - let matchSv = field.data.sourceViewId === StrCast(dv.props.Document[Id]); - let matchTv = field.data.targetViewId === StrCast(dv.props.Document[Id]); - let match = matchSv || matchTv; - return match || found; - }, false); - - return ( -
-
-

{text}

-
-
- ); - } -} \ No newline at end of file +// import React = require("react"); +// import { library } from '@fortawesome/fontawesome-svg-core'; +// import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; +// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +// import { computed, observable, runInAction } from "mobx"; +// import { observer } from "mobx-react"; +// import { FieldView, FieldViewProps } from './FieldView'; +// import "./LinkButtonBox.scss"; +// import { DocumentView } from "./DocumentView"; +// import { Doc } from "../../../new_fields/Doc"; +// import { LinkButtonField } from "../../../new_fields/LinkButtonField"; +// import { Cast, StrCast, BoolCast } from "../../../new_fields/Types"; +// import { CollectionDockingView } from "../collections/CollectionDockingView"; +// import { DocumentManager } from "../../util/DocumentManager"; +// import { Id } from "../../../new_fields/FieldSymbols"; + +// library.add(faCaretUp); +// library.add(faObjectGroup); +// library.add(faStickyNote); +// library.add(faFilePdf); +// library.add(faFilm); + +// @observer +// export class LinkButtonBox extends React.Component { +// public static LayoutString() { return FieldView.LayoutString(LinkButtonBox); } + +// followLink = (): void => { +// console.log("follow link???"); +// let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" })); +// let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId); +// if (targetView && targetView.props.ContainingCollectionView) { +// CollectionDockingView.Instance.AddRightSplit(targetView.props.ContainingCollectionView.props.Document); +// } +// } + +// render() { + +// let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" })); +// let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId); + +// let text = "Could not find link"; +// if (targetView) { +// let context = targetView.props.ContainingCollectionView ? (" in the context of " + StrCast(targetView.props.ContainingCollectionView.props.Document.title)) : ""; +// text = "Link to " + StrCast(targetView.props.Document.title) + context; +// } + +// let activeDvs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)); +// let display = activeDvs.reduce((found, dv) => { +// let matchSv = field.data.sourceViewId === StrCast(dv.props.Document[Id]); +// let matchTv = field.data.targetViewId === StrCast(dv.props.Document[Id]); +// let match = matchSv || matchTv; +// return match || found; +// }, false); + +// return ( +//
+//
+//

{text}

+//
+//
+// ); +// } +// } \ No newline at end of file diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 95199bae2..5f4f7d4f0 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -17,9 +17,8 @@ library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, fa interface GroupTypesDropdownProps { - groupId: string; groupType: string; - setGroup: (groupId: string, group: string) => void; + setGroupType: (group: string) => void; } // this dropdown could be generalized @observer @@ -32,20 +31,20 @@ class GroupTypesDropdown extends React.Component { @action createGroup = (groupType: string): void => { - this.props.setGroup(this.props.groupId, groupType); - LinkManager.Instance.groupMetadataKeys.set(groupType, []); + this.props.setGroupType(groupType); + LinkManager.Instance.addGroupType(groupType); } renderOptions = (): JSX.Element[] | JSX.Element => { if (this._searchTerm === "") return <>; - let allGroupTypes = Array.from(LinkManager.Instance.groupMetadataKeys.keys()); + let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes()); let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()) > -1; let options = groupOptions.map(groupType => { return
{ this.props.setGroup(this.props.groupId, groupType); this.setGroupType(groupType); this.setSearchTerm(""); }}>{groupType}
; + onClick={() => { this.props.setGroupType(groupType); this.setGroupType(groupType); this.setSearchTerm(""); }}>{groupType}
; }); // if search term does not already exist as a group type, give option to create new group type @@ -85,7 +84,7 @@ class LinkMetadataEditor extends React.Component { @action setMetadataKey = (value: string): void => { - let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!); + let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); // don't allow user to create existing key let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase()); @@ -98,12 +97,15 @@ class LinkMetadataEditor extends React.Component { } // set new value for key - let currIndex = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase()); + let currIndex = groupMdKeys.findIndex(key => { + console.log("finding index this", key.toUpperCase(), "that", this._key.toUpperCase()); + return StrCast(key).toUpperCase() === this._key.toUpperCase(); + }); if (currIndex === -1) console.error("LinkMetadataEditor: key was not found"); groupMdKeys[currIndex] = value; this._key = value; - LinkManager.Instance.groupMetadataKeys.set(this.props.groupType, groupMdKeys); + LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, groupMdKeys); } @action @@ -116,13 +118,13 @@ class LinkMetadataEditor extends React.Component { @action removeMetadata = (): void => { - let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!); + let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); let index = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase()); if (index === -1) console.error("LinkMetadataEditor: key was not found"); groupMdKeys.splice(index, 1); - LinkManager.Instance.groupMetadataKeys.set(this.props.groupType, groupMdKeys); + LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, groupMdKeys); this._key = ""; } @@ -137,215 +139,176 @@ class LinkMetadataEditor extends React.Component { } } - -interface LinkEditorProps { +interface LinkGroupEditorProps { sourceDoc: Doc; linkDoc: Doc; - showLinks: () => void; + groupDoc: Doc; } @observer -export class LinkEditor extends React.Component { +export class LinkGroupEditor extends React.Component { - // map of temporary group id to the corresponding group doc - @observable private _groups: Map = new Map(); - - constructor(props: LinkEditorProps) { - super(props); + @action + setGroupType = (groupType: string): void => { + console.log("SET GROUP TYPE TO", groupType); + this.props.groupDoc.type = groupType; + console.log("GROUP TYPE HAS BEEN SET TO ", StrCast(this.props.groupDoc.type)); + } - let groups = new Map(); - let groupList = LinkManager.Instance.getAnchorGroups(props.linkDoc, props.sourceDoc); - groupList.forEach(groupDoc => { - let id = Utils.GenerateGuid(); - groups.set(id, groupDoc); - }); - this._groups = groups; + removeGroupFromLink = (groupType: string): void => { + LinkManager.Instance.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType); } - @action - deleteLink = (): void => { - let index = LinkManager.Instance.allLinks.indexOf(this.props.linkDoc); - LinkManager.Instance.allLinks.splice(index, 1); - this.props.showLinks(); + deleteGroup = (groupType: string): void => { + LinkManager.Instance.deleteGroupType(groupType); } - @action - addGroup = (): void => { - // new group only gets added if there is not already a group with type "new group" - let index = Array.from(this._groups.values()).findIndex(groupDoc => { - return groupDoc.type === "New Group"; - }); - if (index > -1) return; + copyGroup = (groupType: string): void => { + let sourceGroupDoc = this.props.groupDoc; + let sourceMdDoc = Cast(sourceGroupDoc.metadata, Doc, new Doc); - // create new metadata document for group - let mdDoc = Docs.TextDocument(); - mdDoc.proto!.anchor1 = this.props.sourceDoc.title; - mdDoc.proto!.anchor2 = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc).title; + let destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc); + let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); - // create new group document - let groupDoc = Docs.TextDocument(); - groupDoc.proto!.type = "New Group"; - groupDoc.proto!.metadata = mdDoc; + // create new metadata doc with copied kvp + let destMdDoc = new Doc(); + destMdDoc.anchor1 = StrCast(sourceMdDoc.anchor2); + destMdDoc.anchor2 = StrCast(sourceMdDoc.anchor1); + keys.forEach(key => { + let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]); + destMdDoc[key] = val; + }); - this._groups.set(Utils.GenerateGuid(), groupDoc); + // create new group doc with new metadata doc + let destGroupDoc = new Doc(); + destGroupDoc.type = groupType; + destGroupDoc.metadata = destMdDoc; - let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; - LinkManager.Instance.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); + LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, destDoc, destGroupDoc, true); } @action - setGroupType = (groupId: string, groupType: string): void => { - let groupDoc = this._groups.get(groupId); - if (groupDoc) { - groupDoc.proto!.type = groupType; - this._groups.set(groupId, groupDoc); - LinkManager.Instance.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); - } - } - - removeGroupFromLink = (groupId: string, groupType: string): void => { - let groupDoc = this._groups.get(groupId); - if (!groupDoc) console.error("LinkEditor: group not found"); - LinkManager.Instance.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType); - this._groups.delete(groupId); - } - - deleteGroup = (groupId: string, groupType: string): void => { - let groupDoc = this._groups.get(groupId); - if (!groupDoc) console.error("LinkEditor: group not found"); - LinkManager.Instance.deleteGroup(groupType); - this._groups.delete(groupId); + addMetadata = (groupType: string): void => { + let mdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + // only add "new key" if there is no other key with value "new key"; prevents spamming + if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key"); + LinkManager.Instance.setMetadataKeysForGroup(groupType, mdKeys); } - copyGroup = (groupId: string, groupType: string): void => { - let sourceGroupDoc = this._groups.get(groupId); - let sourceMdDoc = Cast(sourceGroupDoc!.metadata, Doc, new Doc); - let destDoc = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc); - let keys = LinkManager.Instance.groupMetadataKeys.get(groupType); - - // create new metadata doc with copied kvp - let destMdDoc = Docs.TextDocument(); - destMdDoc.proto!.anchor1 = StrCast(sourceMdDoc.anchor2); - destMdDoc.proto!.anchor2 = StrCast(sourceMdDoc.anchor1); - if (keys) { - keys.forEach(key => { - let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]); - destMdDoc[key] = val; + renderMetadata = (): JSX.Element[] => { + let metadata: Array = []; + let groupDoc = this.props.groupDoc; + let mdDoc = Cast(groupDoc.metadata, Doc, new Doc); + let groupType = StrCast(groupDoc.type); + let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + if (groupMdKeys) { + groupMdKeys.forEach((key, index) => { + metadata.push( + + ); }); } - - // create new group doc with new metadata doc - let destGroupDoc = Docs.TextDocument(); - destGroupDoc.proto!.type = groupType; - destGroupDoc.proto!.metadata = destMdDoc; - - // if group does not already exist on opposite anchor, create group doc - let index = destGroupList.findIndex(groupDoc => { StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase(); }); - if (index > -1) { - destGroupList[index] = destGroupDoc; - } else { - destGroupList.push(destGroupDoc); - } - - LinkManager.Instance.setAnchorGroups(this.props.linkDoc, destDoc, destGroupList); + return metadata; } - viewGroupAsTable = (groupId: string, groupType: string): JSX.Element => { - let keys = LinkManager.Instance.groupMetadataKeys.get(groupType); - let groupDoc = this._groups.get(groupId); - if (keys && groupDoc) { - let docs: Doc[] = LinkManager.Instance.findAllMetadataDocsInGroup(groupType); - let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys!], docs, { width: 200, height: 200, title: groupType + " table" })); - let ref = React.createRef(); - return
; - } else { - return ; - } + viewGroupAsTable = (groupType: string): JSX.Element => { + let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); + let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys], docs, { width: 500, height: 300, title: groupType + " table" })); + let ref = React.createRef(); + return
; } - renderGroup = (groupId: string, groupDoc: Doc): JSX.Element => { - let type = StrCast(groupDoc.type); - if ((type && LinkManager.Instance.groupMetadataKeys.get(type)) || type === "New Group") { - let buttons; - if (type === "New Group") { - buttons = ( - <> - - - - - - - ); - } else { - buttons = ( - <> - - - - - {this.viewGroupAsTable(groupId, type)} - - ); - } - - return ( -
-
-

type:

- -
- {this.renderMetadata(groupId)} -
- {buttons} -
-
+ render() { + let groupType = StrCast(this.props.groupDoc.type); + // if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") { + let buttons; + if (groupType === "") { + buttons = ( + <> + + + + + + ); } else { - return <>; + buttons = ( + <> + + + + + {this.viewGroupAsTable(groupType)} + + ); } + + return ( +
+
+

type:

+ +
+ {this.renderMetadata()} +
+ {buttons} +
+
+ ); } + // else { + // return <>; + // } + // } +} + +interface LinkEditorProps { + sourceDoc: Doc; + linkDoc: Doc; + showLinks: () => void; +} +@observer +export class LinkEditor extends React.Component { @action - addMetadata = (groupType: string): void => { - console.log("ADD MD"); - let mdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType); - if (mdKeys) { - // only add "new key" if there is no other key with value "new key"; prevents spamming - if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key"); - } else { - mdKeys = ["new key"]; - } - LinkManager.Instance.groupMetadataKeys.set(groupType, mdKeys); + deleteLink = (): void => { + LinkManager.Instance.deleteLink(this.props.linkDoc); + this.props.showLinks(); } - renderMetadata = (groupId: string): JSX.Element[] => { - let metadata: Array = []; - let groupDoc = this._groups.get(groupId); - if (groupDoc) { - let mdDoc = Cast(groupDoc.proto!.metadata, Doc, new Doc); - let groupType = StrCast(groupDoc.proto!.type); - let groupMdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType); - if (groupMdKeys) { - groupMdKeys.forEach((key, index) => { - metadata.push( - - ); - }); - } - } - return metadata; + @action + addGroup = (): void => { + // create new metadata document for group + let mdDoc = new Doc(); + mdDoc.anchor1 = this.props.sourceDoc.title; + mdDoc.anchor2 = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc).title; + + // create new group document + let groupDoc = new Doc(); + groupDoc.type = ""; + groupDoc.metadata = mdDoc; + + LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, this.props.sourceDoc, groupDoc); } render() { - let destination = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + let destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - let groups: Array = []; - this._groups.forEach((groupDoc, groupId) => { - groups.push(this.renderGroup(groupId, groupDoc)); + let groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); + console.log("NUM GROUPS", groupList.length); + let groups = groupList.map(groupDoc => { + return ; }); + + // let groups: Array = []; + // this._groups.forEach((groupDoc, groupId) => { + // groups.push(this.renderGroup(groupId, groupDoc)); + // }); + return (
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index f96c7d2e4..04ca47db3 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -38,7 +38,7 @@ export class LinkMenu extends React.Component { render() { let sourceDoc = this.props.docView.props.Document; - let groups: Map = LinkManager.Instance.findRelatedGroupedLinks(sourceDoc); + let groups: Map = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); if (this._editingLink === undefined) { return (
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index 229143d99..71326f703 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -42,10 +42,10 @@ export class LinkMenuGroup extends React.Component { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - let draggedDocs = this.props.group.map(linkDoc => LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc)); + let draggedDocs = this.props.group.map(linkDoc => LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc)); let dragData = new DragManager.DocumentDragData(draggedDocs); - DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, { + DragManager.StartLinkedDocumentDrag([this._drag.current], this.props.sourceDoc, dragData, e.x, e.y, { handlers: { dragComplete: action(emptyFunction), }, @@ -57,7 +57,7 @@ export class LinkMenuGroup extends React.Component { render() { let groupItems = this.props.group.map(linkDoc => { - let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc); + let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); return ; }); @@ -69,6 +69,6 @@ export class LinkMenuGroup extends React.Component { {groupItems}
- ) + ); } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index 42ef353b7..28694721d 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -53,8 +53,8 @@ export class LinkMenuItem extends React.Component { let mdRows: Array = []; if (groupDoc) { let mdDoc = Cast(groupDoc.metadata, Doc, new Doc); - let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType); - mdRows = keys!.map(key => { + let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + mdRows = keys.map(key => { return (
{key}: {StrCast(mdDoc[key])}
); }); } @@ -88,7 +88,7 @@ export class LinkMenuItem extends React.Component { render() { - let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType); + let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); let canExpand = keys ? keys.length > 0 : false; return ( diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index fda788f2d..9b104184f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -234,23 +234,20 @@ export namespace Doc { export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc { const copy = new Doc; Object.keys(doc).forEach(key => { - console.log(key); const field = doc[key]; if (key === "proto" && copyProto) { - console.log(1); if (field instanceof Doc) { - console.log(2); copy[key] = Doc.MakeCopy(field); } } else { if (field instanceof RefField) { - console.log(3); + console.log("equals field, ref", key); copy[key] = field; } else if (field instanceof ObjectField) { - console.log(4); + console.log("copy field, object", key); copy[key] = ObjectField.MakeCopy(field); } else { - console.log(5); + console.log("equals field", key); copy[key] = field; } } diff --git a/src/new_fields/LinkButtonField.ts b/src/new_fields/LinkButtonField.ts index 92e1ed922..e6d1de749 100644 --- a/src/new_fields/LinkButtonField.ts +++ b/src/new_fields/LinkButtonField.ts @@ -1,35 +1,35 @@ -import { Deserializable } from "../client/util/SerializationHelper"; -import { serializable, primitive, createSimpleSchema, object } from "serializr"; -import { ObjectField } from "./ObjectField"; -import { Copy, ToScriptString } from "./FieldSymbols"; -import { Doc } from "./Doc"; -import { DocumentView } from "../client/views/nodes/DocumentView"; +// import { Deserializable } from "../client/util/SerializationHelper"; +// import { serializable, primitive, createSimpleSchema, object } from "serializr"; +// import { ObjectField } from "./ObjectField"; +// import { Copy, ToScriptString } from "./FieldSymbols"; +// import { Doc } from "./Doc"; +// import { DocumentView } from "../client/views/nodes/DocumentView"; -export type LinkButtonData = { - sourceViewId: string, - targetViewId: string -}; +// export type LinkButtonData = { +// sourceViewId: string, +// targetViewId: string +// }; -const LinkButtonSchema = createSimpleSchema({ - sourceViewId: true, - targetViewId: true -}); +// const LinkButtonSchema = createSimpleSchema({ +// sourceViewId: true, +// targetViewId: true +// }); -@Deserializable("linkButton") -export class LinkButtonField extends ObjectField { - @serializable(object(LinkButtonSchema)) - readonly data: LinkButtonData; +// @Deserializable("linkButton") +// export class LinkButtonField extends ObjectField { +// @serializable(object(LinkButtonSchema)) +// readonly data: LinkButtonData; - constructor(data: LinkButtonData) { - super(); - this.data = data; - } +// constructor(data: LinkButtonData) { +// super(); +// this.data = data; +// } - [Copy]() { - return new LinkButtonField(this.data); - } +// [Copy]() { +// return new LinkButtonField(this.data); +// } - [ToScriptString]() { - return "invalid"; - } -} +// [ToScriptString]() { +// return "invalid"; +// } +// } -- cgit v1.2.3-70-g09d2 From a3c4aa24a9e9074da8f2421954f610c8178e10b1 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 25 Jun 2019 21:28:15 -0400 Subject: link metadata values appear on first load --- src/client/documents/Documents.ts | 19 ------------------- src/client/util/DocumentManager.ts | 8 +++----- src/client/util/DragManager.ts | 2 +- src/client/views/nodes/LinkEditor.tsx | 11 +++++++---- 4 files changed, 11 insertions(+), 29 deletions(-) (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b11b5fdf2..ddbf8f753 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -68,25 +68,7 @@ export interface DocumentOptions { } const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; -// export interface LinkData { -// anchor1: Doc; -// anchor1Page: number; -// anchor1Tags: Array<{ tag: string, name: string, description: string }>; -// anchor2: Doc; -// anchor2Page: number; -// anchor2Tags: Array<{ tag: string, name: string, description: string }>; -// } - -// export interface TagData { -// tag: string; -// name: string; -// description: string; -// } - export namespace DocUtils { - // export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", tags: string = "Default") { - // let protoSrc = source.proto ? source.proto : source; - // let protoTarg = target.proto ? target.proto : target; export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", tags: string = "Default") { if (LinkManager.Instance.doesLinkExist(source, target)) return; let sv = DocumentManager.Instance.getDocumentView(source); @@ -154,7 +136,6 @@ export namespace Docs { audioProto = fields[audioProtoId] as Doc || CreateAudioPrototype(); pdfProto = fields[pdfProtoId] as Doc || CreatePdfPrototype(); iconProto = fields[iconProtoId] as Doc || CreateIconPrototype(); - // linkProto = fields[linkProtoId] as Doc || CreateLinkPrototype(); }); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 767abe63f..d7798ebfd 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -73,6 +73,9 @@ export class DocumentManager { if (doc === toFind) { toReturn.push(view); } else { + // if (Doc.AreProtosEqual(doc, toFind)) { + // toReturn.push(view); + let docSrc = FieldValue(doc.proto); if (docSrc && Object.is(docSrc, toFind)) { toReturn.push(view); @@ -100,11 +103,6 @@ export class DocumentManager { return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]); - // console.log("LINKED DOCUMENT VIEWS"); - // pairs.forEach(p => { - // console.log(StrCast(p.a.Document.title), p.a.props.Document[Id], StrCast(p.b.Document.title), p.b.props.Document[Id]); - // }); - return pairs; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 55d8c570f..27063d1c2 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -230,7 +230,7 @@ export namespace DragManager { (dropData: { [id: string]: any }) => { dropData.droppedDocuments = dragData.draggedDocuments.map(d => { let dv = DocumentManager.Instance.getDocumentView(d); - + // return d; if (dv) { if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { return d; diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 232331204..80eadf668 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -1,8 +1,8 @@ -import { observable, computed, action } from "mobx"; +import { observable, computed, action, trace } from "mobx"; import React = require("react"); import { observer } from "mobx-react"; import './LinkEditor.scss'; -import { StrCast, Cast } from "../../../new_fields/Types"; +import { StrCast, Cast, FieldValue } from "../../../new_fields/Types"; import { Doc } from "../../../new_fields/Doc"; import { LinkManager } from "../../util/LinkManager"; import { Docs } from "../../documents/Documents"; @@ -215,7 +215,10 @@ export class LinkGroupEditor extends React.Component { renderMetadata = (): JSX.Element[] => { let metadata: Array = []; let groupDoc = this.props.groupDoc; - let mdDoc = Cast(groupDoc.metadata, Doc, new Doc); + const mdDoc = FieldValue(Cast(groupDoc.metadata, Doc)); + if (!mdDoc) { + return []; + } let groupType = StrCast(groupDoc.type); let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); @@ -265,7 +268,7 @@ export class LinkGroupEditor extends React.Component { ); } - + trace(); return (
-- cgit v1.2.3-70-g09d2 From 69e37491908b5c189b94f780994c1f142c69be2e Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 26 Jun 2019 14:15:40 -0400 Subject: minor changes --- src/client/util/DocumentManager.ts | 1 - src/client/util/DragManager.ts | 24 +-------- src/client/util/LinkManager.ts | 18 ++++--- src/client/views/nodes/LinkEditor.scss | 12 ++--- src/client/views/nodes/LinkEditor.tsx | 14 ++++-- src/client/views/nodes/LinkMenu.scss | 84 +++++++++++++++++++++++++++++++ src/client/views/nodes/LinkMenu.tsx | 11 ++-- src/client/views/nodes/LinkMenuItem.scss | 86 -------------------------------- src/client/views/nodes/LinkMenuItem.tsx | 5 +- 9 files changed, 117 insertions(+), 138 deletions(-) delete mode 100644 src/client/views/nodes/LinkMenuItem.scss (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index d7798ebfd..877475347 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -68,7 +68,6 @@ export class DocumentManager { //gets document view that is in a freeform canvas collection DocumentManager.Instance.DocumentViews.map(view => { let doc = view.props.Document; - // if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) { if (doc === toFind) { toReturn.push(view); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 27063d1c2..8e6abe18e 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -71,7 +71,6 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n }); } } - // draggedDocs.push(...draggedFromDocs); if (draggedDocs.length) { let moddrag: Doc[] = []; for (const draggedDoc of draggedDocs) { @@ -79,20 +78,6 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n if (doc) moddrag.push(doc); } let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); - // dragData.moveDocument = (document, targetCollection, addDocument) => { - // return false; - // }; - - // runInAction(() => StartDragFunctions.map(func => func())); - // (eles, dragData, downX, downY, options, - // (dropData: { [id: string]: any }) => { - // (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? - // dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : - // dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? - // dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : - // dragData.draggedDocuments - // ); - // }); DragManager.StartLinkedDocumentDrag([dragEle], sourceDoc, dragData, x, y, { handlers: { dragComplete: action(emptyFunction), @@ -230,19 +215,14 @@ export namespace DragManager { (dropData: { [id: string]: any }) => { dropData.droppedDocuments = dragData.draggedDocuments.map(d => { let dv = DocumentManager.Instance.getDocumentView(d); - // return d; if (dv) { if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { return d; } else { - let r = Doc.MakeAlias(d); - // DocUtils.MakeLink(r, sourceDoc); - return r; + return Doc.MakeAlias(d); } } else { - let r = Doc.MakeAlias(d); - // DocUtils.MakeLink(r, sourceDoc); - return r; + return Doc.MakeAlias(d); } }); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 97c816001..1db686751 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -151,7 +151,7 @@ export class LinkManager { // removes group doc of given group type only from given anchor on given link public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) { let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor); - let newGroups = groups.filter(groupDoc => { StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase() }); + let newGroups = groups.filter(groupDoc => StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase()); LinkManager.Instance.setAnchorGroups(linkDoc, anchor, newGroups); } @@ -165,23 +165,25 @@ export class LinkManager { if (groups.length > 0) { groups.forEach(groupDoc => { let groupType = StrCast(groupDoc.type); - let group = anchorGroups.get(groupType); - if (group) group.push(link); - else group = [link]; - anchorGroups.set(groupType, group); + if (groupType === "") { + let group = anchorGroups.get("*"); + anchorGroups.set("*", group ? [...group, link] : [link]); + } else { + let group = anchorGroups.get(groupType); + anchorGroups.set(groupType, group ? [...group, link] : [link]); + } }); } else { // if link is in no groups then put it in default group let group = anchorGroups.get("*"); - if (group) group.push(link); - else group = [link]; - anchorGroups.set("*", group); + anchorGroups.set("*", group ? [...group, link] : [link]); } }); return anchorGroups; } + // gets a list of strings representing the keys of the metadata associated with the given group type public getMetadataKeysInGroup(groupType: string): string[] { if (LinkManager.Instance.LinkManagerDoc) { return LinkManager.Instance.LinkManagerDoc[groupType] ? Cast(LinkManager.Instance.LinkManagerDoc[groupType], listSpec("string"), []) : []; diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 2602b8816..1424d7633 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -10,18 +10,15 @@ margin-bottom: 6px; } -.linKEditor-info { +.linkEditor-info { border-bottom: 0.5px solid $light-color-secondary; padding-bottom: 6px; margin-bottom: 6px; display: flex; justify-content: space-between; - .linkEditor-delete { - width: 20px; - height: 20px; - margin-left: 6px; - padding: 0; + .linkEditor-linkedTo { + width: calc(100% - 26px); } } @@ -105,8 +102,7 @@ cursor: pointer; &:hover { - background-color: $intermediate-color; - font-weight: bold; + background-color: lightgray; } } } diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 87ebeefdb..51efcc36d 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -11,7 +11,6 @@ import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTim import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SetupDrag } from "../../util/DragManager"; -import { anchorPoints, Flyout } from "../DocumentDecorations"; library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); @@ -35,6 +34,11 @@ class GroupTypesDropdown extends React.Component { LinkManager.Instance.addGroupType(groupType); } + onChange = (val: string): void => { + this.setSearchTerm(val); + this.setGroupType(val); + } + renderOptions = (): JSX.Element[] | JSX.Element => { if (this._searchTerm === "") return <>; @@ -59,12 +63,12 @@ class GroupTypesDropdown extends React.Component { render() { return (
- { this.setSearchTerm(e.target.value); this.setGroupType(e.target.value); }}> + this.onChange(e.target.value)}>
{this.renderOptions()}
-
+
); } } @@ -326,7 +330,7 @@ export class LinkEditor extends React.Component {

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

- +
Relationships: diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index 1dd933c32..429977326 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -46,5 +46,89 @@ } } +.linkMenu-item { + // border-top: 0.5px solid $main-accent; + position: relative; + display: flex; + font-size: 12px; + + + .link-name { + position: relative; + + p { + padding: 4px 6px; + line-height: 12px; + border-radius: 5px; + overflow-wrap: break-word; + } + } + + .linkMenu-item-content { + width: 100%; + } + + .link-metadata { + padding: 0 10px 0 16px; + margin-bottom: 4px; + color: $main-accent; + font-style: italic; + font-size: 10.5px; + } + + &:hover { + .linkMenu-item-buttons { + display: flex; + } + .linkMenu-item-content { + &.expand-two p { + width: calc(100% - 52px); + background-color: lightgray; + } + &.expand-three p { + width: calc(100% - 84px); + background-color: lightgray; + } + } + } +} + +.linkMenu-item-buttons { + display: none; + position: absolute; + top: 50%; + right: 0; + transform: translateY(-50%); + + .button { + width: 20px; + height: 20px; + margin: 0; + margin-right: 6px; + border-radius: 50%; + cursor: pointer; + pointer-events: auto; + background-color: $dark-color; + color: $light-color; + font-size: 65%; + transition: transform 0.2s; + text-align: center; + position: relative; + + .fa-icon { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + + &:last-child { + margin-right: 0; + } + &:hover { + background: $main-accent; + } + } +} diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 04ca47db3..8ef899cfc 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -1,15 +1,11 @@ import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { DocumentView } from "./DocumentView"; -import { LinkMenuItem } from "./LinkMenuItem"; import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); -import { Doc, DocListCast } from "../../../new_fields/Doc"; -import { Id } from "../../../new_fields/FieldSymbols"; +import { Doc } from "../../../new_fields/Doc"; import { LinkManager } from "../../util/LinkManager"; -import { DragLinksAsDocuments, DragManager } from "../../util/DragManager"; -import { emptyFunction } from "../../../Utils"; import { LinkMenuGroup } from "./LinkMenuGroup"; interface Props { @@ -22,6 +18,11 @@ export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; + @action + componentWillReceiveProps() { + this._editingLink = undefined; + } + renderAllGroups = (groups: Map>): Array => { let linkItems: Array = []; groups.forEach((group, groupType) => { diff --git a/src/client/views/nodes/LinkMenuItem.scss b/src/client/views/nodes/LinkMenuItem.scss deleted file mode 100644 index 175a93cb2..000000000 --- a/src/client/views/nodes/LinkMenuItem.scss +++ /dev/null @@ -1,86 +0,0 @@ -@import "../globalCssVariables"; - -.linkMenu-item { - // border-top: 0.5px solid $main-accent; - position: relative; - display: flex; - font-size: 12px; - - - .link-name { - position: relative; - - p { - padding: 4px 6px; - line-height: 12px; - border-radius: 5px; - overflow-wrap: break-word; - } - } - - .linkMenu-item-content { - width: 100%; - } - - .link-metadata { - padding: 0 10px 0 16px; - margin-bottom: 4px; - color: $main-accent; - font-style: italic; - font-size: 10.5px; - } - - &:hover { - .linkMenu-item-buttons { - display: flex; - } - .linkMenu-item-content { - &.expand-two p { - width: calc(100% - 52px); - background-color: lightgray; - } - &.expand-three p { - width: calc(100% - 84px); - background-color: lightgray; - } - } - } -} - -.linkMenu-item-buttons { - display: none; - position: absolute; - top: 50%; - right: 0; - transform: translateY(-50%); - - .button { - width: 20px; - height: 20px; - margin: 0; - margin-right: 6px; - border-radius: 50%; - cursor: pointer; - pointer-events: auto; - background-color: $dark-color; - color: $light-color; - font-size: 65%; - transition: transform 0.2s; - text-align: center; - position: relative; - - .fa-icon { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - - &:last-child { - margin-right: 0; - } - &:hover { - background: $main-accent; - } - } -} \ No newline at end of file diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index 28694721d..486e3dc9b 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -4,14 +4,13 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observer } from "mobx-react"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; -import './LinkMenuItem.scss'; +import './LinkMenu.scss'; import React = require("react"); import { Doc } from '../../../new_fields/Doc'; import { StrCast, Cast } from '../../../new_fields/Types'; import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; -import { DragLinksAsDocuments, DragLinkAsDocument } from '../../util/DragManager'; -import { SelectionManager } from '../../util/SelectionManager'; +import { DragLinkAsDocument } from '../../util/DragManager'; import { CollectionDockingView } from '../collections/CollectionDockingView'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); -- cgit v1.2.3-70-g09d2 From 681ba524496d40aecb832fc79d68d7695435aed8 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 26 Jun 2019 16:05:24 -0400 Subject: fixed link alias dragging --- src/client/util/DocumentManager.ts | 6 +- src/client/util/DragManager.ts | 25 +- src/client/views/nodes/LinkMenu.scss | 5 +- src/client/views/nodes/LinkMenu.tsx | 2 +- src/client/views/nodes/LinkMenuGroup.tsx | 7 +- ...357\200\277 1 \357\200\272 0], targetContext);" | 792 +++++++++++++++++++++ 6 files changed, 816 insertions(+), 21 deletions(-) create mode 100644 "tance.jumpToDocument(linkedFwdDocs[altKey \357\200\277 1 \357\200\272 0], ctrlKey, false, document =\357\200\276 this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey \357\200\277 1 \357\200\272 0], targetContext);" (limited to 'src/client/util/DocumentManager.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 877475347..fed30bbdc 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -72,11 +72,7 @@ export class DocumentManager { if (doc === toFind) { toReturn.push(view); } else { - // if (Doc.AreProtosEqual(doc, toFind)) { - // toReturn.push(view); - - let docSrc = FieldValue(doc.proto); - if (docSrc && Object.is(docSrc, toFind)) { + if (Doc.AreProtosEqual(doc, toFind)) { toReturn.push(view); } } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 8e6abe18e..5c75c8fe5 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -9,6 +9,7 @@ import { URLField } from "../../new_fields/URLField"; import { SelectionManager } from "./SelectionManager"; import { Docs, DocUtils } from "../documents/Documents"; import { DocumentManager } from "./DocumentManager"; +import { Id } from "../../new_fields/FieldSymbols"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { @@ -213,19 +214,25 @@ export namespace DragManager { runInAction(() => StartDragFunctions.map(func => func())); StartDrag(eles, dragData, downX, downY, options, (dropData: { [id: string]: any }) => { - dropData.droppedDocuments = dragData.draggedDocuments.map(d => { - let dv = DocumentManager.Instance.getDocumentView(d); - if (dv) { - if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { - return d; + // dropData.droppedDocuments = + console.log(dragData.draggedDocuments.length); + let droppedDocuments: Doc[] = dragData.draggedDocuments.reduce((droppedDocs: Doc[], d) => { + let dvs = DocumentManager.Instance.getDocumentViews(d); + console.log(StrCast(d.title), dvs.length); + + if (dvs.length) { + let inContext = dvs.filter(dv => dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView); + if (inContext.length) { + inContext.forEach(dv => droppedDocs.push(dv.props.Document)); } else { - return Doc.MakeAlias(d); + droppedDocs.push(Doc.MakeAlias(d)); } } else { - return Doc.MakeAlias(d); + droppedDocs.push(Doc.MakeAlias(d)); } - }); - + return droppedDocs; + }, []); + dropData.droppedDocuments = droppedDocuments; }); } diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index 7cc11172b..a4018bd2d 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -25,6 +25,8 @@ &:hover { p { background-color: lightgray; + } + p.expand-one { width: calc(100% - 26px); } .linkEditor-tableButton { @@ -131,8 +133,5 @@ } } -.linkEditor-clearButton { - float: right; -} diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 71384c368..68fde17a0 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -11,7 +11,7 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -library.add(faTrash) +library.add(faTrash); interface Props { docView: DocumentView; diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index 732e76997..f4e0b8931 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -79,13 +79,14 @@ export class LinkMenuGroup extends React.Component { return (
-

{this.props.groupType}:

- {this.viewGroupAsTable(this.props.groupType)} +

{this.props.groupType}:

+ {this.props.groupType === "*" || this.props.groupType === "" ? <> : this.viewGroupAsTable(this.props.groupType)}
{groupItems}
-
+
); } } \ No newline at end of file diff --git "a/tance.jumpToDocument(linkedFwdDocs[altKey \357\200\277 1 \357\200\272 0], ctrlKey, false, document =\357\200\276 this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey \357\200\277 1 \357\200\272 0], targetContext);" "b/tance.jumpToDocument(linkedFwdDocs[altKey \357\200\277 1 \357\200\272 0], ctrlKey, false, document =\357\200\276 this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey \357\200\277 1 \357\200\272 0], targetContext);" new file mode 100644 index 000000000..0aa3ad47b --- /dev/null +++ "b/tance.jumpToDocument(linkedFwdDocs[altKey \357\200\277 1 \357\200\272 0], ctrlKey, false, document =\357\200\276 this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey \357\200\277 1 \357\200\272 0], targetContext);" @@ -0,0 +1,792 @@ +commit cc1f3b32d60786b56280a8b3c00059aa7823af89 +Merge: a81677c deb8576 +Author: Fawn +Date: Wed Jun 26 14:54:46 2019 -0400 + + merge + +commit a81677c7dffafa5134d4c5cbe893f7a886eaab63 +Author: Fawn +Date: Wed Jun 26 14:48:16 2019 -0400 + + can clear links on a doc + +commit 69e37491908b5c189b94f780994c1f142c69be2e +Author: Fawn +Date: Wed Jun 26 14:15:40 2019 -0400 + + minor changes + +commit deb85766ac5648cc8e3ab4bf9d182ac5bbbbe144 +Merge: 219cabb 5e47775 +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Wed Jun 26 12:51:18 2019 -0400 + + Merge pull request #170 from browngraphicslab/presentation-selection-mohammad + + Presentation selection mohammad + +commit 5e477755b392128ab8b39c082f16dd67708be0d2 +Merge: 444f970 6d1f161 +Author: Sam Wilkins +Date: Wed Jun 26 12:48:45 2019 -0400 + + Merge branch 'presentation-selection-mohammad' of https://github.com/browngraphicslab/Dash-Web into presentation-selection-mohammad + +commit 444f970365a4280376e929e78c16090f6ae92739 +Merge: 64ffa0a 219cabb +Author: Sam Wilkins +Date: Wed Jun 26 12:48:40 2019 -0400 + + merged with master + +commit 6d1f161de3c27ec07673b5e48a915961177b57b6 +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Wed Jun 26 12:39:54 2019 -0400 + + long line wrap + +commit f0632e4f6b608d05ef6d9f77d93da259c58c1e8d +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Wed Jun 26 12:33:16 2019 -0400 + + long line wrap + +commit 0d5e2537520ca1e6a6b52f4d0f03aa2bcfc6c5c6 +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Wed Jun 26 12:30:16 2019 -0400 + + cleanup + +commit 8954bac59b50aa3618625379a17dbefe9aceca72 +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Wed Jun 26 12:29:07 2019 -0400 + + removed console.logs + +commit d0ff42632f8a155303e11945a1a974a15052f0db +Author: Fawn +Date: Wed Jun 26 11:40:36 2019 -0400 + + link menu styling + +commit a3c4aa24a9e9074da8f2421954f610c8178e10b1 +Author: Fawn +Date: Tue Jun 25 21:28:15 2019 -0400 + + link metadata values appear on first load + +commit ca8a78de9957ad27d345ad51fdaee9dae3f096bd +Author: Fawn +Date: Tue Jun 25 20:44:34 2019 -0400 + + can't link to containing collection + +commit 2d300b0cd3d02c900865c61eacd539efed5289e6 +Author: Fawn +Date: Tue Jun 25 20:18:14 2019 -0400 + + fixed link metadata rendering bug + +commit 2a698e88da5ef0a9fee1ff4ee69746f1242798c9 +Author: Fawn +Date: Tue Jun 25 18:32:17 2019 -0400 + + fixed render links in treeview + +commit 7abe170ce5bd0c415e23456eb2bed26e8fdee7aa +Merge: 41cf1e8 219cabb +Author: Fawn +Date: Tue Jun 25 18:23:26 2019 -0400 + + merge + +commit 41cf1e8536964764f18ab752140e484e36cbe464 +Author: Fawn +Date: Tue Jun 25 17:09:36 2019 -0400 + + links can save + +commit 64ffa0accfc872c81035079527952aabaf56c6f6 +Author: Mohammad Amoush +Date: Tue Jun 25 13:16:45 2019 -0400 + + Small Css Fix On weight + +commit 219cabb3fe42ab199550efc3423b7aaed4e1ee93 +Author: Tyler Schicke +Date: Mon Jun 24 22:45:19 2019 -0400 + + Switched shift drag of tabs to normal drag and added drag target for document drag + +commit d475b19e9ba7bc8870ec7bc1e10b5cc88decea0b +Author: Tyler Schicke +Date: Mon Jun 24 15:56:42 2019 -0400 + + fixed crash + +commit 522970375fe0227f9221a7e8be02875afd74ca63 +Author: Fawn +Date: Mon Jun 24 14:01:29 2019 -0400 + + link menu styling + +commit addf0e443f64951a437701f0d5a087c1d5968faf +Merge: c9f77d5 d01039b +Author: tschicke-brown +Date: Mon Jun 24 13:57:02 2019 -0400 + + Merge pull request #167 from browngraphicslab/schema_fixes + + Schema and scripting fixes + +commit d01039b10f0ebd328224c0b1a190b0f884a7c727 +Merge: 6abf829 c9f77d5 +Author: Tyler Schicke +Date: Mon Jun 24 13:56:30 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into schema_fixes + +commit c9f77d5aab98e6e7865cdcad957d5c937631775d +Author: Tyler Schicke +Date: Mon Jun 24 13:41:39 2019 -0400 + + Added ReadOnly mode for docs and changed computed values a bit + +commit e18662f2fa9e1d3dd1b0eb3b5531092258d05972 +Author: Mohammad Amoush +Date: Mon Jun 24 12:42:44 2019 -0400 + + Refactoring + +commit 52051829373bc4acfe9d705b64c30e3fddebf439 +Author: Tyler Schicke +Date: Mon Jun 24 10:49:05 2019 -0400 + + Fixed image size stuff + +commit ac781d2fb714ca26fb364d00d5aeb7a20b008655 +Author: Tyler Schicke +Date: Mon Jun 24 10:26:57 2019 -0400 + + Changed how zooming works + +commit 6e5cd0e991e2e6d7ae8de1d73ff273ba0737355c +Author: Tyler Schicke +Date: Sun Jun 23 17:23:33 2019 -0400 + + Fixed shift dragging with no open panes + +commit 32ef8d83d5829e2faadbebaf6f9b694df5d7ea02 +Author: Fawn +Date: Fri Jun 21 17:41:20 2019 -0400 + + link menu styling + +commit 7962aff8431b692af5229cd8e6c390bbe1110336 +Author: Fawn +Date: Fri Jun 21 16:29:31 2019 -0400 + + link menu styling + +commit a4b34adcb34184728be0b69b33a561f6d10f0a98 +Author: Fawn +Date: Fri Jun 21 16:27:03 2019 -0400 + + can drag just a group of links on a doc + +commit e1f5f341854944c533efdb7d36306edd1e1dc747 +Author: Mohammad Amoush +Date: Fri Jun 21 14:53:08 2019 -0400 + + Some More documentation + +commit 542f25d4af36cf0948696d45afba2e9e19f5bc37 +Author: Mohammad Amoush +Date: Fri Jun 21 14:47:11 2019 -0400 + + Redo Grouping Fixed + +commit 60f9122ea31d660d60d5429890c4eb0ef6d8613b +Author: Fawn +Date: Fri Jun 21 13:41:25 2019 -0400 + + following link without viewdoc opens it to right + +commit d78c651322ad228152b862eaa378946fe65cc9f9 +Author: Fawn +Date: Fri Jun 21 13:32:23 2019 -0400 + + dragged links from menu are aliases + +commit 179afa6e80631fcb8899408c3961bf1757e5b19b +Merge: ca5e29f a40e7bb +Author: Bob Zeleznik +Date: Thu Jun 20 22:23:40 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit ca5e29fdc7c238274eaf90682a8fa2ddc90e4e17 +Author: Bob Zeleznik +Date: Thu Jun 20 22:22:57 2019 -0400 + + fix to open on right, fix to image drag fro web, and layout fixes for stacking view multi-column + +commit a40e7bb5e9d1256002083d7e3f3c4db60cd8e9df +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Thu Jun 20 19:41:39 2019 -0400 + + Fixed missed pointer up event + +commit f4b75a7c921181faeeee04fbd57cd24fbd57523e +Author: Mohammad Amoush +Date: Thu Jun 20 19:16:42 2019 -0400 + + Undo/Redo First Version + +commit b1a2871fcca57ce934b8613b315a08eede188669 +Author: Fawn +Date: Thu Jun 20 19:03:16 2019 -0400 + + link menu styling + +commit f2b54dc49205f8ea8944e26e43662a0c8dd08ed0 +Merge: 0cab79a 7d0f6c1 +Author: Tyler Schicke +Date: Thu Jun 20 18:36:04 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web + +commit 0cab79a50719719e1dade40520a6967f7aa8f951 +Author: Tyler Schicke +Date: Thu Jun 20 18:35:45 2019 -0400 + + Added debug and release modes to server and client + +commit fbfe9faca199b6dedd6844f1fa20cc02060a3c5a +Author: Fawn +Date: Thu Jun 20 18:25:49 2019 -0400 + + can see what docs are linked to in treeview: + +commit 7d0f6c18489f7155818611721985d9610b08d8e7 +Merge: d2dfc0f 46a2a9e +Author: yipstanley +Date: Thu Jun 20 17:50:46 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 1f172642d12c4669960b8526324e4bd034994be4 +Author: Tyler Schicke +Date: Thu Jun 20 17:44:24 2019 -0400 + + Added arrange documents in grid command + +commit d2dfc0f9d35f0084a7c0dea73215f5d21055f2f3 +Author: yipstanley +Date: Thu Jun 20 17:17:14 2019 -0400 + + pdf page sizes loading error + +commit e6ebed17e6ddb2ccee81d65fcb451a9b54302762 +Author: Fawn +Date: Thu Jun 20 17:12:48 2019 -0400 + + links can be made from freeform view to treeview + +commit 46a2a9e1f10b63feeb21a1e186daeaef2ccbcda4 +Merge: a39b285 a5dc0e0 +Author: bob +Date: Thu Jun 20 17:11:29 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit a39b2854b848006c19460685d7bf4005a9f650ae +Author: bob +Date: Thu Jun 20 17:09:50 2019 -0400 + + moved AddDocToList to Doc utils + +commit a5dc0e04add05f2f5bf1e17f1ac0a5e0aba1ea41 +Author: Tyler Schicke +Date: Thu Jun 20 16:27:44 2019 -0400 + + Added hidden flag to documents + +commit e88538bb8af2ba648da2326d0f6edd3e0186766e +Author: Mohammad Amoush +Date: Thu Jun 20 15:45:07 2019 -0400 + + Title changing to presentations added + +commit 9b3e80def0be6c09c31b5176817a54323d217d81 +Author: Tyler Schicke +Date: Thu Jun 20 15:06:41 2019 -0400 + + Handled more events in editable view + +commit 1f24c5010a1cf6365265ea1f02327bb81a98134a +Author: Tyler Schicke +Date: Thu Jun 20 14:54:55 2019 -0400 + + Doc.GetProto change and swapped KVP syntax + +commit 4360287e6cafcb59af1ae62fc31ddc161bcf2e51 +Author: Fawn +Date: Thu Jun 20 12:56:13 2019 -0400 + + styling of link proxy + +commit 711abbeba69e4d9afc634b8edf019b12b6dff915 +Author: Mohammad Amoush +Date: Thu Jun 20 12:54:41 2019 -0400 + + Documentation and reset Presentation at removal fixed + +commit a0246ef84396545f79fc4a8b21de1a56cbf06aca +Author: Fawn +Date: Thu Jun 20 11:34:28 2019 -0400 + + merge + +commit 8dbfb3029a99eaf37a5234e9d9e33cc64f779b03 +Merge: af8e5cf e9d62f4 +Author: Tyler Schicke +Date: Thu Jun 20 11:33:01 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web + +commit af8e5cf1bfbfa2d57b4fd89c72306a71d8cabe1d +Author: Tyler Schicke +Date: Thu Jun 20 11:32:54 2019 -0400 + + Fixed context menu search + +commit cd2db5bf11fb89e3cd7016f7f798d65698c74c5e +Merge: 73f0378 e9d62f4 +Author: Fawn +Date: Thu Jun 20 11:31:15 2019 -0400 + + merge + +commit 73f03785f938542a91b28b35043f2feda2bc1432 +Author: Fawn +Date: Thu Jun 20 11:26:33 2019 -0400 + + merge + +commit e9d62f4ca0dbeb57e46239047041a8a04da7b504 +Author: bob +Date: Thu Jun 20 11:26:16 2019 -0400 + + changed color picker. fixed delting selected docs. fixed scaling items in nested panels. + +commit a5478b2d4cc3b66c6b58471cbb05c623d0109724 +Author: Tyler Schicke +Date: Thu Jun 20 10:04:51 2019 -0400 + + "Fixed" search + +commit 01aee875e626c695fe208addaaa6f58aad387dd6 +Author: Tyler Schicke +Date: Thu Jun 20 10:02:08 2019 -0400 + + Mostly keep context menu on screen + +commit 38de022621175bda7410df4444fcd2bbee0919cb +Author: Bob Zeleznik +Date: Wed Jun 19 23:43:47 2019 -0400 + + slight tweaks. + +commit 9e55bfaad39aa47ab0594c6af7f1aa68e2a8db7a +Merge: 118ecb1 827c589 +Author: Bob Zeleznik +Date: Wed Jun 19 22:40:57 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 118ecb14ce519bcbade12b3d52e11b22fcc371b3 +Author: Bob Zeleznik +Date: Wed Jun 19 22:40:54 2019 -0400 + + cleaned up and enhanced tree view + +commit c5e401cb0a7fec2279ceecbc8d1429dcdd2f04b9 +Author: Fawn +Date: Wed Jun 19 22:27:21 2019 -0400 + + buttons on cut links functional except for when dragged from link menu + +commit 6fc6054dc7aea144fd967a8cb3fe7d8fe5ec6d6d +Author: Mohammad Amoush +Date: Wed Jun 19 19:13:30 2019 -0400 + + Width of the presentations fixed, removal of presentations option added, backUP group and normal groups updated when a doc is removed from presentation by removing it from both + +commit 827c58950b649629c84211d41fdd4d041287801e +Merge: 05e50f2 96c26c5 +Author: Tyler Schicke +Date: Wed Jun 19 18:49:50 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web + +commit 96c26c57527d443784bde9752551bfa10b3ce4d2 +Author: Bob Zeleznik +Date: Wed Jun 19 18:34:45 2019 -0400 + + removed marquee summarizing icon + +commit 05e50f27a15e8a02ffb27606c51026d1b85bc677 +Author: Tyler Schicke +Date: Wed Jun 19 17:36:52 2019 -0400 + + Added basic keyboard controls to context menu + +commit fa37e023b88127cb8a6b393a848200361a396fb4 +Merge: 565b27c 5b2a498 +Author: Tyler Schicke +Date: Wed Jun 19 16:21:09 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web + +commit 565b27cca8953a60067de367cae4c0a99beb3cab +Author: Tyler Schicke +Date: Wed Jun 19 16:21:03 2019 -0400 + + started adding selection to context menu + +commit 5b2a498aca75bd53ffab61f998218bec546b8154 +Merge: 358437e 39e8a7a +Author: bob +Date: Wed Jun 19 16:17:21 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 358437eeafe42e029ffe27702bde15a3fad54a3b +Author: bob +Date: Wed Jun 19 16:17:18 2019 -0400 + + working version of embedded tree view docs. + +commit 4c1383e47f2203a00bc7f3d73c209f3149d6a772 +Author: Mohammad Amoush +Date: Wed Jun 19 15:53:05 2019 -0400 + + ... + +commit a288a2fd0a30a3a16dd01bc4e12dcf6bc117c766 +Author: Mohammad Amoush +Date: Wed Jun 19 15:25:24 2019 -0400 + + Navigation and Zoom Option For Manual Selection Added and New Presentation TItle Naming Added + + Now, You can manually click on navigate or zoom and navigate to that document if current was their index. A way to manually disregard groups, and just navigate to that doc. + +commit 39e8a7a365442cdc11024c4de8019184fd0057ac +Merge: 5b6f13d 9ab4739 +Author: Stanley Yip <33562077+yipstanley@users.noreply.github.com> +Date: Wed Jun 19 15:05:38 2019 -0400 + + Merge pull request #163 from browngraphicslab/pdf_fixes + + deleting annotations + +commit 5b6f13d64e9e38b94df0ae61ffedcb0b34290045 +Merge: 35e73f3 4ebbdd8 +Author: Tyler Schicke +Date: Wed Jun 19 15:04:46 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web + +commit 35e73f369a2145d8a042e0011a43e71763d57998 +Author: Tyler Schicke +Date: Wed Jun 19 15:02:48 2019 -0400 + + added better search to context menu + +commit 9ab47393a2ce3d174ad3238422c2c310764be9af +Author: yipstanley +Date: Wed Jun 19 14:40:28 2019 -0400 + + interaction improvements with delete button + +commit b9849810231e540a5898a56012abd32c197b23b5 +Author: yipstanley +Date: Wed Jun 19 14:39:15 2019 -0400 + + anna + +commit b960a876d6a31b3eaebb0ac6eca6f191a0d4c900 +Author: yipstanley +Date: Wed Jun 19 14:38:43 2019 -0400 + + oop + +commit 46d57bc21cda4703855b85a4603bd471975d845b +Author: yipstanley +Date: Wed Jun 19 14:25:47 2019 -0400 + + deleting annotations + +commit f362dbfc237536c6c4a8c6d088c3dc818080f7c2 +Author: Fawn +Date: Wed Jun 19 12:50:58 2019 -0400 + + both tail ends of a cut link appear on hover/focus of an anchor + +commit fb62f3b2e39bbe2dd3da5eaffedbaa8e60f06dbb +Author: Mohammad Amoush +Date: Wed Jun 19 12:35:54 2019 -0400 + + Grouping for different presentations fixed + +commit 4ebbdd803cdf83806902509dfa0432ce3a139403 +Merge: 0bb2052 c056ade +Author: Stanley Yip <33562077+yipstanley@users.noreply.github.com> +Date: Wed Jun 19 11:48:16 2019 -0400 + + Merge pull request #162 from browngraphicslab/pdf_fixes + + Pdf fixes + +commit c056adeca11f35972b5f75c6b1cc31292d5765d4 +Author: yipstanley +Date: Wed Jun 19 11:47:20 2019 -0400 + + push + +commit 37f327ab659e6fa1221f9f4ed7649402c5dedc00 +Author: yipstanley +Date: Wed Jun 19 11:24:32 2019 -0400 + + aspect ratio, dragging, and full screen scrolling fixed + +commit 0bb20528c8167b3ba1c4c88d97586d50ae183b4c +Author: bob +Date: Wed Jun 19 10:37:36 2019 -0400 + + added highlight for expanded tree view items + +commit f60398d5db9041e09c809c16a0b885936ac11a3d +Author: bob +Date: Wed Jun 19 10:21:37 2019 -0400 + + fixed multi-column stacking + +commit 0674331f3611d297028526c888c718a75b012e0a +Author: bob +Date: Wed Jun 19 09:36:21 2019 -0400 + + fixed resizing stacking views. changed defaults for new docs in treeView + +commit 1472d2b56aa64896f0a93f172322121d19cd1592 +Author: bob +Date: Wed Jun 19 09:11:35 2019 -0400 + + fixed lint errors. + +commit 8c94bb92b23dea138fa752929b6134e7214dfb60 +Merge: 3b880d7 13e301d +Author: Bob Zeleznik +Date: Tue Jun 18 22:51:48 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 3b880d7b15b7107049ae27601b9f759b17f7fde9 +Author: Bob Zeleznik +Date: Tue Jun 18 22:51:46 2019 -0400 + + added initial keyboard shortcuts for adding and moving docs in TreeView. fixed image drag bug. + +commit 13e301dea2f537b67b338cc6a98d3f3b5a8e1f36 +Author: Tyler Schicke +Date: Tue Jun 18 20:58:32 2019 -0400 + + Fixed linter errors + +commit 464fa03d6ebb2a7aaef1d7622afa3e1e7ee816a3 +Author: Tyler Schicke +Date: Tue Jun 18 20:11:31 2019 -0400 + + Context menu improvements and error fixes + +commit 4ffcff69a2fc767c6a03d46d7296b6a8c7ffd281 +Author: madelinegr +Date: Tue Jun 18 19:13:45 2019 -0400 + + Presentations Listed, Option to Change Added, and + +commit ca126adda9e4def83fb5c2e07e382917ca0b4ee0 +Author: Tyler Schicke +Date: Tue Jun 18 17:24:59 2019 -0400 + + Fixed docking view? + +commit b0ac30172019713e1c75083c1199485d902e0eed +Author: Tyler Schicke +Date: Tue Jun 18 16:37:28 2019 -0400 + + Fixed zoomBasis stuff and added deletion handling for reponse from server + +commit 8e5afb5bbb47324a381b5184254e77eba7bd8536 +Author: Fawn +Date: Tue Jun 18 16:30:24 2019 -0400 + + can click on button link to node in different context than source + +commit 6fcd0d8d6fb1471b8af460f6d80bdf0d0e681566 +Author: Fawn +Date: Tue Jun 18 15:17:27 2019 -0400 + + added button to delete a link + +commit d91e7eec9a62363b383b929166cdf600b124334c +Author: Fawn +Date: Tue Jun 18 15:09:21 2019 -0400 + + links to nodes in different contexts render as a circle + +commit d3cad099d49690810166d0342f7c371bda0f007e +Merge: 04668e2 b1af251 +Author: bob +Date: Tue Jun 18 13:30:55 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 04668e21313f6e62e5ab35ac737fc54191769a5a +Author: bob +Date: Tue Jun 18 13:30:41 2019 -0400 + + fixed cleanup of marquee keyhandler. + +commit b1af251b058743798aa3fa3895d22327c8560dfc +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Tue Jun 18 13:19:50 2019 -0400 + + Added pointer down flag for tab focus + +commit 9544576ec0167d64f564ae4c87d392eba07ff467 +Author: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> +Date: Tue Jun 18 13:18:34 2019 -0400 + + Added tab focusing on hover + +commit 2633f61d311528e62d50d4ff56f5884b3b51ac61 +Author: bob +Date: Tue Jun 18 13:12:15 2019 -0400 + + added undo/redo bindings for app. + +commit 3a25bad918c72f5d6de9a720de9e0d316c00f2fe +Author: bob +Date: Tue Jun 18 13:03:28 2019 -0400 + + fixed issues with expanding text boxes that have a dynamic title + +commit f4fcf306e2579b7479610899a01c06fb157d47de +Author: bob +Date: Tue Jun 18 12:03:14 2019 -0400 + + fixed goldenlayout nesting + +commit 4f0086f6ea948c1c5254db2acc93f6735987daa5 +Merge: 749eef1 d7ebe7b +Author: bob +Date: Tue Jun 18 11:31:49 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 749eef13af1338225b2bec4dbcd7a50a5650d285 +Author: bob +Date: Tue Jun 18 11:31:46 2019 -0400 + + fixed image drag drop when not selected. + +commit d7ebe7b7d19cf7dc797443aa485293670c3ee4e2 +Merge: 66d4cc9 08872de +Author: yipstanley +Date: Tue Jun 18 11:08:44 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 66d4cc94bcc69f590d90dd35823f93b8e2fb90d8 +Author: yipstanley +Date: Tue Jun 18 10:52:10 2019 -0400 + + selection fixes + +commit 08872def596af073c5f14336c8faf07f44561bbc +Merge: 8d00265 c50ba1c +Author: bob +Date: Tue Jun 18 10:28:31 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit 8d0026573ad9a196f864490bcf07c78f54082bad +Author: bob +Date: Tue Jun 18 10:28:29 2019 -0400 + + fixed selection within multicolumn stacking view. added drop of html image selections. + +commit c50ba1c4cc01d5cd085dee0dae6f633164efeb80 +Merge: cc032e2 64e6a94 +Author: yipstanley +Date: Tue Jun 18 10:10:58 2019 -0400 + + Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web + +commit cc032e2f60015728f64f46ef009c9306e36746a0 +Author: yipstanley +Date: Tue Jun 18 10:05:49 2019 -0400 + + fixes + +commit 64e6a941639aab8d7109178aa151a50909547309 +Author: Bob Zeleznik +Date: Tue Jun 18 09:05:41 2019 -0400 + + fixed index out of range + +commit 4b8324fcf44c5d3c3a4b3f6e98a4d1dfce84811b +Author: Bob Zeleznik +Date: Tue Jun 18 08:53:01 2019 -0400 + + removed trace + +commit a3b8a57027d7c45ea19d259e1ec18fa6a8648c24 +Author: Bob Zeleznik +Date: Tue Jun 18 08:49:02 2019 -0400 + + looked like wrong code... + +commit 2f5c38c6a0a5220c2a31931c34d94e199854d703 +Author: Bob Zeleznik +Date: Tue Jun 18 08:36:37 2019 -0400 + + more streamlining + +commit 62c781c0c79ac395c5e117d208a90485ff1ba599 +Author: Bob Zeleznik +Date: Tue Jun 18 02:19:07 2019 -0400 + + faster loading of PDFs + +commit 4dc8c03562a0473becb895824740da487e16e771 +Author: Bob Zeleznik +Date: Tue Jun 18 00:17:58 2019 -0400 + + added dropping of Dash urls from gmail + +commit 9c7ff72a8ad249c05b672a46e3fbbb69ffca3a2a +Merge: 8c64ffd 71b1cfb +Author: Tyler Schicke +Date: Mon Jun 17 23:04:22 2019 -0400 + + Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web + +commit 8c64ffd92e382050bc8727981cf9fb830e4f02a7 +Author: Tyler Schicke +Date: Mon Jun 17 23:04:07 2019 -0400 + + Added share with user functionality -- cgit v1.2.3-70-g09d2