From c541acbdfc7ec66522409beeebce5f33b340273f Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Tue, 4 Jun 2019 14:07:20 -0400 Subject: move computers --- src/client/views/PresentationView.scss | 4 ++++ src/client/views/PresentationView.tsx | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/client/views/PresentationView.scss b/src/client/views/PresentationView.scss index fb4a851c4..97ce80a02 100644 --- a/src/client/views/PresentationView.scss +++ b/src/client/views/PresentationView.scss @@ -53,6 +53,10 @@ float: right; } +.presentation-interaction { + float: left; +} + .presentationView-name { font-size: 15px; display: inline-block; diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 9d5798ff1..b6e0f0889 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -58,6 +58,12 @@ class PresentationViewList extends React.Component { {`${index + 1}. ${title}`} +

+ + + + + ); -- cgit v1.2.3-70-g09d2 From 464096297d34bb824ed665aa50dfb58f268c1d12 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Tue, 4 Jun 2019 20:01:59 -0400 Subject: BUttons in Presentation CSSed and grouping up insertion done, removal almost done --- src/client/views/MainView.tsx | 2 +- src/client/views/PresentationView.scss | 83 --------- src/client/views/PresentationView.tsx | 165 ----------------- src/client/views/nodes/DocumentView.tsx | 2 +- .../views/presentationview/PresentationElement.tsx | 115 ++++++++++++ .../views/presentationview/PresentationView.scss | 88 +++++++++ .../views/presentationview/PresentationView.tsx | 203 +++++++++++++++++++++ 7 files changed, 408 insertions(+), 250 deletions(-) delete mode 100644 src/client/views/PresentationView.scss delete mode 100644 src/client/views/PresentationView.tsx create mode 100644 src/client/views/presentationview/PresentationElement.tsx create mode 100644 src/client/views/presentationview/PresentationView.scss create mode 100644 src/client/views/presentationview/PresentationView.tsx (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a093ffdec..c98e6e8fb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -14,7 +14,7 @@ import { Docs } from '../documents/Documents'; import { SetupDrag, DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; -import { PresentationView } from './PresentationView'; +import { PresentationView } from './presentationview/PresentationView'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { ContextMenu } from './ContextMenu'; import { DocumentDecorations } from './DocumentDecorations'; diff --git a/src/client/views/PresentationView.scss b/src/client/views/PresentationView.scss deleted file mode 100644 index 97ce80a02..000000000 --- a/src/client/views/PresentationView.scss +++ /dev/null @@ -1,83 +0,0 @@ -.presentationView-cont { - position: absolute; - background: white; - z-index: 1; - box-shadow: #AAAAAA .2vw .2vw .4vw; - right: 0; - top: 0; - bottom: 0; -} - -.presentationView-item { - padding: 10px; - display: inline-block; - width: 100%; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all .1s; -} - -.presentationView-listCont { - padding-left: 10px; - padding-right: 10px; -} - -.presentationView-item:hover { - transition: all .1s; - background: #AAAAAA -} - -.presentationView-selected { - background: gray; -} - -.presentationView-heading { - background: lightseagreen; - padding: 10px; - display: inline-block; - width: 100%; -} - -.presentationView-title { - padding-top: 3px; - padding-bottom: 3px; - font-size: 25px; - display: inline-block; -} - -.presentation-icon { - float: right; -} - -.presentation-interaction { - float: left; -} - -.presentationView-name { - font-size: 15px; - display: inline-block; -} - -.presentation-button { - margin-right: 12.5%; - margin-left: 12.5%; - width: 25%; -} - -.presentation-buttons { - padding: 10px; -} - -.presentation-next:hover { - transition: all .1s; - background: #AAAAAA -} - -.presentation-back:hover { - transition: all .1s; - background: #AAAAAA -} \ No newline at end of file diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx deleted file mode 100644 index b6e0f0889..000000000 --- a/src/client/views/PresentationView.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, runInAction, reaction } from "mobx"; -import "./PresentationView.scss"; -import { DocumentManager } from "../util/DocumentManager"; -import { Utils } from "../../Utils"; -import { Doc, DocListCast, DocListCastAsync } from "../../new_fields/Doc"; -import { listSpec } from "../../new_fields/Schema"; -import { Cast, NumCast, FieldValue, PromiseValue, StrCast, BoolCast } from "../../new_fields/Types"; -import { Id } from "../../new_fields/FieldSymbols"; -import { List } from "../../new_fields/List"; -import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; - -export interface PresViewProps { - Document: Doc; -} - -interface PresListProps extends PresViewProps { - deleteDocument(index: number): void; - gotoDocument(index: number): void; -} - - -@observer -/** - * Component that takes in a document prop and a boolean whether it's collapsed or not. - */ -class PresentationViewList extends React.Component { - - - /** - * Renders a single child document. It will just append a list element. - * @param document The document to render. - */ - renderChild = (document: Doc, index: number) => { - let title = document.title; - - //to get currently selected presentation doc - let selected = NumCast(this.props.Document.selectedDoc, 0); - - let className = "presentationView-item"; - if (selected === index) { - //this doc is selected - className += " presentationView-selected"; - } - let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } - let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } - return ( -
{ this.props.gotoDocument(index); e.stopPropagation(); }}> - - {`${index + 1}. ${title}`} - - -

- - - - - -
- ); - - } - - render() { - const children = DocListCast(this.props.Document.data); - - return ( -
- {children.map(this.renderChild)} -
- ); - } -} - - -@observer -export class PresentationView extends React.Component { - public static Instance: PresentationView; - - //observable means render is re-called every time variable is changed - @observable - collapsed: boolean = false; - closePresentation = action(() => this.props.Document.width = 0); - next = () => { - const current = NumCast(this.props.Document.selectedDoc); - this.gotoDocument(current + 1); - - } - back = () => { - const current = NumCast(this.props.Document.selectedDoc); - this.gotoDocument(current - 1); - } - - @action - public RemoveDoc = (index: number) => { - const value = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); - if (value) { - value.splice(index, 1); - } - } - - public gotoDocument = async (index: number) => { - const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); - if (!list) { - return; - } - if (index < 0 || index >= list.length) { - return; - } - - this.props.Document.selectedDoc = index; - const doc = await list[index]; - DocumentManager.Instance.jumpToDocument(doc); - } - - //initilize class variables - constructor(props: PresViewProps) { - super(props); - PresentationView.Instance = this; - } - - /** - * Adds a document to the presentation view - **/ - @action - public PinDoc(doc: Doc) { - //add this new doc to props.Document - const data = Cast(this.props.Document.data, listSpec(Doc)); - if (data) { - data.push(doc); - } else { - this.props.Document.data = new List([doc]); - } - - this.props.Document.width = 300; - } - - render() { - let titleStr = StrCast(this.props.Document.title); - let width = NumCast(this.props.Document.width); - - //TODO: next and back should be icons - return ( -
-
-
{titleStr}
- -
-
- - -
- -
- ); - } -} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7750b9173..984cac9b9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -23,7 +23,7 @@ import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { DocComponent } from "../DocComponent"; -import { PresentationView } from "../PresentationView"; +import { PresentationView } from "../presentationview/PresentationView"; import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx new file mode 100644 index 000000000..02d97ee4d --- /dev/null +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -0,0 +1,115 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { Doc } from "../../../new_fields/Doc"; +import { NumCast, BoolCast } from "../../../new_fields/Types"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { observable, action } from "mobx"; +import "./PresentationView.scss"; + + + +interface PresentationElementProps { + mainDocument: Doc; + document: Doc; + index: number; + deleteDocument(index: number): void; + gotoDocument(index: number): void; + groupedMembers: [Doc[]]; + allListElements: Doc[]; + +} + +@observer +export default class PresentationElement extends React.Component { + + @observable selectedButtons: boolean[] = new Array(6); + + + @action + onGroupClick = (document: Doc, index: number, buttonStatus: boolean[] | boolean) => { + let p = this.props; + if (Array.isArray(buttonStatus)) { + if (buttonStatus[5]) { + buttonStatus[5] = false; + console.log("Reached!"); + if (index >= 1) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); + } + } + } else { + buttonStatus[5] = true; + if (index >= 1) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1].push(doc)); + } + p.groupedMembers[index - 1].push(document); + //this.onGroupClick() + } + } + } else { + if (!buttonStatus) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); + } + } else { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => { if (!p.groupedMembers[index - 1].includes(doc)) { p.groupedMembers[index - 1].push(doc); } }); + } + if (!p.groupedMembers[index - 1].includes(document)) { + p.groupedMembers[index - 1].push(document); + } + } + } + if (index >= 2) { + this.onGroupClick(p.allListElements[index - 1], index - 1, p.groupedMembers[index - 2].length !== 0); + } + + p.groupedMembers.forEach((docArray: Doc[], index: number) => console.log("Index: ", index, " size: ", docArray.length)); + console.log("Group Size: ", p.groupedMembers[index - 1].length); + } + + + + render() { + let p = this.props; + let title = p.document.title; + + //to get currently selected presentation doc + let selected = NumCast(p.mainDocument.selectedDoc, 0); + + let className = "presentationView-item"; + if (selected === p.index) { + //this doc is selected + className += " presentationView-selected"; + } + let onEnter = (e: React.PointerEvent) => { p.document.libraryBrush = true; } + let onLeave = (e: React.PointerEvent) => { p.document.libraryBrush = false; } + return ( +
{ p.gotoDocument(p.index); e.stopPropagation(); }}> + + {`${p.index + 1}. ${title}`} + + +

+ + + + + + + +
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/presentationview/PresentationView.scss b/src/client/views/presentationview/PresentationView.scss new file mode 100644 index 000000000..07c3e69fd --- /dev/null +++ b/src/client/views/presentationview/PresentationView.scss @@ -0,0 +1,88 @@ +.presentationView-cont { + position: absolute; + background: white; + z-index: 1; + box-shadow: #AAAAAA .2vw .2vw .4vw; + right: 0; + top: 0; + bottom: 0; +} + +.presentationView-item { + padding: 10px; + display: inline-block; + width: 100%; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all .1s; +} + +.presentationView-listCont { + padding-left: 10px; + padding-right: 10px; +} + +.presentationView-item:hover { + transition: all .1s; + background: #AAAAAA +} + +.presentationView-selected { + background: gray; +} + +.presentationView-heading { + background: lightseagreen; + padding: 10px; + display: inline-block; + width: 100%; +} + +.presentationView-title { + padding-top: 3px; + padding-bottom: 3px; + font-size: 25px; + display: inline-block; +} + +.presentation-icon { + float: right; +} + +.presentation-interaction { + float: left; +} + +.presentation-interaction-selected { + background: #505050; + float: left; +} + +.presentationView-name { + font-size: 15px; + display: inline-block; +} + +.presentation-button { + margin-right: 12.5%; + margin-left: 12.5%; + width: 25%; +} + +.presentation-buttons { + padding: 10px; +} + +.presentation-next:hover { + transition: all .1s; + background: #AAAAAA +} + +.presentation-back:hover { + transition: all .1s; + background: #AAAAAA +} \ No newline at end of file diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx new file mode 100644 index 000000000..5a7d38e28 --- /dev/null +++ b/src/client/views/presentationview/PresentationView.tsx @@ -0,0 +1,203 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { observable, action, runInAction, reaction } from "mobx"; +import "./PresentationView.scss"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Utils } from "../../../Utils"; +import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; +import { listSpec } from "../../../new_fields/Schema"; +import { Cast, NumCast, FieldValue, PromiseValue, StrCast, BoolCast } from "../../../new_fields/Types"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { List } from "../../../new_fields/List"; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import PresentationElement from "./PresentationElement"; + +export interface PresViewProps { + Document: Doc; +} + +interface PresListProps extends PresViewProps { + deleteDocument(index: number): void; + gotoDocument(index: number): void; + groupedMembers: [Doc[]]; + +} + + +@observer +/** + * Component that takes in a document prop and a boolean whether it's collapsed or not. + */ +class PresentationViewList extends React.Component { + + + // onGroupClick = (document: Doc, index: number, buttonStatus: boolean[]) => { + // if (buttonStatus[5]) { + // buttonStatus[5] = false; + // if (index >= 1) { + // if (this.groupedMembers[index].length >= 0) { + // this.groupedMembers[index].forEach((doc: Doc) => this.groupedMembers[index - 1].slice(this.groupedMembers[index - 1].indexOf(doc), 1)); + // } + // } + // } else { + // buttonStatus[5] = true; + // console.log("reached!! ", buttonStatus[5]); + // if (index >= 1) { + // if (this.groupedMembers[index].length >= 0) { + // this.groupedMembers[index].forEach((doc: Doc) => this.groupedMembers[index - 1].push(doc)); + // } + // this.groupedMembers[index - 1].push(document); + // } + // } + // } + @action + initializeGroupArrays = (docList: Doc[]) => { + docList.forEach((doc: Doc, index: number) => { + if (this.props.groupedMembers.length < index + 1) { + this.props.groupedMembers[index] = new Array(); + } + }); + } + + // /** + // * Renders a single child document. It will just append a list element. + // * @param document The document to render. + // */ + // renderChild = (document: Doc, index: number) => { + // let title = document.title; + + // //to get currently selected presentation doc + // let selected = NumCast(this.props.Document.selectedDoc, 0); + + // let className = "presentationView-item"; + // if (selected === index) { + // //this doc is selected + // className += " presentationView-selected"; + // } + // let selectedButtons: boolean[] = new Array(6); + // let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } + // let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } + // return ( + //
{ this.props.gotoDocument(index); e.stopPropagation(); }}> + // + // {`${index + 1}. ${title}`} + // + // + //

+ // + // + // + // + // + // + + //
+ // ); + + // } + + render() { + const children = DocListCast(this.props.Document.data); + this.initializeGroupArrays(children); + + return ( +
+ {children.map((doc: Doc, index: number) => )} +
+ ); + } +} + + +@observer +export class PresentationView extends React.Component { + public static Instance: PresentationView; + + @observable groupedMembers: [Doc[]] = [[]]; + + + //observable means render is re-called every time variable is changed + @observable + collapsed: boolean = false; + closePresentation = action(() => this.props.Document.width = 0); + next = () => { + const current = NumCast(this.props.Document.selectedDoc); + this.gotoDocument(current + 1); + + } + back = () => { + const current = NumCast(this.props.Document.selectedDoc); + this.gotoDocument(current - 1); + } + + @action + public RemoveDoc = (index: number) => { + const value = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + if (value) { + value.splice(index, 1); + } + } + + public gotoDocument = async (index: number) => { + const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + if (!list) { + return; + } + if (index < 0 || index >= list.length) { + return; + } + + this.props.Document.selectedDoc = index; + const doc = await list[index]; + DocumentManager.Instance.jumpToDocument(doc); + } + + //initilize class variables + constructor(props: PresViewProps) { + super(props); + PresentationView.Instance = this; + } + + /** + * Adds a document to the presentation view + **/ + @action + public PinDoc(doc: Doc) { + //add this new doc to props.Document + const data = Cast(this.props.Document.data, listSpec(Doc)); + if (data) { + data.push(doc); + } else { + this.props.Document.data = new List([doc]); + } + + this.props.Document.width = 300; + } + + render() { + let titleStr = StrCast(this.props.Document.title); + let width = NumCast(this.props.Document.width); + + //TODO: next and back should be icons + return ( +
+
+
{titleStr}
+ +
+
+ + +
+ +
+ ); + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From efce6bf5ad2de96c8d4ee688ce0083608ecb541e Mon Sep 17 00:00:00 2001 From: madelinegr Date: Wed, 5 Jun 2019 14:29:38 -0400 Subject: Grouping done, insertion order should be checked --- .../views/presentationview/PresentationElement.tsx | 106 +++++++++++++++++++-- .../views/presentationview/PresentationView.tsx | 5 +- 2 files changed, 103 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 02d97ee4d..4d7f07154 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -41,14 +41,17 @@ export default class PresentationElement extends React.Component= 1) { if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1].push(doc)); + p.groupedMembers[index].forEach((doc: Doc) => { if (!p.groupedMembers[index - 1].includes(doc)) { p.groupedMembers[index - 1].push(doc); } }); + } + if (!p.groupedMembers[index - 1].includes(document)) { + p.groupedMembers[index - 1].push(document); } - p.groupedMembers[index - 1].push(document); //this.onGroupClick() } } } else { if (!buttonStatus) { + console.log("U reached me!"); if (p.groupedMembers[index].length >= 0) { p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); } @@ -62,11 +65,98 @@ export default class PresentationElement extends React.Component= 2) { - this.onGroupClick(p.allListElements[index - 1], index - 1, p.groupedMembers[index - 2].length !== 0); + this.onGroupClick(p.allListElements[index - 1], index - 1, p.groupedMembers[index - 2].length !== 1); } p.groupedMembers.forEach((docArray: Doc[], index: number) => console.log("Index: ", index, " size: ", docArray.length)); - console.log("Group Size: ", p.groupedMembers[index - 1].length); + console.log("Group Size: ", p.groupedMembers[index - 1].length, "Index: ", index - 1); + } + + + @action + onGroupClickRec = (document: Doc, index: number, buttonStatus: boolean) => { + let p = this.props; + if (buttonStatus) { + if (index >= 1) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => { + if (!p.groupedMembers[index - 1].includes(doc)) { + p.groupedMembers[index - 1].push(doc); + } + }); + } + + if (index >= 2) { + let nextBool = p.groupedMembers[index - 2].length !== 1; + if (nextBool === buttonStatus) { + this.onGroupClickRec(document, index - 1, p.groupedMembers[index - 2].length !== 1); + } + } + + } + } + else { + + if (index >= 1) { + let removeSize = p.groupedMembers[index].length; + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => { + p.groupedMembers[index - 1].pop(); console.log("Reached!!"); + }); + } + + + + if (index >= 2) { + let nextBool = p.groupedMembers[index - 2].length !== 1; + if (nextBool !== buttonStatus) { + this.recursiveDeleteGroups(index - 1, removeSize); + } + } + } + } + + } + + @action + recursiveDeleteGroups = (index: number, removeSize: number) => { + let p = this.props; + for (let i = 0; i < removeSize; i++) { + p.groupedMembers[index - 1].pop(); + } + if (index >= 2) { + + let nextBool = p.groupedMembers[index - 2].length !== 1; + if (nextBool === true) { + this.recursiveDeleteGroups(index - 1, removeSize); + } + } + } + + @action + onGroupClickRec2 = (document: Doc, index: number, buttonStatus: boolean) => { + let p = this.props; + if (buttonStatus) { + if (index >= 1) { + p.groupedMembers[index - 1].push(document); + if (index >= 2) { + this.onGroupClickRec2(document, index - 1, p.groupedMembers[index - 2].length !== 1); + } + } + } + } + + @action + changeGroupStatus = () => { + if (this.selectedButtons[5]) { + this.selectedButtons[5] = false; + } else { + this.selectedButtons[5] = true; + } + } + + printGroupSizes = () => { + this.props.groupedMembers.forEach((doc: Doc[], index: number) => console.log("Index: ", index, " size: ", doc.length)); } @@ -83,8 +173,8 @@ export default class PresentationElement extends React.Component { p.document.libraryBrush = true; } - let onLeave = (e: React.PointerEvent) => { p.document.libraryBrush = false; } + let onEnter = (e: React.PointerEvent) => { p.document.libraryBrush = true; }; + let onLeave = (e: React.PointerEvent) => { p.document.libraryBrush = false; }; return (
E
diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 5a7d38e28..9baf75ad3 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -52,9 +52,12 @@ class PresentationViewList extends React.Component { // } @action initializeGroupArrays = (docList: Doc[]) => { + console.log("Starting len: ", this.props.groupedMembers.length); docList.forEach((doc: Doc, index: number) => { - if (this.props.groupedMembers.length < index + 1) { + if (this.props.groupedMembers.length < index + 2) { this.props.groupedMembers[index] = new Array(); + this.props.groupedMembers[index].push(docList[index]); + } }); } -- cgit v1.2.3-70-g09d2 From 917c4f0ed9c61e52a06fce2872ffe3048b46099f Mon Sep 17 00:00:00 2001 From: madelinegr Date: Wed, 5 Jun 2019 14:58:23 -0400 Subject: comments removed --- .../views/presentationview/PresentationElement.tsx | 64 ---------------------- 1 file changed, 64 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 4d7f07154..08a663150 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -24,55 +24,6 @@ export default class PresentationElement extends React.Component { - let p = this.props; - if (Array.isArray(buttonStatus)) { - if (buttonStatus[5]) { - buttonStatus[5] = false; - console.log("Reached!"); - if (index >= 1) { - if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); - } - } - } else { - buttonStatus[5] = true; - if (index >= 1) { - if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => { if (!p.groupedMembers[index - 1].includes(doc)) { p.groupedMembers[index - 1].push(doc); } }); - } - if (!p.groupedMembers[index - 1].includes(document)) { - p.groupedMembers[index - 1].push(document); - } - //this.onGroupClick() - } - } - } else { - if (!buttonStatus) { - console.log("U reached me!"); - if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); - } - } else { - if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => { if (!p.groupedMembers[index - 1].includes(doc)) { p.groupedMembers[index - 1].push(doc); } }); - } - if (!p.groupedMembers[index - 1].includes(document)) { - p.groupedMembers[index - 1].push(document); - } - } - } - if (index >= 2) { - this.onGroupClick(p.allListElements[index - 1], index - 1, p.groupedMembers[index - 2].length !== 1); - } - - p.groupedMembers.forEach((docArray: Doc[], index: number) => console.log("Index: ", index, " size: ", docArray.length)); - console.log("Group Size: ", p.groupedMembers[index - 1].length, "Index: ", index - 1); - } - - @action onGroupClickRec = (document: Doc, index: number, buttonStatus: boolean) => { let p = this.props; @@ -105,8 +56,6 @@ export default class PresentationElement extends React.Component= 2) { let nextBool = p.groupedMembers[index - 2].length !== 1; if (nextBool !== buttonStatus) { @@ -133,19 +82,6 @@ export default class PresentationElement extends React.Component { - let p = this.props; - if (buttonStatus) { - if (index >= 1) { - p.groupedMembers[index - 1].push(document); - if (index >= 2) { - this.onGroupClickRec2(document, index - 1, p.groupedMembers[index - 2].length !== 1); - } - } - } - } - @action changeGroupStatus = () => { if (this.selectedButtons[5]) { -- cgit v1.2.3-70-g09d2 From a54e3b99c2c6d4c39cbdd935978b5e78015956ab Mon Sep 17 00:00:00 2001 From: madelinegr Date: Wed, 5 Jun 2019 17:29:43 -0400 Subject: Enums for buttons --- src/client/views/nodes/DocumentView.tsx | 4 +- .../views/presentationview/PresentationElement.tsx | 45 +++++++++++++++++----- .../views/presentationview/PresentationView.tsx | 5 +-- 3 files changed, 40 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 984cac9b9..449fa76a7 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -83,6 +83,7 @@ const schema = createSchema({ nativeWidth: "number", nativeHeight: "number", backgroundColor: "string", + opacity: "number" }); export const positionSchema = createSchema({ @@ -464,7 +465,8 @@ export class DocumentView extends DocComponent(Docu background: this.Document.backgroundColor || "", width: nativeWidth, height: nativeHeight, - transform: `scale(${scaling}, ${scaling})` + transform: `scale(${scaling}, ${scaling})`, + opacity: NumCast(this.props.Document.opacity, 1) }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 08a663150..48e740c4b 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -19,6 +19,16 @@ interface PresentationElementProps { } +enum buttonIndex { + Show = 0, + Navigate = 1, + HideTillPressed = 2, + FadeAfter = 3, + HideAfter = 4, + Group = 5, + +} + @observer export default class PresentationElement extends React.Component { @@ -84,10 +94,10 @@ export default class PresentationElement extends React.Component { - if (this.selectedButtons[5]) { - this.selectedButtons[5] = false; + if (this.selectedButtons[buttonIndex.Group]) { + this.selectedButtons[buttonIndex.Group] = false; } else { - this.selectedButtons[5] = true; + this.selectedButtons[buttonIndex.Group] = true; } } @@ -95,6 +105,21 @@ export default class PresentationElement extends React.Component console.log("Index: ", index, " size: ", doc.length)); } + @action + onHideDocumentUntilPressClick = (e: React.MouseEvent) => { + e.stopPropagation(); + if (this.selectedButtons[buttonIndex.HideTillPressed]) { + this.selectedButtons[buttonIndex.HideTillPressed] = false; + + } else { + this.selectedButtons[buttonIndex.HideTillPressed] = true; + } + } + + hideDocumentIfNotPressed = () => { + this.props.allListElements.forEach((doc: Doc) => doc.opacity = 0); + } + render() { @@ -125,15 +150,15 @@ export default class PresentationElement extends React.Component

- - - - - - + + + + + diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 9baf75ad3..b41149099 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -55,7 +55,7 @@ class PresentationViewList extends React.Component { console.log("Starting len: ", this.props.groupedMembers.length); docList.forEach((doc: Doc, index: number) => { if (this.props.groupedMembers.length < index + 2) { - this.props.groupedMembers[index] = new Array(); + this.props.groupedMembers[index] = []; this.props.groupedMembers[index].push(docList[index]); } @@ -123,8 +123,7 @@ class PresentationViewList extends React.Component { export class PresentationView extends React.Component { public static Instance: PresentationView; - @observable groupedMembers: [Doc[]] = [[]]; - + @observable groupedMembers: Doc[][] = []; //observable means render is re-called every time variable is changed @observable -- cgit v1.2.3-70-g09d2 From 36cf1b38e5da3ec948fd85d5d751a65dd8ec44fb Mon Sep 17 00:00:00 2001 From: madelinegr Date: Wed, 5 Jun 2019 20:04:00 -0400 Subject: Grouping With GUIDs is mostly done --- .../views/presentationview/PresentationElement.tsx | 69 ++++++++++++++++++++-- .../views/presentationview/PresentationView.tsx | 9 +-- 2 files changed, 69 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 48e740c4b..81be2c49f 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -1,10 +1,11 @@ import { observer } from "mobx-react"; import React = require("react"); import { Doc } from "../../../new_fields/Doc"; -import { NumCast, BoolCast } from "../../../new_fields/Types"; +import { NumCast, BoolCast, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; import { observable, action } from "mobx"; import "./PresentationView.scss"; +import { Utils } from "../../../Utils"; @@ -14,8 +15,9 @@ interface PresentationElementProps { index: number; deleteDocument(index: number): void; gotoDocument(index: number): void; - groupedMembers: [Doc[]]; + groupedMembers: Doc[][]; allListElements: Doc[]; + groupMappings: Map; } @@ -34,6 +36,63 @@ export default class PresentationElement extends React.Component { + let p = this.props; + if (buttonStatus) { + if (index >= 1) { + let newGuid = Utils.GenerateGuid(); + let aboveGuid = StrCast(p.allListElements[index - 1].presentId, undefined); + let docGuid = StrCast(document.presentId, undefined); + if (aboveGuid !== undefined) { + if (p.groupMappings.has(aboveGuid)) { + let aboveArray = p.groupMappings.get(aboveGuid)!; + if (p.groupMappings.has(docGuid)) { + let docsArray = p.groupMappings.get(docGuid)!; + docsArray.forEach((doc: Doc) => { + if (!aboveArray.includes(doc)) { + aboveArray.push(doc); + } + }); + } else { + if (!aboveArray.includes(document)) { + aboveArray.push(document); + + } + + } + } + document.presentId = aboveGuid; + } else { + p.allListElements[index - 1].presentId = newGuid; + let newAboveArray: Doc[] = []; + if (p.groupMappings.has(docGuid)) { + let docsArray = p.groupMappings.get(docGuid)!; + docsArray.forEach((doc: Doc) => newAboveArray.push(doc)); + } else { + newAboveArray.push(document); + } + document.presentId = newGuid; + p.groupMappings.set(newGuid, newAboveArray); + + + } + + } + } else { + let curArray = p.groupMappings.get(StrCast(document.presentId, Utils.GenerateGuid()))!; + let targetIndex = curArray.indexOf(document); + let firstPart = curArray.slice(0, targetIndex); + let secondPart = curArray.slice(targetIndex); + p.groupMappings.set(StrCast(p.allListElements[index - 1].presentId, Utils.GenerateGuid()), firstPart); + p.groupMappings.set(StrCast(document.presentId, Utils.GenerateGuid()), secondPart); + + + } + + } + @action onGroupClickRec = (document: Doc, index: number, buttonStatus: boolean) => { let p = this.props; @@ -117,7 +176,7 @@ export default class PresentationElement extends React.Component { - this.props.allListElements.forEach((doc: Doc) => doc.opacity = 0); + this.props.allListElements.forEach((doc: Doc) => doc.opacity = 1); } @@ -158,8 +217,8 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); this.changeGroupStatus(); - this.onGroupClickRec(p.document, p.index, this.selectedButtons[buttonIndex.Group]); - this.printGroupSizes(); + this.onGroupClick(p.document, p.index, this.selectedButtons[buttonIndex.Group]); + //this.printGroupSizes(); }}>F diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index b41149099..6cf908d01 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -19,8 +19,8 @@ export interface PresViewProps { interface PresListProps extends PresViewProps { deleteDocument(index: number): void; gotoDocument(index: number): void; - groupedMembers: [Doc[]]; - + groupedMembers: Doc[][]; + groupMappings: Map; } @@ -112,7 +112,7 @@ class PresentationViewList extends React.Component { return (
- {children.map((doc: Doc, index: number) => )} + {children.map((doc: Doc, index: number) => )}
); } @@ -124,6 +124,7 @@ export class PresentationView extends React.Component { public static Instance: PresentationView; @observable groupedMembers: Doc[][] = []; + @observable groupMappings: Map = new Map(); //observable means render is re-called every time variable is changed @observable @@ -198,7 +199,7 @@ export class PresentationView extends React.Component { - + ); } -- cgit v1.2.3-70-g09d2 From 9cf1a4375700a0d473db1affcba5e9d28f22d124 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 6 Jun 2019 12:57:38 -0400 Subject: Guid emptystring error fixed for grouping --- .../views/collections/CollectionBaseView.tsx | 3 ++ .../views/presentationview/PresentationElement.tsx | 53 +++++++++++++++++----- 2 files changed, 44 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 734669893..6639879e1 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -146,6 +146,9 @@ export class CollectionBaseView extends React.Component { } }); + //initial + // + if (index !== -1) { value.splice(index, 1); diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 81be2c49f..2d14476d2 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -40,33 +40,60 @@ export default class PresentationElement extends React.Component { let p = this.props; - if (buttonStatus) { - if (index >= 1) { + if (index >= 1) { + if (buttonStatus) { let newGuid = Utils.GenerateGuid(); - let aboveGuid = StrCast(p.allListElements[index - 1].presentId, undefined); - let docGuid = StrCast(document.presentId, undefined); + let aboveGuid = StrCast(p.allListElements[index - 1].presentId, null); + let docGuid = StrCast(document.presentId, null); if (aboveGuid !== undefined) { if (p.groupMappings.has(aboveGuid)) { let aboveArray = p.groupMappings.get(aboveGuid)!; if (p.groupMappings.has(docGuid)) { + console.log("Doc Guid: ", docGuid); + console.log("Above Guid: ", aboveGuid); let docsArray = p.groupMappings.get(docGuid)!; docsArray.forEach((doc: Doc) => { if (!aboveArray.includes(doc)) { aboveArray.push(doc); + } }); + console.log("CAlled first one"); + } else { if (!aboveArray.includes(document)) { aboveArray.push(document); + console.log("CAlled this one"); + console.log("Doc: ", document); } } + console.log("AboveArray Size: ", aboveArray.length); + } else { + let newAboveArray: Doc[] = []; + newAboveArray.push(p.allListElements[index - 1]); + if (p.groupMappings.has(docGuid)) { + let docsArray = p.groupMappings.get(docGuid)!; + docsArray.forEach((doc: Doc) => { + newAboveArray.push(doc); + + }); + } else { + newAboveArray.push(document); + + } + p.groupMappings.set(aboveGuid, newAboveArray); + console.log("NewABove array size: ", newAboveArray.length); + + + } document.presentId = aboveGuid; } else { p.allListElements[index - 1].presentId = newGuid; let newAboveArray: Doc[] = []; + newAboveArray.push(p.allListElements[index - 1]); if (p.groupMappings.has(docGuid)) { let docsArray = p.groupMappings.get(docGuid)!; docsArray.forEach((doc: Doc) => newAboveArray.push(doc)); @@ -75,20 +102,22 @@ export default class PresentationElement extends React.Component Date: Thu, 6 Jun 2019 16:08:18 -0400 Subject: Grouping done --- .../views/presentationview/PresentationElement.tsx | 95 ++++++++++++---------- .../views/presentationview/PresentationView.tsx | 11 +++ 2 files changed, 62 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 2d14476d2..eb7002731 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -45,72 +45,79 @@ export default class PresentationElement extends React.Component { - if (!aboveArray.includes(doc)) { - aboveArray.push(doc); - - } - }); - console.log("CAlled first one"); - - } else { - if (!aboveArray.includes(document)) { - aboveArray.push(document); - console.log("CAlled this one"); - console.log("Doc: ", document); - + // if (aboveGuid !== undefined) { + if (p.groupMappings.has(aboveGuid)) { + let aboveArray = p.groupMappings.get(aboveGuid)!; + if (p.groupMappings.has(docGuid)) { + console.log("Doc Guid: ", docGuid); + console.log("Above Guid: ", aboveGuid); + let docsArray = p.groupMappings.get(docGuid)!; + docsArray.forEach((doc: Doc) => { + if (!aboveArray.includes(doc)) { + aboveArray.push(doc); } - - } - console.log("AboveArray Size: ", aboveArray.length); + doc.presentId = aboveGuid; + }); + console.log("CAlled first one"); + p.groupMappings.delete(docGuid); } else { - let newAboveArray: Doc[] = []; - newAboveArray.push(p.allListElements[index - 1]); - if (p.groupMappings.has(docGuid)) { - let docsArray = p.groupMappings.get(docGuid)!; - docsArray.forEach((doc: Doc) => { - newAboveArray.push(doc); - - }); - } else { - newAboveArray.push(document); + if (!aboveArray.includes(document)) { + aboveArray.push(document); + console.log("CAlled this one"); + console.log("Doc: ", document); } - p.groupMappings.set(aboveGuid, newAboveArray); - console.log("NewABove array size: ", newAboveArray.length); - - } - document.presentId = aboveGuid; + console.log("AboveArray Size: ", aboveArray.length); } else { - p.allListElements[index - 1].presentId = newGuid; let newAboveArray: Doc[] = []; newAboveArray.push(p.allListElements[index - 1]); if (p.groupMappings.has(docGuid)) { let docsArray = p.groupMappings.get(docGuid)!; - docsArray.forEach((doc: Doc) => newAboveArray.push(doc)); + docsArray.forEach((doc: Doc) => { + newAboveArray.push(doc); + doc.presentId = aboveGuid; + }); + p.groupMappings.delete(docGuid); } else { newAboveArray.push(document); + } - document.presentId = newGuid; - p.groupMappings.set(newGuid, newAboveArray); - console.log("New Array created"); + p.groupMappings.set(aboveGuid, newAboveArray); + console.log("NewABove array size: ", newAboveArray.length); + } + document.presentId = aboveGuid; + // } else { + // p.allListElements[index - 1].presentId = newGuid; + // let newAboveArray: Doc[] = []; + // newAboveArray.push(p.allListElements[index - 1]); + // if (p.groupMappings.has(docGuid)) { + // let docsArray = p.groupMappings.get(docGuid)!; + // docsArray.forEach((doc: Doc) => { + // doc.presentId = newGuid; + // newAboveArray.push(doc); + // }); + // p.groupMappings.delete(docGuid); + // } else { + // newAboveArray.push(document); + // } + // document.presentId = newGuid; + // p.groupMappings.set(newGuid, newAboveArray); + // console.log("New Array created"); + + + // } } else { let curArray = p.groupMappings.get(StrCast(document.presentId, Utils.GenerateGuid()))!; let targetIndex = curArray.indexOf(document); let firstPart = curArray.slice(0, targetIndex); + let firstPartNewGuid = Utils.GenerateGuid(); + firstPart.forEach((doc: Doc) => doc.presentId = firstPartNewGuid); let secondPart = curArray.slice(targetIndex); p.groupMappings.set(StrCast(p.allListElements[index - 1].presentId, Utils.GenerateGuid()), firstPart); p.groupMappings.set(StrCast(document.presentId, Utils.GenerateGuid()), secondPart); diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 6cf908d01..79b7c1f15 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -62,6 +62,16 @@ class PresentationViewList extends React.Component { }); } + @action + initializeGroupIds = (docList: Doc[]) => { + docList.forEach((doc: Doc, index: number) => { + let docGuid = StrCast(doc.presentId, null); + if (docGuid === undefined) { + doc.presentId = Utils.GenerateGuid(); + } + }); + } + // /** // * Renders a single child document. It will just append a list element. // * @param document The document to render. @@ -109,6 +119,7 @@ class PresentationViewList extends React.Component { render() { const children = DocListCast(this.props.Document.data); this.initializeGroupArrays(children); + this.initializeGroupIds(children); return (
-- cgit v1.2.3-70-g09d2 From 51c59893afd84eb9f36669282cbf0479ee9d9f84 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 6 Jun 2019 16:45:32 -0400 Subject: Cleaned the ex implementation --- .../views/presentationview/PresentationElement.tsx | 88 ---------------------- .../views/presentationview/PresentationView.tsx | 17 +---- 2 files changed, 2 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index eb7002731..f5220c564 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -15,7 +15,6 @@ interface PresentationElementProps { index: number; deleteDocument(index: number): void; gotoDocument(index: number): void; - groupedMembers: Doc[][]; allListElements: Doc[]; groupMappings: Map; @@ -45,12 +44,9 @@ export default class PresentationElement extends React.Component { if (!aboveArray.includes(doc)) { @@ -91,27 +87,6 @@ export default class PresentationElement extends React.Component { - // doc.presentId = newGuid; - // newAboveArray.push(doc); - // }); - // p.groupMappings.delete(docGuid); - // } else { - // newAboveArray.push(document); - // } - // document.presentId = newGuid; - // p.groupMappings.set(newGuid, newAboveArray); - // console.log("New Array created"); - - - // } - } else { let curArray = p.groupMappings.get(StrCast(document.presentId, Utils.GenerateGuid()))!; let targetIndex = curArray.indexOf(document); @@ -129,64 +104,6 @@ export default class PresentationElement extends React.Component { - let p = this.props; - if (buttonStatus) { - if (index >= 1) { - if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => { - if (!p.groupedMembers[index - 1].includes(doc)) { - p.groupedMembers[index - 1].push(doc); - } - }); - } - - if (index >= 2) { - let nextBool = p.groupedMembers[index - 2].length !== 1; - if (nextBool === buttonStatus) { - this.onGroupClickRec(document, index - 1, p.groupedMembers[index - 2].length !== 1); - } - } - - } - } - else { - - if (index >= 1) { - let removeSize = p.groupedMembers[index].length; - if (p.groupedMembers[index].length >= 0) { - p.groupedMembers[index].forEach((doc: Doc) => { - p.groupedMembers[index - 1].pop(); console.log("Reached!!"); - }); - } - - if (index >= 2) { - let nextBool = p.groupedMembers[index - 2].length !== 1; - if (nextBool !== buttonStatus) { - this.recursiveDeleteGroups(index - 1, removeSize); - } - } - } - } - - } - - @action - recursiveDeleteGroups = (index: number, removeSize: number) => { - let p = this.props; - for (let i = 0; i < removeSize; i++) { - p.groupedMembers[index - 1].pop(); - } - if (index >= 2) { - - let nextBool = p.groupedMembers[index - 2].length !== 1; - if (nextBool === true) { - this.recursiveDeleteGroups(index - 1, removeSize); - } - } - } - @action changeGroupStatus = () => { if (this.selectedButtons[buttonIndex.Group]) { @@ -196,10 +113,6 @@ export default class PresentationElement extends React.Component { - this.props.groupedMembers.forEach((doc: Doc[], index: number) => console.log("Index: ", index, " size: ", doc.length)); - } - @action onHideDocumentUntilPressClick = (e: React.MouseEvent) => { e.stopPropagation(); @@ -254,7 +167,6 @@ export default class PresentationElement extends React.ComponentF
diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 79b7c1f15..3263ea62e 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -19,7 +19,6 @@ export interface PresViewProps { interface PresListProps extends PresViewProps { deleteDocument(index: number): void; gotoDocument(index: number): void; - groupedMembers: Doc[][]; groupMappings: Map; } @@ -50,17 +49,6 @@ class PresentationViewList extends React.Component { // } // } // } - @action - initializeGroupArrays = (docList: Doc[]) => { - console.log("Starting len: ", this.props.groupedMembers.length); - docList.forEach((doc: Doc, index: number) => { - if (this.props.groupedMembers.length < index + 2) { - this.props.groupedMembers[index] = []; - this.props.groupedMembers[index].push(docList[index]); - - } - }); - } @action initializeGroupIds = (docList: Doc[]) => { @@ -118,12 +106,11 @@ class PresentationViewList extends React.Component { render() { const children = DocListCast(this.props.Document.data); - this.initializeGroupArrays(children); this.initializeGroupIds(children); return (
- {children.map((doc: Doc, index: number) => )} + {children.map((doc: Doc, index: number) => )}
); } @@ -210,7 +197,7 @@ export class PresentationView extends React.Component { - + ); } -- cgit v1.2.3-70-g09d2 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/documents/Documents.ts | 30 +++++----- src/client/util/DocumentManager.ts | 54 ++++++++++++------ src/client/util/DragManager.ts | 19 +++++-- src/client/views/DocumentDecorations.tsx | 8 ++- .../CollectionFreeFormLinksView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 6 +- src/client/views/nodes/LinkBox.tsx | 17 +++--- src/client/views/nodes/LinkManager.tsx | 51 +++++++++++++++++ src/client/views/nodes/LinkMenu.scss | 65 +++++++++++++++++++++- src/client/views/nodes/LinkMenu.tsx | 51 ++++++++++++++--- 10 files changed, 247 insertions(+), 56 deletions(-) create mode 100644 src/client/views/nodes/LinkManager.tsx (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ab61b915c..87b831663 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -35,6 +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"; var requestImageSize = require('request-image-size'); var path = require('path'); @@ -70,12 +71,12 @@ const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; export namespace DocUtils { export function MakeLink(source: Doc, target: Doc) { - let protoSrc = source.proto ? source.proto : source; - let protoTarg = target.proto ? target.proto : target; + // let protoSrc = source.proto ? source.proto : source; + // let protoTarg = target.proto ? target.proto : target; UndoManager.RunInBatch(() => { let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; - linkDoc.proto!.title = "-link name-"; + linkDoc.proto!.title = source.proto!.title + " and " + target.proto!.title; linkDoc.proto!.linkDescription = ""; linkDoc.proto!.linkTags = "Default"; @@ -84,17 +85,20 @@ export namespace DocUtils { linkDoc.proto!.linkedFrom = source; linkDoc.proto!.linkedFromPage = source.curPage; - let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); - if (!linkedFrom) { - protoTarg.linkedFromDocs = linkedFrom = new List(); - } - linkedFrom.push(linkDoc); + // let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); + // if (!linkedFrom) { + // protoTarg.linkedFromDocs = linkedFrom = new List(); + // } + // linkedFrom.push(linkDoc); + + // let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); + // if (!linkedTo) { + // protoSrc.linkedToDocs = linkedTo = new List(); + // } + // linkedTo.push(linkDoc); + + LinkManager.Instance.allLinks.push(linkDoc); - let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); - if (!linkedTo) { - protoSrc.linkedToDocs = linkedTo = new List(); - } - linkedTo.push(linkDoc); return linkDoc; }, "make link"); } 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 diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 1e84a0db0..7854cc080 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -4,6 +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"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { @@ -41,14 +42,20 @@ 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[] = []; + // let draggedFromDocs: Doc[] = []; if (srcTarg) { - let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); - let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); - if (linkToDocs) draggedDocs = linkToDocs.map(linkDoc => Cast(linkDoc.linkedTo, Doc) as Doc); - if (linkFromDocs) draggedFromDocs = linkFromDocs.map(linkDoc => Cast(linkDoc.linkedFrom, Doc) as Doc); + // 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 LinkManager.Instance.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); } - draggedDocs.push(...draggedFromDocs); + // draggedDocs.push(...draggedFromDocs); if (draggedDocs.length) { let moddrag: Doc[] = []; for (const draggedDoc of draggedDocs) { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index da9b1253e..2aae9bce6 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -28,6 +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"; library.add(faLink); @@ -510,9 +511,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let linkButton = null; if (SelectionManager.SelectedDocuments().length > 0) { let selFirst = SelectionManager.SelectedDocuments()[0]; - let linkToSize = Cast(selFirst.props.Document.linkedToDocs, listSpec(Doc), []).length; - let linkFromSize = Cast(selFirst.props.Document.linkedFromDocs, listSpec(Doc), []).length; - let linkCount = linkToSize + linkFromSize; + // let linkToSize = Cast(selFirst.props.Document.linkedToDocs, listSpec(Doc), []).length; + // let linkFromSize = Cast(selFirst.props.Document.linkedFromDocs, listSpec(Doc), []).length; + // let linkCount = linkToSize + linkFromSize; + let linkCount = LinkManager.Instance.findAllRelatedLinks(selFirst.props.Document).length; linkButton = ( { @undoBatch - onViewButtonPressed = async (e: React.PointerEvent): Promise => { + followLink = async (e: React.PointerEvent): Promise => { e.stopPropagation(); DocumentManager.Instance.jumpToDocument(this.props.pairedDoc, e.altKey); } @@ -62,8 +63,8 @@ export class LinkBox extends React.Component { return ( // -
-
+
+

{this.props.linkName}

@@ -72,13 +73,15 @@ export class LinkBox extends React.Component {
-
+
{/*
*/} +
+
-
+
-
+
); diff --git a/src/client/views/nodes/LinkManager.tsx b/src/client/views/nodes/LinkManager.tsx new file mode 100644 index 000000000..1064eaa22 --- /dev/null +++ b/src/client/views/nodes/LinkManager.tsx @@ -0,0 +1,51 @@ +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.scss b/src/client/views/nodes/LinkMenu.scss index dedcce6ef..860f31d8a 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -1,3 +1,5 @@ +@import "../globalCssVariables"; + #linkMenu-container { width: 100%; height: auto; @@ -18,4 +20,65 @@ width: 100%; height: 100px; overflow-y: scroll; -} \ No newline at end of file +} + +.link-menu-group { + .link-menu-item { + border-top: 0.5px solid $light-color-secondary; + padding: 6px; + position: relative; + display: flex; + + .link-menu-item-content { + width: 100%; + } + + &:last-child { + border-bottom: 0.5px solid $light-color-secondary; + } + &:hover .link-menu-item-buttons { + display: flex; + } + &:hover .link-menu-item-content { + width: calc(100% - 72px); + } + } + .link-menu-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 3f09d6214..6dc5623d1 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -8,6 +8,7 @@ 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"; interface Props { docView: DocumentView; @@ -19,26 +20,62 @@ export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; - renderLinkItems(links: Doc[], key: string, type: string) { + // renderLinkItems(links: Doc[], key: string, type: string) { + // return links.map(link => { + // let doc = FieldValue(Cast(link[key], Doc)); + // if (doc) { + // return this._editingLink = link)} type={type} />; + // } + // }); + // } + + renderLinkGroup(links: Doc[]) { + console.log("render link group"); + let source = this.props.docView.Document; + console.log("num links", links.length, typeof links); return links.map(link => { - let doc = FieldValue(Cast(link[key], Doc)); + let destination = (link["linkedTo"] === source) ? link["linkedFrom"] : link["linkedTo"]; + let doc = FieldValue(Cast(destination, Doc)); if (doc) { - return this._editingLink = link)} type={type} />; + console.log(doc[Id] + source[Id], "source is", source[Id]); + return this._editingLink = link)} type={""} />; } }); } + renderLinkItems(links: Map>) { + console.log("render link items"); + + let linkItems: Array = []; + + links.forEach((links, group) => { + console.log("category is ", group); + linkItems.push( +
+

{group}:

+
+ {this.renderLinkGroup(links)} +
+
+ ) + }); + + return linkItems; + } + render() { //get list of links from document - let linkFrom = DocListCast(this.props.docView.props.Document.linkedFromDocs); - let linkTo = DocListCast(this.props.docView.props.Document.linkedToDocs); + // let linkFrom = DocListCast(this.props.docView.props.Document.linkedFromDocs); + // let linkTo = DocListCast(this.props.docView.props.Document.linkedToDocs); + let related = LinkManager.Instance.findRelatedGroupedLinks(this.props.docView.props.Document); if (this._editingLink === undefined) { return (
{/* */}
- {this.renderLinkItems(linkTo, "linkedTo", "Destination: ")} - {this.renderLinkItems(linkFrom, "linkedFrom", "Source: ")} + {/* {this.renderLinkItems(linkTo, "linkedTo", "Destination: ")} + {this.renderLinkItems(linkFrom, "linkedFrom", "Source: ")} */} + {this.renderLinkItems(related)}
); -- cgit v1.2.3-70-g09d2 From ecbf6dda7f410f866b1031966982b23b031e72ee Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 6 Jun 2019 18:47:48 -0400 Subject: Pres ELements mapped --- .../views/presentationview/PresentationElement.tsx | 16 +++++++++------- src/client/views/presentationview/PresentationView.tsx | 8 +++++--- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index f5220c564..33c0289d7 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -3,7 +3,7 @@ import React = require("react"); import { Doc } from "../../../new_fields/Doc"; import { NumCast, BoolCast, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; -import { observable, action } from "mobx"; +import { observable, action, computed } from "mobx"; import "./PresentationView.scss"; import { Utils } from "../../../Utils"; @@ -35,6 +35,10 @@ export default class PresentationElement extends React.Component { @@ -118,18 +122,16 @@ export default class PresentationElement extends React.Component { - this.props.allListElements.forEach((doc: Doc) => doc.opacity = 1); + } } - render() { let p = this.props; let title = p.document.title; @@ -160,7 +162,7 @@ export default class PresentationElement extends React.Component
- + - + ); } -- cgit v1.2.3-70-g09d2 From 3473a78055d657829efb8818b643a5348c15fffc Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 6 Jun 2019 19:47:45 -0400 Subject: ... --- src/client/views/presentationview/PresentationView.tsx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 0655418f4..6089665fe 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -132,6 +132,8 @@ export class PresentationView extends React.Component { closePresentation = action(() => this.props.Document.width = 0); next = () => { const current = NumCast(this.props.Document.selectedDoc); + // let currentPresId = StrCast(current.presentId); + // this.groupMappings.get(current.presentId); this.gotoDocument(current + 1); } -- cgit v1.2.3-70-g09d2 From 8699b8bb3a3b93e2ec5eff7ca239bccbdccab8ae Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 12:23:34 -0400 Subject: Next and Prev adjusted to groups --- .../views/presentationview/PresentationView.tsx | 54 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 6089665fe..bede2dd66 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -130,16 +130,62 @@ export class PresentationView extends React.Component { @observable collapsed: boolean = false; closePresentation = action(() => this.props.Document.width = 0); - next = () => { + next = async () => { const current = NumCast(this.props.Document.selectedDoc); // let currentPresId = StrCast(current.presentId); + let docAtCurrent = await this.getDocAtIndex(current); + if (docAtCurrent === undefined) { + return; + } + let curPresId = StrCast(docAtCurrent.presentId); + let nextSelected = current + 1; + + if (this.groupMappings.has(curPresId)) { + let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; + console.log("It reaches here"); + console.log("CurArray Len: ", currentsArray.length) + //nextSelected = current + currentsArray.length - current - 1; + nextSelected = current + currentsArray.length - currentsArray.indexOf(docAtCurrent) - 1; + if (nextSelected === current) nextSelected = current + 1; + } + // this.groupMappings.get(current.presentId); - this.gotoDocument(current + 1); + this.gotoDocument(nextSelected); } - back = () => { + back = async () => { const current = NumCast(this.props.Document.selectedDoc); - this.gotoDocument(current - 1); + let docAtCurrent = await this.getDocAtIndex(current); + if (docAtCurrent === undefined) { + return; + } + let curPresId = StrCast(docAtCurrent.presentId); + let prevSelected = current - 1; + + if (this.groupMappings.has(curPresId)) { + let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; + prevSelected = current - currentsArray.length + (currentsArray.length - currentsArray.indexOf(docAtCurrent)); + if (prevSelected === current) prevSelected = current - 1; + + + } + + + this.gotoDocument(prevSelected); + } + + getDocAtIndex = async (index: number) => { + const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + if (!list) { + return undefined; + } + if (index < 0 || index >= list.length) { + return undefined; + } + + this.props.Document.selectedDoc = index; + const doc = await list[index]; + return doc; } @action -- cgit v1.2.3-70-g09d2 From 6a905a729cbb59add629a305f99e1e225f958ea3 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 15:00:52 -0400 Subject: Guid Updatae Guids will only be assigned to docs that are not in groups --- src/client/views/presentationview/PresentationView.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index bede2dd66..9acdea98e 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -55,8 +55,9 @@ class PresentationViewList extends React.Component { initializeGroupIds = (docList: Doc[]) => { docList.forEach((doc: Doc, index: number) => { let docGuid = StrCast(doc.presentId, null); - if (docGuid === undefined) { + if (!this.props.groupMappings.has(docGuid)) { doc.presentId = Utils.GenerateGuid(); + } }); } -- cgit v1.2.3-70-g09d2 From ecac03b032c4d1484408b892024135a814cd3265 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 15:53:21 -0400 Subject: Hide Until Presented Is Done --- .../views/presentationview/PresentationElement.tsx | 9 +++--- .../views/presentationview/PresentationView.tsx | 37 ++++++++++++++++++++-- 2 files changed, 39 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 33c0289d7..2621b92a3 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -20,7 +20,7 @@ interface PresentationElementProps { } -enum buttonIndex { +export enum buttonIndex { Show = 0, Navigate = 1, HideTillPressed = 2, @@ -120,14 +120,15 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); + const current = NumCast(this.props.mainDocument.selectedDoc); if (this.selectedButtons[buttonIndex.HideTillPressed]) { this.selectedButtons[buttonIndex.HideTillPressed] = false; this.props.document.opacity = 1; - } else { this.selectedButtons[buttonIndex.HideTillPressed] = true; - this.props.document.opacity = 0; - + if (this.props.index > current) { + this.props.document.opacity = 0; + } } } diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 9acdea98e..4fcc0b523 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -10,7 +10,7 @@ import { Cast, NumCast, FieldValue, PromiseValue, StrCast, BoolCast } from "../. import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; -import PresentationElement from "./PresentationElement"; +import PresentationElement, { buttonIndex } from "./PresentationElement"; export interface PresViewProps { Document: Doc; @@ -21,6 +21,7 @@ interface PresListProps extends PresViewProps { gotoDocument(index: number): void; groupMappings: Map; presElementsMappings: Map; + setChildrenDocs: (docList: Doc[]) => void; } @@ -57,7 +58,6 @@ class PresentationViewList extends React.Component { let docGuid = StrCast(doc.presentId, null); if (!this.props.groupMappings.has(docGuid)) { doc.presentId = Utils.GenerateGuid(); - } }); } @@ -109,6 +109,7 @@ class PresentationViewList extends React.Component { render() { const children = DocListCast(this.props.Document.data); this.initializeGroupIds(children); + this.props.setChildrenDocs(children); return (
@@ -126,6 +127,7 @@ export class PresentationView extends React.Component { @observable groupedMembers: Doc[][] = []; @observable groupMappings: Map = new Map(); @observable presElementsMappings: Map = new Map(); + @observable childrenDocs: Doc[] = []; //observable means render is re-called every time variable is changed @observable @@ -175,6 +177,26 @@ export class PresentationView extends React.Component { this.gotoDocument(prevSelected); } + showAfterPresented = (index: number) => { + this.presElementsMappings.forEach((presElem: PresentationElement, key: Doc) => { + if (presElem.selected[buttonIndex.HideTillPressed]) { + if (this.childrenDocs.indexOf(key) <= index) { + key.opacity = 1; + } + } + }); + } + + hideIfNotPresented = (index: number) => { + this.presElementsMappings.forEach((presElem: PresentationElement, key: Doc) => { + if (presElem.selected[buttonIndex.HideTillPressed]) { + if (this.childrenDocs.indexOf(key) > index) { + key.opacity = 0; + } + } + }); + } + getDocAtIndex = async (index: number) => { const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); if (!list) { @@ -209,6 +231,10 @@ export class PresentationView extends React.Component { this.props.Document.selectedDoc = index; const doc = await list[index]; DocumentManager.Instance.jumpToDocument(doc); + this.hideIfNotPresented(index); + this.showAfterPresented(index); + + } //initilize class variables @@ -233,6 +259,11 @@ export class PresentationView extends React.Component { this.props.Document.width = 300; } + @action + setChildrenDocs = (docList: Doc[]) => { + this.childrenDocs = docList; + } + render() { let titleStr = StrCast(this.props.Document.title); let width = NumCast(this.props.Document.width); @@ -248,7 +279,7 @@ export class PresentationView extends React.Component {
- + ); } -- cgit v1.2.3-70-g09d2 From 213cd917b20a8955ebfa0a4127e2853614314087 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 16:43:26 -0400 Subject: HideAfter Presented Done --- .../views/presentationview/PresentationElement.tsx | 12 +++++++++++- src/client/views/presentationview/PresentationView.tsx | 16 ++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 2621b92a3..bf09efaf2 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -132,6 +132,16 @@ export default class PresentationElement extends React.Component { + e.stopPropagation(); + if (this.selectedButtons[buttonIndex.HideAfter]) { + this.selectedButtons[buttonIndex.HideAfter] = false; + } else { + this.selectedButtons[buttonIndex.HideAfter] = true; + } + } + render() { let p = this.props; @@ -165,7 +175,7 @@ export default class PresentationElement extends React.ComponentB - + - + */}
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 f88bb6cb27d84041637ac31d8b4b82a710367dfb Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 18:08:18 -0400 Subject: Navigation done --- .../views/presentationview/PresentationElement.tsx | 13 +++++++++- .../views/presentationview/PresentationView.tsx | 29 +++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index e821c9478..c89cd4309 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -158,6 +158,17 @@ export default class PresentationElement extends React.Component { + e.stopPropagation(); + if (this.selectedButtons[buttonIndex.Navigate]) { + this.selectedButtons[buttonIndex.Navigate] = false; + + } else { + this.selectedButtons[buttonIndex.Navigate] = true; + } + } + render() { let p = this.props; @@ -188,7 +199,7 @@ export default class PresentationElement extends React.Component { this.props.deleteDocument(p.index); e.stopPropagation(); }}>X

- + diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index efc333ee3..cbfad56d1 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -222,6 +222,32 @@ export class PresentationView extends React.Component { }); } + navigateToElement = (curDoc: Doc) => { + let docToJump: Doc = curDoc; + let curDocPresId = StrCast(curDoc.presentId, null); + + if (curDocPresId !== undefined) { + if (this.groupMappings.has(curDocPresId)) { + let currentDocGroup = this.groupMappings.get(curDocPresId)!; + currentDocGroup.forEach((doc: Doc, index: number) => { + let selectedButtons: boolean[] = this.presElementsMappings.get(doc)!.selected; + if (selectedButtons[buttonIndex.Navigate]) { + docToJump = doc; + } + }); + } + + } + if (docToJump === curDoc) { + if (this.presElementsMappings.get(curDoc)!.selected[buttonIndex.Navigate]) { + DocumentManager.Instance.jumpToDocument(curDoc); + } else { + return; + } + } + DocumentManager.Instance.jumpToDocument(docToJump); + } + getDocAtIndex = async (index: number) => { const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); if (!list) { @@ -255,7 +281,8 @@ export class PresentationView extends React.Component { this.props.Document.selectedDoc = index; const doc = await list[index]; - DocumentManager.Instance.jumpToDocument(doc); + // DocumentManager.Instance.jumpToDocument(doc); + this.navigateToElement(doc); this.hideIfNotPresented(index); this.showAfterPresented(index); -- cgit v1.2.3-70-g09d2 From 91614b758e937113a39ab3490b8ec379ee0e03c1 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 19:04:04 -0400 Subject: Icons for buttons and next and back is added --- package.json | 2 ++ .../views/presentationview/PresentationElement.tsx | 23 ++++++++++++++++------ .../views/presentationview/PresentationView.tsx | 10 ++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/package.json b/package.json index df0767b50..de4e7b37e 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,8 @@ "dependencies": { "@fortawesome/fontawesome-free-solid": "^5.0.13", "@fortawesome/fontawesome-svg-core": "^1.2.15", + "@fortawesome/free-brands-svg-icons": "^5.9.0", + "@fortawesome/free-regular-svg-icons": "^5.9.0", "@fortawesome/free-solid-svg-icons": "^5.7.2", "@fortawesome/react-fontawesome": "^0.1.4", "@hig/flyout": "^1.0.3", diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index c89cd4309..1a3f35d44 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -6,9 +6,20 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { observable, action, computed } from "mobx"; import "./PresentationView.scss"; import { Utils } from "../../../Utils"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFile as fileSolid, faLocationArrow, faArrowUp, faSearch } from '@fortawesome/free-solid-svg-icons'; +import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; + +library.add(faArrowUp); +library.add(fileSolid); +library.add(fileRegular); +library.add(faLocationArrow); +library.add(faSearch); + interface PresentationElementProps { mainDocument: Doc; document: Doc; @@ -198,16 +209,16 @@ export default class PresentationElement extends React.Component

- - - - - + + + + + + }}> ); diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index cbfad56d1..e3a879833 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -11,6 +11,12 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import PresentationElement, { buttonIndex } from "./PresentationElement"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faArrowRight, faArrowLeft } from '@fortawesome/free-solid-svg-icons'; + +library.add(faArrowLeft); +library.add(faArrowRight); export interface PresViewProps { Document: Doc; @@ -328,8 +334,8 @@ export class PresentationView extends React.Component {
- - + +
-- cgit v1.2.3-70-g09d2 From cfb4470fa457581a78ea93fc53519c09f2516669 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 19:35:01 -0400 Subject: unnecessary console.logs and comments removed --- .../views/presentationview/PresentationElement.tsx | 7 -- .../views/presentationview/PresentationView.tsx | 76 +--------------------- 2 files changed, 1 insertion(+), 82 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 1a3f35d44..ee423c90a 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -69,18 +69,14 @@ export default class PresentationElement extends React.Component { - - // onGroupClick = (document: Doc, index: number, buttonStatus: boolean[]) => { - // if (buttonStatus[5]) { - // buttonStatus[5] = false; - // if (index >= 1) { - // if (this.groupedMembers[index].length >= 0) { - // this.groupedMembers[index].forEach((doc: Doc) => this.groupedMembers[index - 1].slice(this.groupedMembers[index - 1].indexOf(doc), 1)); - // } - // } - // } else { - // buttonStatus[5] = true; - // console.log("reached!! ", buttonStatus[5]); - // if (index >= 1) { - // if (this.groupedMembers[index].length >= 0) { - // this.groupedMembers[index].forEach((doc: Doc) => this.groupedMembers[index - 1].push(doc)); - // } - // this.groupedMembers[index - 1].push(document); - // } - // } - // } - @action initializeGroupIds = (docList: Doc[]) => { docList.forEach((doc: Doc, index: number) => { @@ -68,50 +47,6 @@ class PresentationViewList extends React.Component { }); } - // /** - // * Renders a single child document. It will just append a list element. - // * @param document The document to render. - // */ - // renderChild = (document: Doc, index: number) => { - // let title = document.title; - - // //to get currently selected presentation doc - // let selected = NumCast(this.props.Document.selectedDoc, 0); - - // let className = "presentationView-item"; - // if (selected === index) { - // //this doc is selected - // className += " presentationView-selected"; - // } - // let selectedButtons: boolean[] = new Array(6); - // let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } - // let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } - // return ( - //
{ this.props.gotoDocument(index); e.stopPropagation(); }}> - // - // {`${index + 1}. ${title}`} - // - // - //

- // - // - // - // - // - // - - //
- // ); - - // } - render() { const children = DocListCast(this.props.Document.data); this.initializeGroupIds(children); @@ -119,7 +54,7 @@ class PresentationViewList extends React.Component { return (
- {children.map((doc: Doc, index: number) => this.props.presElementsMappings.set(doc, e!)} key={index} mainDocument={this.props.Document} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} />)} + {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={index} mainDocument={this.props.Document} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} />)}
); } @@ -141,7 +76,6 @@ export class PresentationView extends React.Component { closePresentation = action(() => this.props.Document.width = 0); next = async () => { const current = NumCast(this.props.Document.selectedDoc); - // let currentPresId = StrCast(current.presentId); let docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent === undefined) { return; @@ -151,14 +85,10 @@ export class PresentationView extends React.Component { if (this.groupMappings.has(curPresId)) { let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; - console.log("It reaches here"); - console.log("CurArray Len: ", currentsArray.length) - //nextSelected = current + currentsArray.length - current - 1; nextSelected = current + currentsArray.length - currentsArray.indexOf(docAtCurrent) - 1; if (nextSelected === current) nextSelected = current + 1; } - // this.groupMappings.get(current.presentId); this.gotoDocument(nextSelected); } @@ -209,7 +139,6 @@ export class PresentationView extends React.Component { let selectedButtons: boolean[] = presElem.selected; if (selectedButtons[buttonIndex.HideAfter]) { if (this.childrenDocs.indexOf(key) >= index) { - console.log("CAlled this right"); key.opacity = 1; } } @@ -220,8 +149,6 @@ export class PresentationView extends React.Component { } if (selectedButtons[buttonIndex.HideTillPressed]) { if (this.childrenDocs.indexOf(key) > index) { - console.log("KeyIndex: ", this.childrenDocs.indexOf(key)); - console.log("Cur index: ", index); key.opacity = 0; } } @@ -287,7 +214,6 @@ export class PresentationView extends React.Component { this.props.Document.selectedDoc = index; const doc = await list[index]; - // DocumentManager.Instance.jumpToDocument(doc); this.navigateToElement(doc); this.hideIfNotPresented(index); this.showAfterPresented(index); -- cgit v1.2.3-70-g09d2 From 24730e6fe8114828a96c6c0ce9c170ff2488e423 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 7 Jun 2019 19:56:35 -0400 Subject: Documentation --- .../views/presentationview/PresentationElement.tsx | 46 ++++++++++++++++++++- .../views/presentationview/PresentationView.tsx | 47 +++++++++++++++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index ee423c90a..dfe078a8e 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -31,6 +31,7 @@ interface PresentationElementProps { } +//enum for the all kinds of buttons a doc in presentation can have export enum buttonIndex { Show = 0, Navigate = 1, @@ -41,26 +42,41 @@ export enum buttonIndex { } +/** + * This class models the view a document added to presentation will have in the presentation. + * It involves some functionality for its buttons and options. + */ @observer export default class PresentationElement extends React.Component { @observable selectedButtons: boolean[] = new Array(6); + /** + * Getter to get the status of the buttons. + */ @computed get selected() { return this.selectedButtons; } + /** + * The function that is called to group docs together. It tries to group a doc + * that turned grouping option with the above document. If that doc is grouped with + * other documents. Those other documents will be grouped with doc's above document as well. + */ @action onGroupClick = (document: Doc, index: number, buttonStatus: boolean) => { let p = this.props; if (index >= 1) { + //checking if options was turned true if (buttonStatus) { - let newGuid = Utils.GenerateGuid(); + //getting the id of the above-doc and the doc let aboveGuid = StrCast(p.allListElements[index - 1].presentId, null); let docGuid = StrCast(document.presentId, null); + //the case where above-doc is already in group if (p.groupMappings.has(aboveGuid)) { let aboveArray = p.groupMappings.get(aboveGuid)!; + //case where doc is already in group if (p.groupMappings.has(docGuid)) { let docsArray = p.groupMappings.get(docGuid)!; docsArray.forEach((doc: Doc) => { @@ -70,6 +86,7 @@ export default class PresentationElement extends React.Component { @@ -87,6 +107,8 @@ export default class PresentationElement extends React.Component { if (this.selectedButtons[buttonIndex.Group]) { @@ -121,6 +148,10 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); @@ -136,6 +167,11 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); @@ -149,6 +185,11 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); @@ -162,6 +203,9 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index c7839a384..e987d12f6 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -37,10 +37,17 @@ interface PresListProps extends PresViewProps { */ class PresentationViewList extends React.Component { + /** + * Method that initializes presentation ids for the + * docs that is in the presentation, when presentation list + * gets re-rendered. It makes sure to not assign ids to the + * docs that are in the group, so that mapping won't be disrupted. + */ @action initializeGroupIds = (docList: Doc[]) => { docList.forEach((doc: Doc, index: number) => { let docGuid = StrCast(doc.presentId, null); + //checking if part of group if (!this.props.groupMappings.has(docGuid)) { doc.presentId = Utils.GenerateGuid(); } @@ -65,9 +72,11 @@ class PresentationViewList extends React.Component { export class PresentationView extends React.Component { public static Instance: PresentationView; - @observable groupedMembers: Doc[][] = []; + //Mapping from presentation ids to a list of doc that represent a group @observable groupMappings: Map = new Map(); + //mapping from docs to their rendered component @observable presElementsMappings: Map = new Map(); + //variable that holds all the docs in the presentation @observable childrenDocs: Doc[] = []; //observable means render is re-called every time variable is changed @@ -76,16 +85,21 @@ export class PresentationView extends React.Component { closePresentation = action(() => this.props.Document.width = 0); next = async () => { const current = NumCast(this.props.Document.selectedDoc); + //asking to get document at current index let docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent === undefined) { return; } + //asking for it's presentation id let curPresId = StrCast(docAtCurrent.presentId); let nextSelected = current + 1; + //if curDoc is in a group, selection slides until last one, if not it's next one if (this.groupMappings.has(curPresId)) { let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; nextSelected = current + currentsArray.length - currentsArray.indexOf(docAtCurrent) - 1; + + //end of grup so go beyond if (nextSelected === current) nextSelected = current + 1; } @@ -94,16 +108,21 @@ export class PresentationView extends React.Component { } back = async () => { const current = NumCast(this.props.Document.selectedDoc); + //requesting for the doc at current index let docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent === undefined) { return; } + + //asking for its presentation id. let curPresId = StrCast(docAtCurrent.presentId); let prevSelected = current - 1; + //checking if this presentation id is mapped to a group, if so chosing the first element in group if (this.groupMappings.has(curPresId)) { let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; prevSelected = current - currentsArray.length + (currentsArray.length - currentsArray.indexOf(docAtCurrent)); + //end of grup so go beyond if (prevSelected === current) prevSelected = current - 1; @@ -113,9 +132,15 @@ export class PresentationView extends React.Component { this.gotoDocument(prevSelected); } + /** + * This is the method that checks for the actions that need to be performed + * after the document has been presented, which involves 3 button options: + * Hide Until Presented, Hide After Presented, Fade After Presented + */ showAfterPresented = (index: number) => { this.presElementsMappings.forEach((presElem: PresentationElement, key: Doc) => { let selectedButtons: boolean[] = presElem.selected; + //the order of cases is aligned based on priority if (selectedButtons[buttonIndex.HideTillPressed]) { if (this.childrenDocs.indexOf(key) <= index) { key.opacity = 1; @@ -134,9 +159,17 @@ export class PresentationView extends React.Component { }); } + /** + * This is the method that checks for the actions that need to be performed + * before the document has been presented, which involves 3 button options: + * Hide Until Presented, Hide After Presented, Fade After Presented + */ hideIfNotPresented = (index: number) => { this.presElementsMappings.forEach((presElem: PresentationElement, key: Doc) => { let selectedButtons: boolean[] = presElem.selected; + + //the order of cases is aligned based on priority + if (selectedButtons[buttonIndex.HideAfter]) { if (this.childrenDocs.indexOf(key) >= index) { key.opacity = 1; @@ -155,10 +188,16 @@ export class PresentationView extends React.Component { }); } + /** + * This method makes sure that cursor navigates to the element that + * 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) => { let docToJump: Doc = curDoc; let curDocPresId = StrCast(curDoc.presentId, null); + //checking if in group if (curDocPresId !== undefined) { if (this.groupMappings.has(curDocPresId)) { let currentDocGroup = this.groupMappings.get(curDocPresId)!; @@ -171,7 +210,9 @@ 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 { @@ -181,6 +222,9 @@ export class PresentationView extends React.Component { DocumentManager.Instance.jumpToDocument(docToJump); } + /** + * Async function that supposedly return the doc that is located at given index. + */ getDocAtIndex = async (index: number) => { const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); if (!list) { @@ -191,6 +235,7 @@ export class PresentationView extends React.Component { } this.props.Document.selectedDoc = index; + //awaiting async call to finish to get Doc instance const doc = await list[index]; return doc; } -- cgit v1.2.3-70-g09d2 From cd483361f9b372dc79a001e3182fdac459e229ec Mon Sep 17 00:00:00 2001 From: madelinegr Date: Mon, 10 Jun 2019 13:34:42 -0400 Subject: Start/Reset and interaction while playin added --- .../views/presentationview/PresentationElement.tsx | 42 ++++++++++--- .../views/presentationview/PresentationView.scss | 4 +- .../views/presentationview/PresentationView.tsx | 69 +++++++++++++++++++--- 3 files changed, 97 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index dfe078a8e..f346940a2 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -28,6 +28,8 @@ interface PresentationElementProps { gotoDocument(index: number): void; allListElements: Doc[]; groupMappings: Map; + presStatus: boolean; + } @@ -158,11 +160,15 @@ export default class PresentationElement extends React.Component= current) { + this.props.document.opacity = 1; + } } else { this.selectedButtons[buttonIndex.HideTillPressed] = true; - if (this.props.index > current) { - this.props.document.opacity = 0; + if (this.props.presStatus) { + if (this.props.index > current) { + this.props.document.opacity = 0; + } } } } @@ -175,13 +181,22 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); + const current = NumCast(this.props.mainDocument.selectedDoc); if (this.selectedButtons[buttonIndex.HideAfter]) { this.selectedButtons[buttonIndex.HideAfter] = false; + if (this.props.index <= current) { + this.props.document.opacity = 1; + } } else { if (this.selectedButtons[buttonIndex.FadeAfter]) { this.selectedButtons[buttonIndex.FadeAfter] = false; } this.selectedButtons[buttonIndex.HideAfter] = true; + if (this.props.presStatus) { + if (this.props.index < current) { + this.props.document.opacity = 0; + } + } } } @@ -193,13 +208,22 @@ export default class PresentationElement extends React.Component { e.stopPropagation(); + const current = NumCast(this.props.mainDocument.selectedDoc); if (this.selectedButtons[buttonIndex.FadeAfter]) { this.selectedButtons[buttonIndex.FadeAfter] = false; + if (this.props.index <= current) { + this.props.document.opacity = 1; + } } else { if (this.selectedButtons[buttonIndex.HideAfter]) { this.selectedButtons[buttonIndex.HideAfter] = false; } this.selectedButtons[buttonIndex.FadeAfter] = true; + if (this.props.presStatus) { + if (this.props.index < current) { + this.props.document.opacity = 0.5; + } + } } } @@ -246,12 +270,12 @@ export default class PresentationElement extends React.Component

- - - - - - + + + + + ; + } else { + return ; + } + } + + @action + startOrResetPres = () => { + if (this.presStatus) { + this.presStatus = false; + this.resetPresentation(); + } else { + this.presStatus = true; + this.startPresentation(); + } + } + + @action + resetPresentation = () => { + this.groupMappings = new Map(); + let selectedButtons: boolean[]; + this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { + selectedButtons = component.selected; + selectedButtons.forEach((val: boolean, index: number) => selectedButtons[index] = false); + doc.presentId = Utils.GenerateGuid(); + doc.opacity = 1; + }); + this.props.Document.selectedDoc = 0; + + } + + startPresentation = () => { + this.props.Document.selectedDoc = 0; + let selectedButtons: boolean[]; + this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { + selectedButtons = component.selected; + if (selectedButtons[buttonIndex.HideTillPressed]) { + if (this.childrenDocs.indexOf(doc) > 0) { + doc.opacity = 0; + } + + } + }); + + } + render() { let titleStr = StrCast(this.props.Document.title); let width = NumCast(this.props.Document.width); @@ -306,9 +360,10 @@ export class PresentationView extends React.Component {
+ {this.renderPlayPauseButton()}
- + ); } -- cgit v1.2.3-70-g09d2 From 6339ce36664b008c4274dc51fc2e7851b9dabf89 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Mon, 10 Jun 2019 14:03:33 -0400 Subject: Next And Back Fixed For groups --- .../views/presentationview/PresentationView.tsx | 49 ++++++++++++++-------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 93c084dfd..8d1be6af1 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -91,18 +91,18 @@ export class PresentationView extends React.Component { next = async () => { const current = NumCast(this.props.Document.selectedDoc); //asking to get document at current index - let docAtCurrent = await this.getDocAtIndex(current); - if (docAtCurrent === undefined) { + let docAtCurrentNext = await this.getDocAtIndex(current + 1); + if (docAtCurrentNext === undefined) { return; } //asking for it's presentation id - let curPresId = StrCast(docAtCurrent.presentId); + let curNextPresId = StrCast(docAtCurrentNext.presentId); let nextSelected = current + 1; //if curDoc is in a group, selection slides until last one, if not it's next one - if (this.groupMappings.has(curPresId)) { - let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; - nextSelected = current + currentsArray.length - currentsArray.indexOf(docAtCurrent) - 1; + if (this.groupMappings.has(curNextPresId)) { + let currentsArray = this.groupMappings.get(StrCast(docAtCurrentNext.presentId))!; + nextSelected = current + currentsArray.length - currentsArray.indexOf(docAtCurrentNext); //end of grup so go beyond if (nextSelected === current) nextSelected = current + 1; @@ -126,7 +126,7 @@ export class PresentationView extends React.Component { //checking if this presentation id is mapped to a group, if so chosing the first element in group if (this.groupMappings.has(curPresId)) { let currentsArray = this.groupMappings.get(StrCast(docAtCurrent.presentId))!; - prevSelected = current - currentsArray.length + (currentsArray.length - currentsArray.indexOf(docAtCurrent)); + prevSelected = current - currentsArray.length + (currentsArray.length - currentsArray.indexOf(docAtCurrent)) - 1; //end of grup so go beyond if (prevSelected === current) prevSelected = current - 1; @@ -252,7 +252,7 @@ export class PresentationView extends React.Component { value.splice(index, 1); } } - + @action public gotoDocument = async (index: number) => { const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); if (!list) { @@ -261,8 +261,13 @@ export class PresentationView extends React.Component { if (index < 0 || index >= list.length) { return; } - this.props.Document.selectedDoc = index; + + if (!this.presStatus) { + this.presStatus = true; + this.startPresentation(index); + } + const doc = await list[index]; if (this.presStatus) { this.navigateToElement(doc); @@ -301,9 +306,9 @@ export class PresentationView extends React.Component { renderPlayPauseButton = () => { if (this.presStatus) { - return ; + return ; } else { - return ; + return ; } } @@ -314,7 +319,7 @@ export class PresentationView extends React.Component { this.resetPresentation(); } else { this.presStatus = true; - this.startPresentation(); + this.startPresentation(0); } } @@ -332,17 +337,27 @@ export class PresentationView extends React.Component { } - startPresentation = () => { - this.props.Document.selectedDoc = 0; + startPresentation = (startIndex: number) => { let selectedButtons: boolean[]; this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { selectedButtons = component.selected; if (selectedButtons[buttonIndex.HideTillPressed]) { - if (this.childrenDocs.indexOf(doc) > 0) { + if (this.childrenDocs.indexOf(doc) > startIndex) { doc.opacity = 0; } } + if (selectedButtons[buttonIndex.HideAfter]) { + if (this.childrenDocs.indexOf(doc) < startIndex) { + doc.opacity = 0; + } + } + if (selectedButtons[buttonIndex.FadeAfter]) { + if (this.childrenDocs.indexOf(doc) < startIndex) { + doc.opacity = 0.5; + } + } + }); } @@ -359,9 +374,9 @@ export class PresentationView extends React.Component {
- + {this.renderPlayPauseButton()} - +
-- cgit v1.2.3-70-g09d2 From caf61bef345db0addd37c03bf2d0b0d2dd724c47 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Mon, 10 Jun 2019 14:17:27 -0400 Subject: Edge Case For Starting Presentation Fixed Navigation happens when u start document --- src/client/views/presentationview/PresentationView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 8d1be6af1..40e6885f0 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -320,6 +320,7 @@ export class PresentationView extends React.Component { } else { this.presStatus = true; this.startPresentation(0); + this.gotoDocument(0); } } -- 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') 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 074b4b2a3246ae86fda334629d40540dd2bbf633 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 11 Jun 2019 15:27:02 -0400 Subject: links can choose group type from preexisting group types --- src/client/util/LinkManager.ts | 2 +- src/client/views/nodes/LinkEditor.scss | 26 +++ src/client/views/nodes/LinkEditor.tsx | 370 ++++++++++++++++++--------------- src/client/views/nodes/LinkMenu.tsx | 43 ++-- 4 files changed, 252 insertions(+), 189 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 5e8e0475b..99fb4c6c0 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -57,7 +57,7 @@ export class LinkManager { } @observable public allLinks: Array = []; - @observable public allGroups: Map = new Map(); + @observable public allGroups: Map> = new Map(); public findAllRelatedLinks(anchor: Doc): Array { return LinkManager.Instance.allLinks.filter( diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 52ed26442..d3ac8cf19 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -80,5 +80,31 @@ } .linkEditor-metadata-row { display: flex; + justify-content: space-between; + input { + width: calc(50% - 2px); + } + } +} + +.linkEditor-dropdown { + width: 100%; + position: relative; + .linkEditor-options-wrapper { + width: 100%; + position: absolute; + top: 19px; + left: 0; + display: flex; + flex-direction: column; + } + .linkEditor-option { + background-color: red; + border: 1px solid $intermediate-color; + border-top: 0; + cursor: pointer; + &:hover { + background-color: $light-color-secondary; + } } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 14fdd26df..481d3bf37 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -21,85 +21,119 @@ import { string } from "prop-types"; library.add(faArrowLeft); library.add(faEllipsisV); +// this dropdown could be generalizeds +@observer +class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: string, setGroup: (groupId: string, group: string) => void }> { + @observable private _searchTerm: string = ""; + @observable private _groupType: string = this.props.groupType; + + @action + setSearchTerm(value: string) { + this._searchTerm = value; + } + + @action + setGroupType(value: string) { + this._groupType = value; + } + + createGroup(value: string) { + LinkManager.Instance.allGroups.set(value, []); + this.props.setGroup(this.props.groupId, value); + } + + renderOptions = (): JSX.Element[] => { + let allGroups: string[], searchTerm: string, results: string[], exactFound: boolean; + if (this._searchTerm !== "") { + allGroups = Array.from(LinkManager.Instance.allGroups.keys()); + searchTerm = this._searchTerm.toUpperCase(); + results = allGroups.filter(group => group.toUpperCase().indexOf(searchTerm) > -1); + exactFound = results.findIndex(group => group.toUpperCase() === searchTerm) > -1; + } else { + results = []; + exactFound = false; + } + + let options = []; + results.forEach(result => { + options.push(
{ this.props.setGroup(this.props.groupId, result); this.setGroupType(result); this.setSearchTerm("") }}>{result}
) + }); + + if (!exactFound && this._searchTerm !== "") { + options.push(
{ this.createGroup(this._searchTerm); this.setGroupType(this._searchTerm); this.setSearchTerm("") }}>Create new "{this._searchTerm}" group
) + } + + return options; + } + + render() { + return ( +
+ { this.setSearchTerm(e.target.value); this.setGroupType(e.target.value) }}> +
+ {this.renderOptions()} +
+
+ ) + } +} + + interface LinkEditorProps { sourceDoc: Doc; linkDoc: Doc; - groups: Map; - metadata: Map>; + // groups: Map; + // metadata: Map>; showLinks: () => void; } @observer 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); - // @observable private _tags: Array = Cast(this.props.linkDoc.linkTags, List); - - // @action - // onTitleChanged = (e: React.ChangeEvent) => { - // this._title = e.target.value; - // } + @observable private _groups: Map = new Map(); + @observable private _metadata: Map> = new Map(); + + constructor(props: LinkEditorProps) { + super(props); + + let groups = new Map(); + let metadata: Map> = new Map(); + let groupList = (Doc.AreProtosEqual(props.sourceDoc, Cast(props.linkDoc.anchor1, Doc, new Doc))) ? + Cast(props.linkDoc.anchor1Groups, listSpec(Doc), []) : Cast(props.linkDoc.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); + } else { + // promise doc + } + }) + this._groups = groups; + this._metadata = metadata; + } // @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(""); + // editGroup(groupId: string, value: string) { + // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; + // let groupDoc = this._groups.get(groupId); + // if (groupDoc) { + // groupDoc.proto!.type = value; + // LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, [groupDoc]); + // } // } - @action - 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; - LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, [groupDoc]); - } - } - @action addGroup = (e: React.MouseEvent): void => { // create new document for group @@ -107,149 +141,150 @@ export class LinkEditor extends React.Component { groupDoc.proto!.title = ""; groupDoc.proto!.metadata = new List([]); - this.props.groups.set(Utils.GenerateGuid(), groupDoc); + this._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._groups.values())); + } + @action + setGroup = (groupId: string, group: string): void => { 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())); + let groupDoc = this._groups.get(groupId); + if (groupDoc) { + groupDoc.proto!.type = group; + LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, [groupDoc]); + } } renderGroup(groupId: string, groupDoc: Doc) { - // let metadata = this.props.metadata.get(groupId); - // if (!metadata) { - // metadata = new Map(); - // } + console.log("testing", groupDoc["strawberry"], groupDoc["type"]); return ( - //
-
-

type:

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

type:

+ + {/* this.editGroup(groupId, e.target.value)}> */} + {/* this.editGroup(groupId, e.target.value)}> */} +
+ {this.renderMetadata(groupId)} +
- // {/* {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); + addMetadata = (groupType: string): void => { + let mdKeys = LinkManager.Instance.allGroups.get(groupType); + if (mdKeys) { + if (mdKeys.indexOf("new key") > -1) { + mdKeys.push("new key"); + } } else { - mdMap = new Map(); - mdMap.set(Utils.GenerateGuid(), mdDoc); + mdKeys = ["new key"]; } + LinkManager.Instance.allGroups.set(groupType, mdKeys); + console.log("md added", groupType, LinkManager.Instance.allGroups.get(groupType), LinkManager.Instance.allGroups); + + // // create new metadata doc + // let mdDoc = Docs.TextDocument(); + // mdDoc.proto!.title = ""; + // mdDoc.proto!.value = ""; + + // // append to map + // let mdMap = this._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 internal representation of metadata + // this._metadata.set(groupId, mdMap); - // 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())); + // // add to internatal representation of group + // let groupDoc = this._groups.get(groupId); + // if (groupDoc) { + // groupDoc.proto!.metadata = new List(Array.from(mdMap.values())); + // this._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._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); + // editMetadataTitle(groupId: string, mdId: string, value: string) { + // let groupMd = this._metadata.get(groupId); + // if (groupMd) { + // let mdDoc = groupMd.get(mdId); // if (mdDoc) { // mdDoc.proto!.title = value; // } // } + // // set group and link? // } // @action - // editMetadataValue = (groupId: string, mdId: string, value: string) => { - // let group = this.props.metadata.get(groupId); - // if (group) { - // let mdDoc = group.get(mdId); + // editMetadataValue(groupId: string, mdId: string, value: string) { + // let groupMd = this._metadata.get(groupId); + // if (groupMd) { + // let mdDoc = groupMd.get(mdId); // if (mdDoc) { // mdDoc.proto!.value = value; // } // } + // // set group and link? // } - @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)}> -
- ) - }) + 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.allGroups.get(groupType); + console.log("rendering md", groupType, groupMdKeys, LinkManager.Instance.allGroups); + if (groupMdKeys) { + groupMdKeys.forEach(key => { + metadata.push( +
+ + : + +
+ ) + }) + } } - 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)}> - //
- // ) - // }) - } + // let metadataMap = this._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)}> + //
+ // ) + // }) + // } - renderGroups() { - let groups: Array = []; - this.props.groups.forEach((groupDoc, groupId) => { - groups.push(this.renderGroup(groupId, groupDoc)) - }); - return groups; + return metadata; } render() { let destination = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + let groups: Array = []; + this._groups.forEach((groupDoc, groupId) => { + groups.push(this.renderGroup(groupId, groupDoc)) + }); + return (
@@ -258,8 +293,7 @@ export class LinkEditor extends React.Component { Groups:
- {this.renderGroups()} - + {groups}
); diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index ab478feae..e378ee1cb 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -48,7 +48,6 @@ export class LinkMenu extends React.Component { let linkItems: Array = []; links.forEach((links, group) => { - console.log("category is ", group); linkItems.push(

{group}:

@@ -59,6 +58,10 @@ export class LinkMenu extends React.Component { ) }); + if (linkItems.length === 0) { + linkItems.push(

no links have been created yet

); + } + return linkItems; } @@ -79,28 +82,28 @@ export class LinkMenu extends React.Component {
); } else { - 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(groupDoc => { - if (groupDoc instanceof Doc) { - let id = Utils.GenerateGuid(); - groups.set(id, groupDoc); + // 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(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); - } - }) + // 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 f9b472e6d69fcb99b8139cfcd6c36a8277962251 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Tue, 11 Jun 2019 17:52:18 -0400 Subject: Saving PresStatus Not Done, THere are bugs --- .../views/presentationview/PresentationElement.tsx | 41 +++++++++++++++- .../views/presentationview/PresentationView.tsx | 54 +++++++++++++++++++--- 2 files changed, 86 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index f346940a2..7928722f2 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; import React = require("react"); -import { Doc } from "../../../new_fields/Doc"; -import { NumCast, BoolCast, StrCast } from "../../../new_fields/Types"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { NumCast, BoolCast, StrCast, Cast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; import { observable, action, computed } from "mobx"; import "./PresentationView.scss"; @@ -10,6 +10,8 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faFile as fileSolid, faLocationArrow, faArrowUp, faSearch } from '@fortawesome/free-solid-svg-icons'; import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; +import { List } from "../../../new_fields/List"; +import { listSpec } from "../../../new_fields/Schema"; @@ -29,6 +31,8 @@ interface PresentationElementProps { allListElements: Doc[]; groupMappings: Map; presStatus: boolean; + presButtonBackUp: Doc; + presGroupBackUp: Doc; } @@ -60,6 +64,22 @@ export default class PresentationElement extends React.Component>; + let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); + if (castedList.length !== 0) { + // this.selectedButtons = castedList; + let selectedButtonOfDoc = Cast(castedList[this.props.index].selectedButtons, listSpec("boolean"), null); + if (selectedButtonOfDoc !== undefined) { + this.selectedButtons = selectedButtonOfDoc; + } + console.log("Entered!!"); + + } + console.log("Mounted!!"); + //this.props.presButtonBackUp.elIndex = this.props.index; + } /** * The function that is called to group docs together. It tries to group a doc @@ -171,6 +191,16 @@ export default class PresentationElement extends React.Component { + // let castedList = Cast(this.props.presButtonBackUp.selectedButtons, listSpec(Doc), null) as any as List>; + let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); + castedList[this.props.index].selectedButtons = new List(this.selectedButtons); + + //this.props.mainDocument.presButtonBackUp = this.props.presButtonBackUp; } /** @@ -198,6 +228,8 @@ export default class PresentationElement extends React.Component; setChildrenDocs: (docList: Doc[]) => void; presStatus: boolean; + presButtonBackUp: Doc; + presGroupBackUp: Doc; } @@ -57,14 +59,30 @@ class PresentationViewList extends React.Component { }); } + @action + initializeSelectedButtonDocs = (docList: Doc[]) => { + + let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); + if (castedList.length === 0) { + let newDocArray: List = new List(); + newDocArray.push(new Doc()); + this.props.presButtonBackUp.selectedButtonDocs = newDocArray; + } else { + castedList.push(new Doc()); + } + + + } + render() { const children = DocListCast(this.props.Document.data); this.initializeGroupIds(children); this.props.setChildrenDocs(children); + this.initializeSelectedButtonDocs(children); return (
- {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={index} mainDocument={this.props.Document} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} />)} + {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={index} mainDocument={this.props.Document} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} presButtonBackUp={this.props.presButtonBackUp} presGroupBackUp={this.props.presGroupBackUp} />)}
); } @@ -83,6 +101,28 @@ export class PresentationView extends React.Component { @observable childrenDocs: Doc[] = []; //variable to hold if presentation is started @observable presStatus: boolean = false; + //back-up so that presentation stays the way it's when refreshed + @observable presGroupBackUp: Doc = new Doc(); + @observable presButtonBackUp: Doc = new Doc(); + + @action + componentDidMount() { + let castedGroupBackUp: Doc = Cast(this.props.Document.presGroupBackUp, Doc, new Doc()); + let castedButtonBackUp: Doc = Cast(this.props.Document.presButtonBackUp, Doc, new Doc()); + // if (castedButtonBackUp === undefined) { + // this.props.Document.presButtonBackUp = new Doc(); + // } else { + this.presButtonBackUp = castedButtonBackUp; + // } + // if (castedGroupBackUp === undefined) { + // this.props.Document.presGroupBackUp = new Doc(); + // } else { + this.presGroupBackUp = castedGroupBackUp; + // + + // } + + } //observable means render is re-called every time variable is changed @observable @@ -326,12 +366,12 @@ export class PresentationView extends React.Component { @action resetPresentation = () => { - this.groupMappings = new Map(); - let selectedButtons: boolean[]; + //this.groupMappings = new Map(); + //let selectedButtons: boolean[]; this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { - selectedButtons = component.selected; - selectedButtons.forEach((val: boolean, index: number) => selectedButtons[index] = false); - doc.presentId = Utils.GenerateGuid(); + //selectedButtons = component.selected; + //selectedButtons.forEach((val: boolean, index: number) => selectedButtons[index] = false); + //doc.presentId = Utils.GenerateGuid(); doc.opacity = 1; }); this.props.Document.selectedDoc = 0; @@ -379,7 +419,7 @@ export class PresentationView extends React.Component { {this.renderPlayPauseButton()}
- + ); } -- cgit v1.2.3-70-g09d2 From 2c3b54d6e07c37a4f5fd52a49d6d60e7a8e5d2d2 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 11 Jun 2019 18:17:28 -0400 Subject: metadata types can be assigned to groups of links --- src/client/documents/Documents.ts | 2 +- src/client/views/nodes/LinkEditor.tsx | 76 +++++++++++++++++++++++++++++------ src/client/views/nodes/LinkMenu.tsx | 1 - 3 files changed, 64 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 731490d97..9f1501265 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -91,7 +91,7 @@ export namespace DocUtils { UndoManager.RunInBatch(() => { let groupDoc = Docs.TextDocument(); groupDoc.proto!.type = "*"; - groupDoc.proto!.metadata = new List([]); + groupDoc.proto!.metadata = Docs.TextDocument(); let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 481d3bf37..8d12bc30f 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -37,6 +37,7 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s this._groupType = value; } + @action createGroup(value: string) { LinkManager.Instance.allGroups.set(value, []); this.props.setGroup(this.props.groupId, value); @@ -81,12 +82,49 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s } } +@observer +class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc, mdKey: string, mdValue: string }> { + @observable private _key: string = this.props.mdKey; + @observable private _value: string = this.props.mdValue; + + @action + editMetadataKey = (value: string): void => { + // TODO: check that metadata doesnt already exist in group + let groupMdKeys = new Array(...LinkManager.Instance.allGroups.get(this.props.groupType)!); + if (groupMdKeys) { + let index = groupMdKeys.indexOf(this._key); + if (index > -1) { + groupMdKeys[index] = value; + } + else { + console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys) + } + } + + this._key = value; + LinkManager.Instance.allGroups.set(this.props.groupType, groupMdKeys); + } + + @action + editMetadataValue = (value: string): void => { + this.props.mdDoc[this._key] = value; + this._value = value; + } + + render() { + return ( +
+ this.editMetadataKey(e.target.value)}>: + this.editMetadataValue(e.target.value)}> +
+ ) + } +} + interface LinkEditorProps { sourceDoc: Doc; linkDoc: Doc; - // groups: Map; - // metadata: Map>; showLinks: () => void; } @@ -158,7 +196,6 @@ export class LinkEditor extends React.Component { } renderGroup(groupId: string, groupDoc: Doc) { - console.log("testing", groupDoc["strawberry"], groupDoc["type"]); return (
@@ -168,23 +205,28 @@ export class LinkEditor extends React.Component { {/* this.editGroup(groupId, e.target.value)}> */}
{this.renderMetadata(groupId)} - + {groupDoc["type"] === "*" ? <> : } + + {/* */}
) } + viewGroupAsTable = (): void => { + + } + @action addMetadata = (groupType: string): void => { let mdKeys = LinkManager.Instance.allGroups.get(groupType); if (mdKeys) { - if (mdKeys.indexOf("new key") > -1) { + if (mdKeys.indexOf("new key") === -1) { mdKeys.push("new key"); } } else { mdKeys = ["new key"]; } LinkManager.Instance.allGroups.set(groupType, mdKeys); - console.log("md added", groupType, LinkManager.Instance.allGroups.get(groupType), LinkManager.Instance.allGroups); // // create new metadata doc // let mdDoc = Docs.TextDocument(); @@ -239,6 +281,14 @@ export class LinkEditor extends React.Component { // // set group and link? // } + @action + editMetadataKey(groupId: string, value: string) { + let groupDoc = this._groups.get(groupId); + if (groupDoc) { + + } + } + renderMetadata(groupId: string) { let metadata: Array = []; let groupDoc = this._groups.get(groupId); @@ -246,15 +296,15 @@ export class LinkEditor extends React.Component { let mdDoc = Cast(groupDoc.proto!.metadata, Doc, new Doc); let groupType = StrCast(groupDoc.proto!.type); let groupMdKeys = LinkManager.Instance.allGroups.get(groupType); - console.log("rendering md", groupType, groupMdKeys, LinkManager.Instance.allGroups); if (groupMdKeys) { - groupMdKeys.forEach(key => { + groupMdKeys.forEach((key, index) => { metadata.push( -
- - : - -
+ + //
+ // + // : + // + //
) }) } diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index e378ee1cb..21b5807ae 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -38,7 +38,6 @@ export class LinkMenu extends React.Component { 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={""} />; } }); -- cgit v1.2.3-70-g09d2 From 9a93306ba382018ebf3c686117bd4301beda61ef Mon Sep 17 00:00:00 2001 From: madelinegr Date: Wed, 12 Jun 2019 15:33:51 -0400 Subject: BUtton status and pres status saved on refresh, only groups left --- src/client/views/MainView.tsx | 7 ++- .../views/presentationview/PresentationElement.tsx | 42 ++++++++++------ .../views/presentationview/PresentationView.tsx | 57 ++++++++++++++++------ 3 files changed, 73 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index c98e6e8fb..3d772916e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -200,12 +200,15 @@ export class MainView extends React.Component { whenActiveChanged={emptyFunction} bringToFront={emptyFunction} ContainingCollectionView={undefined} />; - const pres = mainCont ? FieldValue(Cast(mainCont.presentationView, Doc)) : undefined; + let castRes = mainCont ? FieldValue(Cast(mainCont.presentationView, Doc)) : undefined; + console.log("GETTING mainContent()"); + console.log(castRes instanceof Promise); + console.log(castRes); return {({ measureRef }) =>
{content} - {pres ? : null} + {castRes ? : null}
}
; diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 7928722f2..9fe69c2e3 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -1,9 +1,9 @@ import { observer } from "mobx-react"; import React = require("react"); -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { NumCast, BoolCast, StrCast, Cast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/FieldSymbols"; -import { observable, action, computed } from "mobx"; +import { observable, action, computed, runInAction } from "mobx"; import "./PresentationView.scss"; import { Utils } from "../../../Utils"; import { library } from '@fortawesome/fontawesome-svg-core'; @@ -64,21 +64,33 @@ export default class PresentationElement extends React.Component>; - let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); - if (castedList.length !== 0) { - // this.selectedButtons = castedList; - let selectedButtonOfDoc = Cast(castedList[this.props.index].selectedButtons, listSpec("boolean"), null); + let castedList = Cast(this.props.presButtonBackUp.selectedButtonDocs, listSpec(Doc)); + if (!castedList) { + this.props.presButtonBackUp.selectedButtonDocs = castedList = new List(); + } + // let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); + + console.log("Mounted!!"); + console.log("CastedList Len: ", castedList.length); + console.log("Index of doc: ", this.props.index); + + if (castedList.length <= this.props.index) { + console.log("Entered here by index : ", this.props.index); + castedList.push(new Doc()); + } else { + let curDoc: Doc = await castedList[this.props.index]; + let selectedButtonOfDoc = Cast(curDoc.selectedButtons, listSpec("boolean"), null); + console.log("Entered First Place"); if (selectedButtonOfDoc !== undefined) { - this.selectedButtons = selectedButtonOfDoc; + runInAction(() => this.selectedButtons = selectedButtonOfDoc); + console.log("Entered Second Place"); } - console.log("Entered!!"); - } - console.log("Mounted!!"); - //this.props.presButtonBackUp.elIndex = this.props.index; + + } /** @@ -195,9 +207,9 @@ export default class PresentationElement extends React.Component { + autoSaveButtonChange = async (index: buttonIndex) => { // let castedList = Cast(this.props.presButtonBackUp.selectedButtons, listSpec(Doc), null) as any as List>; - let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); + let castedList = (await DocListCastAsync(this.props.presButtonBackUp.selectedButtonDocs))!; castedList[this.props.index].selectedButtons = new List(this.selectedButtons); //this.props.mainDocument.presButtonBackUp = this.props.presButtonBackUp; diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 8b0b919fd..b872181ae 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -78,7 +78,7 @@ class PresentationViewList extends React.Component { const children = DocListCast(this.props.Document.data); this.initializeGroupIds(children); this.props.setChildrenDocs(children); - this.initializeSelectedButtonDocs(children); + //this.initializeSelectedButtonDocs(children); return (
@@ -105,23 +105,47 @@ export class PresentationView extends React.Component { @observable presGroupBackUp: Doc = new Doc(); @observable presButtonBackUp: Doc = new Doc(); - @action + + componentDidMount() { - let castedGroupBackUp: Doc = Cast(this.props.Document.presGroupBackUp, Doc, new Doc()); - let castedButtonBackUp: Doc = Cast(this.props.Document.presButtonBackUp, Doc, new Doc()); - // if (castedButtonBackUp === undefined) { - // this.props.Document.presButtonBackUp = new Doc(); - // } else { - this.presButtonBackUp = castedButtonBackUp; - // } - // if (castedGroupBackUp === undefined) { - // this.props.Document.presGroupBackUp = new Doc(); - // } else { - this.presGroupBackUp = castedGroupBackUp; - // - - // } + // let newDoc = new Doc(); + // let newDoc2 = new Doc(); + let castedGroupBackUp = Cast(this.props.Document.presGroupBackUp, Doc); + let castedButtonBackUp = Cast(this.props.Document.presButtonBackUp, Doc); + if (castedGroupBackUp instanceof Promise) { + castedGroupBackUp.then(doc => { + let toAssign = doc ? doc : new Doc(); + this.props.Document.presGroupBackUp = toAssign; + runInAction(() => this.presGroupBackUp = toAssign); + }); + } else { + runInAction(() => { + let toAssign = new Doc(); + this.presGroupBackUp = toAssign; + this.props.Document.presGroupBackUp = toAssign; + + }); + + } + + if (castedButtonBackUp instanceof Promise) { + castedButtonBackUp.then(doc => { + let toAssign = doc ? doc : new Doc(); + this.props.Document.presButtonBackUp = toAssign; + runInAction(() => this.presButtonBackUp = toAssign); + }); + + } else { + runInAction(() => { + let toAssign = new Doc(); + this.presButtonBackUp = toAssign; + this.props.Document.presButtonBackUp = toAssign; + }); + + } + let presStatusBackUp = BoolCast(this.props.Document.presStatus, null); + runInAction(() => this.presStatus = presStatusBackUp); } //observable means render is re-called every time variable is changed @@ -362,6 +386,7 @@ export class PresentationView extends React.Component { this.startPresentation(0); this.gotoDocument(0); } + this.props.Document.presStatus = this.presStatus; } @action -- cgit v1.2.3-70-g09d2 From e1fd270f1806ffd51174c835b335ceb4ebb2fe56 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 12 Jun 2019 16:20:46 -0400 Subject: created remove handlers for link metadata and groups --- src/client/documents/Documents.ts | 14 +- src/client/util/LinkManager.ts | 110 ++++++++++----- src/client/views/nodes/LinkBox.tsx | 38 ++--- src/client/views/nodes/LinkEditor.scss | 32 ++++- src/client/views/nodes/LinkEditor.tsx | 250 +++++++++++++++------------------ src/client/views/nodes/LinkMenu.scss | 2 +- src/client/views/nodes/LinkMenu.tsx | 33 +---- 7 files changed, 251 insertions(+), 228 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9f1501265..9517cbbda 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -89,9 +89,13 @@ export namespace DocUtils { // let protoSrc = source.proto ? source.proto : source; // let protoTarg = target.proto ? target.proto : target; UndoManager.RunInBatch(() => { - let groupDoc = Docs.TextDocument(); - groupDoc.proto!.type = "*"; - groupDoc.proto!.metadata = Docs.TextDocument(); + // let groupDoc1 = Docs.TextDocument(); + // groupDoc1.proto!.type = "*"; + // groupDoc1.proto!.metadata = Docs.TextDocument(); + + // let groupDoc2 = Docs.TextDocument(); + // groupDoc2.proto!.type = "*"; + // groupDoc2.proto!.metadata = Docs.TextDocument(); let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; @@ -99,11 +103,11 @@ export namespace DocUtils { // linkDoc.proto!.linkDescription = ""; linkDoc.proto!.anchor1 = source; linkDoc.proto!.anchor1Page = source.curPage; - linkDoc.proto!.anchor1Groups = new List([groupDoc]); + linkDoc.proto!.anchor1Groups = new List([]); linkDoc.proto!.anchor2 = target; linkDoc.proto!.anchor2Page = target.curPage; - linkDoc.proto!.anchor2Groups = new List([groupDoc]); + linkDoc.proto!.anchor2Groups = new List([]); // linkDoc.proto!.linkedTo = target; // linkDoc.proto!.linkedToPage = target.curPage; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 99fb4c6c0..cc8617052 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -9,6 +9,7 @@ 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"; +import { string } from "prop-types"; export namespace LinkUtils { export function findOppositeAnchor(link: Doc, anchor: Doc): Doc { @@ -40,14 +41,48 @@ export namespace LinkUtils { // } export function setAnchorGroups(link: Doc, anchor: Doc, groups: Doc[]) { + // console.log("setting groups for anchor", anchor["title"]); if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { link.anchor1Groups = new List(groups); } else { link.anchor2Groups = new List(groups); } } + + export function removeGroupFromAnchor(link: Doc, anchor: Doc, groupType: string) { + 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), []); + } + + let newGroups: Doc[] = []; + groups.forEach(groupDoc => { + if (groupDoc instanceof Doc && StrCast(groupDoc["type"]) !== groupType) { + newGroups.push(groupDoc); + } + }) + LinkUtils.setAnchorGroups(link, anchor, newGroups); + } } +/* + * link doc: + * - anchor1: doc + * - anchor1page: number + * - anchor1groups: list of group docs representing the groups anchor1 categorizes this link/anchor2 in + * - anchor2: doc + * - anchor2page: number + * - anchor2groups: list of group docs representing the groups anchor2 categorizes this link/anchor1 in + * + * group doc: + * - type: string representing the group type/name/category + * - metadata: doc representing the metadata kvps + * + * metadata doc: + * - user defined kvps + */ export class LinkManager { private static _instance: LinkManager; public static get Instance(): LinkManager { @@ -56,60 +91,57 @@ export class LinkManager { private constructor() { } - @observable public allLinks: Array = []; - @observable public allGroups: Map> = new Map(); + @observable public allLinks: Array = []; // list of link docs + @observable public allGroups: Map> = new Map(); // map of group type to list of its metadata keys 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))); } + // returns map of group type to anchor's links in that group type public findRelatedGroupedLinks(anchor: Doc): Map> { let related = this.findAllRelatedLinks(anchor); - let anchorGroups = new Map(); + let anchorGroups = new Map>(); related.forEach(link => { - // get groups of given doc - 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 = anchorGroups.get(groupType); // TODO: clean this up lol - if (group) group.push(link); - else group = [link]; - anchorGroups.set(groupType, group); - } else { - // promise doc - } - - }) - } - 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); - } - } + // get groups of given anchor categorizes this link/opposite anchor in + let groups = (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) ? Cast(link.anchor1Groups, listSpec(Doc), []) : Cast(link.anchor2Groups, listSpec(Doc), []); + if (groups.length > 0) { + groups.forEach(groupDoc => { + if (groupDoc instanceof Doc) { + let groupType = StrCast(groupDoc["type"]); + let group = anchorGroups.get(groupType); // TODO: clean this up lol + if (group) group.push(link); + else group = [link]; + anchorGroups.set(groupType, group); + } else { + // promise doc + } + + }) + } + 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); + } - // 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 anchorGroups; } - - - - // public findAnchorTags(link: Doc, source: Doc): Doc[] { - // if (source) - // } + public deleteGroup(groupType: string) { + let deleted = LinkManager.Instance.allGroups.delete(groupType); + if (deleted) { + LinkManager.Instance.allLinks.forEach(linkDoc => { + LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc["anchor1"], Doc, new Doc), groupType); + LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc["anchor2"], Doc, new Doc), groupType); + }) + } + } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index ebca1dc69..5597bb1aa 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -41,23 +41,23 @@ export class LinkBox extends React.Component { this.props.showEditor(); } - @action - onDeleteButtonPressed = async (e: React.PointerEvent): Promise => { - e.stopPropagation(); - const [linkedFrom, linkedTo] = await Promise.all([Cast(this.props.linkDoc.linkedFrom, Doc), Cast(this.props.linkDoc.linkedTo, Doc)]); - if (linkedFrom) { - const linkedToDocs = Cast(linkedFrom.linkedToDocs, listSpec(Doc)); - if (linkedToDocs) { - linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc), 1); - } - } - if (linkedTo) { - const linkedFromDocs = Cast(linkedTo.linkedFromDocs, listSpec(Doc)); - if (linkedFromDocs) { - linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc), 1); - } - } - } + // @action + // onDeleteButtonPressed = async (e: React.PointerEvent): Promise => { + // e.stopPropagation(); + // const [linkedFrom, linkedTo] = await Promise.all([Cast(this.props.linkDoc.linkedFrom, Doc), Cast(this.props.linkDoc.linkedTo, Doc)]); + // if (linkedFrom) { + // const linkedToDocs = Cast(linkedFrom.linkedToDocs, listSpec(Doc)); + // if (linkedToDocs) { + // linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc), 1); + // } + // } + // if (linkedTo) { + // const linkedFromDocs = Cast(linkedTo.linkedFromDocs, listSpec(Doc)); + // if (linkedFromDocs) { + // linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc), 1); + // } + // } + // } render() { @@ -80,8 +80,8 @@ export class LinkBox extends React.Component {
-
-
+ {/*
+
*/} ); diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index d3ac8cf19..b56f3046a 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -74,6 +74,7 @@ } .linkEditor-group-row { display: flex; + margin-bottom: 6px; .linkEditor-group-row-label { margin-right: 6px; } @@ -81,8 +82,17 @@ .linkEditor-metadata-row { display: flex; justify-content: space-between; + margin-bottom: 6px; input { - width: calc(50% - 2px); + width: calc(50% - 18px); + height: 20px; + } + button { + width: 20px; + height: 20px; + margin-left: 6px; + padding: 0; + font-size: 14px; } } } @@ -90,6 +100,7 @@ .linkEditor-dropdown { width: 100%; position: relative; + z-index: 999; .linkEditor-options-wrapper { width: 100%; position: absolute; @@ -107,4 +118,23 @@ background-color: $light-color-secondary; } } +} + +.linkEditor-group-buttons { + height: 20px; + display: flex; + justify-content: space-between; + button { + width: 31%; + height: 20px; + margin-left: 6px; + padding: 0; + font-size: 10px; + &:first-child { // delete + font-size: 14px; + } + &:disabled { // delete + background-color: gray; + } + } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 8d12bc30f..05e05c2ee 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -1,11 +1,7 @@ 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 { List } from "../../../new_fields/List"; @@ -21,7 +17,7 @@ import { string } from "prop-types"; library.add(faArrowLeft); library.add(faEllipsisV); -// this dropdown could be generalizeds +// this dropdown could be generalized @observer class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: string, setGroup: (groupId: string, group: string) => void }> { @observable private _searchTerm: string = ""; @@ -63,7 +59,7 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s if (!exactFound && this._searchTerm !== "") { options.push(
{ this.createGroup(this._searchTerm); this.setGroupType(this._searchTerm); this.setSearchTerm("") }}>Create new "{this._searchTerm}" group
) + onClick={() => { this.createGroup(this._searchTerm); this.setGroupType(this._searchTerm); this.setSearchTerm("") }}>Define new "{this._searchTerm}" relationship) } return options; @@ -82,6 +78,8 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s } } + + @observer class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc, mdKey: string, mdValue: string }> { @observable private _key: string = this.props.mdKey; @@ -111,11 +109,28 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc this._value = value; } + @action + removeMetadata = (): void => { + let groupMdKeys = new Array(...LinkManager.Instance.allGroups.get(this.props.groupType)!); + if (groupMdKeys) { + let index = groupMdKeys.indexOf(this._key); + if (index > -1) { + groupMdKeys.splice(index, 1); + } + else { + console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys) + } + } + this._key = ""; + LinkManager.Instance.allGroups.set(this.props.groupType, groupMdKeys); + } + render() { return (
this.editMetadataKey(e.target.value)}>: this.editMetadataValue(e.target.value)}> +
) } @@ -131,85 +146,129 @@ interface LinkEditorProps { @observer export class LinkEditor extends React.Component { - @observable private _groups: Map = new Map(); - @observable private _metadata: Map> = new Map(); + @observable private _groups: Map = new Map(); // map of temp group id to the corresponding group doc constructor(props: LinkEditorProps) { super(props); let groups = new Map(); - let metadata: Map> = new Map(); let groupList = (Doc.AreProtosEqual(props.sourceDoc, Cast(props.linkDoc.anchor1, Doc, new Doc))) ? Cast(props.linkDoc.anchor1Groups, listSpec(Doc), []) : Cast(props.linkDoc.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); } else { // promise doc } }) this._groups = groups; - this._metadata = metadata; } - // @action - // editGroup(groupId: string, value: string) { - // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; - // let groupDoc = this._groups.get(groupId); - // if (groupDoc) { - // groupDoc.proto!.type = value; - // 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([]); + addGroup = (): void => { + console.log("before adding", ...Array.from(this._groups.keys())); + + let index = Array.from(this._groups.values()).findIndex(groupDoc => { + return groupDoc["type"] === "New Group"; + }) + if (index === -1) { + // create new document for group + let groupDoc = Docs.TextDocument(); + groupDoc.proto!.type = "New Group"; + groupDoc.proto!.metadata = Docs.TextDocument(); - this._groups.set(Utils.GenerateGuid(), groupDoc); + this._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._groups.values())); + let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; + LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); + } + + + // console.log("set anchor groups for", this.props.sourceDoc["title"]); + console.log("after adding", ...Array.from(this._groups.keys())); } @action - setGroup = (groupId: string, group: string): void => { + setGroupType = (groupId: string, groupType: string): void => { + console.log("setting for ", groupId); let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; let groupDoc = this._groups.get(groupId); if (groupDoc) { - groupDoc.proto!.type = group; - LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, [groupDoc]); + console.log("found group doc"); + groupDoc.proto!.type = groupType; + + this._groups.set(groupId, groupDoc); + + let gd = this._groups.get(groupId); + if (gd) + console.log("just created", StrCast(gd["type"])); + + LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); + console.log("set", Array.from(this._groups.values()).length) + } + + let anchor1groups: string[] = []; + Cast(this.props.linkDoc.anchor1Groups, listSpec(Doc), []).forEach(doc => { + if (doc instanceof Doc) { + anchor1groups.push(StrCast(doc.proto!.type)); + } else { + console.log("promise"); + } + }) + let anchor2groups: string[] = []; + Cast(this.props.linkDoc.anchor2Groups, listSpec(Doc), []).forEach(doc => { + if (doc instanceof Doc) { + anchor2groups.push(StrCast(doc.proto!.type)); + } else { + console.log("promise"); + } + }) + console.log("groups for anchors; anchor1: [", ...anchor1groups, "] ; anchor2: [", ...anchor2groups, "]") + } + + removeGroupFromLink = (groupId: string, groupType: string) => { + // this._groups.delete(groupId); + let groupDoc = this._groups.get(groupId); + if (groupDoc) { + LinkUtils.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType); + this._groups.delete(groupId); + } + // LinkUtils.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); + console.log("\nremoved", groupId, "remaining", ...Array.from(this._groups.keys()), "\n"); + } + + deleteGroup = (groupId: string, groupType: string) => { + let groupDoc = this._groups.get(groupId); + if (groupDoc) { + LinkManager.Instance.deleteGroup(groupType); + this._groups.delete(groupId); } } renderGroup(groupId: string, groupDoc: Doc) { - return ( -
-
-

type:

- - {/* this.editGroup(groupId, e.target.value)}> */} - {/* this.editGroup(groupId, e.target.value)}> */} + let type = StrCast(groupDoc["type"]); + if ((type && LinkManager.Instance.allGroups.get(type)) || type === "New Group") { + return ( +
+
+

type:

+ +
+ {this.renderMetadata(groupId)} +
+ {groupDoc["type"] === "New Group" ? : + } + {/* */} + + + +
- {this.renderMetadata(groupId)} - {groupDoc["type"] === "*" ? <> : } - - {/* */} -
- ) + ) + } else { + return <> + } } viewGroupAsTable = (): void => { @@ -228,65 +287,6 @@ export class LinkEditor extends React.Component { } LinkManager.Instance.allGroups.set(groupType, mdKeys); - // // create new metadata doc - // let mdDoc = Docs.TextDocument(); - // mdDoc.proto!.title = ""; - // mdDoc.proto!.value = ""; - - // // append to map - // let mdMap = this._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._metadata.set(groupId, mdMap); - - // // add to internatal representation of group - // let groupDoc = this._groups.get(groupId); - // if (groupDoc) { - // groupDoc.proto!.metadata = new List(Array.from(mdMap.values())); - // this._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._groups.values())); - } - - // @action - // editMetadataTitle(groupId: string, mdId: string, value: string) { - // let groupMd = this._metadata.get(groupId); - // if (groupMd) { - // let mdDoc = groupMd.get(mdId); - // if (mdDoc) { - // mdDoc.proto!.title = value; - // } - // } - // // set group and link? - // } - - // @action - // editMetadataValue(groupId: string, mdId: string, value: string) { - // let groupMd = this._metadata.get(groupId); - // if (groupMd) { - // let mdDoc = groupMd.get(mdId); - // if (mdDoc) { - // mdDoc.proto!.value = value; - // } - // } - // // set group and link? - // } - - @action - editMetadataKey(groupId: string, value: string) { - let groupDoc = this._groups.get(groupId); - if (groupDoc) { - - } } renderMetadata(groupId: string) { @@ -300,30 +300,10 @@ export class LinkEditor extends React.Component { groupMdKeys.forEach((key, index) => { metadata.push( - //
- // - // : - // - //
) }) } } - - - // let metadataMap = this._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; } @@ -340,10 +320,10 @@ export class LinkEditor extends React.Component {

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

- Groups: - + Relationships: +
- {groups} + {groups.length > 0 ? groups :
There are currently no relationships associated with this link.
}
); diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index 860f31d8a..7e031b897 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -40,7 +40,7 @@ display: flex; } &:hover .link-menu-item-content { - width: calc(100% - 72px); + width: calc(100% - 42px); } } .link-menu-item-buttons { diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 21b5807ae..47bd6c3eb 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -32,7 +32,7 @@ export class LinkMenu extends React.Component { // }); // } - renderLinkGroupItems(links: Doc[]) { + renderGroup(links: Doc[]) { let source = this.props.docView.Document; return links.map(link => { let destination = LinkUtils.findOppositeAnchor(link, source); @@ -43,7 +43,7 @@ export class LinkMenu extends React.Component { }); } - renderLinkItems = (links: Map>): Array => { + renderLinks = (links: Map>): Array => { let linkItems: Array = []; links.forEach((links, group) => { @@ -51,7 +51,7 @@ export class LinkMenu extends React.Component {

{group}:

- {this.renderLinkGroupItems(links)} + {this.renderGroup(links)}
) @@ -65,10 +65,7 @@ export class LinkMenu extends React.Component { } render() { - //get list of links from document - // let linkFrom = DocListCast(this.props.docView.props.Document.linkedFromDocs); - // let linkTo = DocListCast(this.props.docView.props.Document.linkedToDocs); - let related = LinkManager.Instance.findRelatedGroupedLinks(this.props.docView.props.Document); + let related: Map = LinkManager.Instance.findRelatedGroupedLinks(this.props.docView.props.Document); if (this._editingLink === undefined) { return (
@@ -76,31 +73,11 @@ export class LinkMenu extends React.Component {
{/* {this.renderLinkItems(linkTo, "linkedTo", "Destination: ")} {this.renderLinkItems(linkFrom, "linkedFrom", "Source: ")} */} - {this.renderLinkItems(related)} + {this.renderLinks(related)}
); } else { - // 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(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)}> ); -- cgit v1.2.3-70-g09d2 From 2843baddfa1fe4f46762c63b732eedb5ea7c6e41 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 12 Jun 2019 18:23:22 -0400 Subject: link group can be viewed as a table --- src/client/views/nodes/LinkEditor.tsx | 69 ++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 05e05c2ee..3886687f1 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -13,6 +13,7 @@ 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"; +import { SetupDrag } from "../../util/DragManager"; library.add(faArrowLeft); library.add(faEllipsisV); @@ -176,7 +177,7 @@ export class LinkEditor extends React.Component { // create new document for group let groupDoc = Docs.TextDocument(); groupDoc.proto!.type = "New Group"; - groupDoc.proto!.metadata = Docs.TextDocument(); + // groupDoc.proto!.metadata = Docs.TextDocument(); this._groups.set(Utils.GenerateGuid(), groupDoc); @@ -246,6 +247,55 @@ export class LinkEditor extends React.Component { } } + copyGroup = (groupId: string, groupType: string) => { + let oppAnchor = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + let groupList = (Doc.AreProtosEqual(oppAnchor, Cast(this.props.linkDoc.anchor1, Doc, new Doc))) ? + Cast(this.props.linkDoc.anchor1Groups, listSpec(Doc), []) : Cast(this.props.linkDoc.anchor2Groups, listSpec(Doc), []); + // if group already exists on opposite anchor, copy value + let index = groupList.findIndex(groupDoc => { + if (groupDoc instanceof Doc) { + return StrCast(groupDoc["type"]) === groupType; + } else { + return false; + } + }) + // TODO: clean + // if (index > 0) { + // let thisGroupDoc = this._groups.get(groupId); + // let oppGroupDoc = groupList[index]; + // let keys = LinkManager.Instance.allGroups.get(groupType); + // if (keys) { + // keys.forEach(key => { + // if (thisGroupDoc && oppGroupDoc instanceof Doc) { // TODO: clean + // let val = thisGroupDoc[key] === undefined ? "" : StrCast(thisGroupDoc[key]); + // oppGroupDoc[key] = val; + // } + // // mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key]) + // // oppGroupDoc[key] = thisGroupDoc[key]; + // }) + // } + // // LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [oppGroupDoc]); + // } else { + let thisGroupDoc = this._groups.get(groupId); + let newGroupDoc = Docs.TextDocument(); + newGroupDoc.proto!.type = groupType; + let keys = LinkManager.Instance.allGroups.get(groupType); + if (keys) { + keys.forEach(key => { + if (thisGroupDoc) { // TODO: clean + let val = thisGroupDoc[key] === undefined ? "" : StrCast(thisGroupDoc[key]); + newGroupDoc[key] = val; + } + // mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key]) + // oppGroupDoc[key] = thisGroupDoc[key]; + }) + } + LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [newGroupDoc]); // TODO: fix to append to list + // } + + // else create group on opposite anchor + } + renderGroup(groupId: string, groupDoc: Doc) { let type = StrCast(groupDoc["type"]); if ((type && LinkManager.Instance.allGroups.get(type)) || type === "New Group") { @@ -259,10 +309,10 @@ export class LinkEditor extends React.Component {
{groupDoc["type"] === "New Group" ? : } - {/* */} + {this.viewGroupAsTable(groupId, type)}
) @@ -271,10 +321,20 @@ export class LinkEditor extends React.Component { } } - viewGroupAsTable = (): void => { - + viewGroupAsTable(groupId: string, groupType: string) { + let keys = LinkManager.Instance.allGroups.get(groupType); + let groupDoc = this._groups.get(groupId); + if (keys && groupDoc) { + console.log("keys:", ...keys); + let createTable = action(() => Docs.SchemaDocument(keys!, [Cast(groupDoc!["metadata"], Doc, new Doc)], { width: 200, height: 200, title: groupType + " table" })); + let ref = React.createRef(); + return
+ } else { + return <> + } } + @action addMetadata = (groupType: string): void => { let mdKeys = LinkManager.Instance.allGroups.get(groupType); @@ -286,7 +346,6 @@ export class LinkEditor extends React.Component { mdKeys = ["new key"]; } LinkManager.Instance.allGroups.set(groupType, mdKeys); - } renderMetadata(groupId: string) { -- cgit v1.2.3-70-g09d2 From 5c60cd95b3f766a18dee95ead388dd9f9603d138 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Wed, 12 Jun 2019 18:49:37 -0400 Subject: Groups saving on refresh done --- .../views/presentationview/PresentationElement.tsx | 25 ++++++++++----- .../views/presentationview/PresentationView.tsx | 36 ++++++++++++++++++++-- 2 files changed, 50 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 9fe69c2e3..53e6f903b 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -71,22 +71,14 @@ export default class PresentationElement extends React.Component(); } - // let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); - - console.log("Mounted!!"); - console.log("CastedList Len: ", castedList.length); - console.log("Index of doc: ", this.props.index); if (castedList.length <= this.props.index) { - console.log("Entered here by index : ", this.props.index); castedList.push(new Doc()); } else { let curDoc: Doc = await castedList[this.props.index]; let selectedButtonOfDoc = Cast(curDoc.selectedButtons, listSpec("boolean"), null); - console.log("Entered First Place"); if (selectedButtonOfDoc !== undefined) { runInAction(() => this.selectedButtons = selectedButtonOfDoc); - console.log("Entered Second Place"); } } @@ -167,6 +159,21 @@ export default class PresentationElement extends React.Component { + let castedList: List = new List(); + this.props.presGroupBackUp.groupDocs = castedList; + this.props.groupMappings.forEach((docArray: Doc[], id: String) => { + let newGroupDoc = new Doc(); + castedList.push(newGroupDoc); + newGroupDoc.presentIdStore = id.toString(); + newGroupDoc.grouping = new List(docArray); + }); } @@ -180,6 +187,8 @@ export default class PresentationElement extends React.Component { * docs that are in the group, so that mapping won't be disrupted. */ @action - initializeGroupIds = (docList: Doc[]) => { - docList.forEach((doc: Doc, index: number) => { + initializeGroupIds = async (docList: Doc[]) => { + docList.forEach(async (doc: Doc, index: number) => { let docGuid = StrCast(doc.presentId, null); //checking if part of group - if (!this.props.groupMappings.has(docGuid)) { + let storedGuids: string[] = []; + let castedGroupDocs = await DocListCastAsync(this.props.presGroupBackUp.groupDocs); + if (castedGroupDocs !== undefined) { + castedGroupDocs.forEach((doc: Doc) => { + let storedGuid = StrCast(doc.presentIdStore, null); + if (storedGuid) { + storedGuids.push(storedGuid); + } + + }); + } + if (!this.props.groupMappings.has(docGuid) && !storedGuids.includes(docGuid)) { doc.presentId = Utils.GenerateGuid(); } }); @@ -117,6 +128,11 @@ export class PresentationView extends React.Component { let toAssign = doc ? doc : new Doc(); this.props.Document.presGroupBackUp = toAssign; runInAction(() => this.presGroupBackUp = toAssign); + if (doc) { + if (toAssign[Id] === doc[Id]) { + this.retrieveGroupMappings(); + } + } }); } else { runInAction(() => { @@ -148,6 +164,20 @@ export class PresentationView extends React.Component { runInAction(() => this.presStatus = presStatusBackUp); } + retrieveGroupMappings = async () => { + //runInAction(() => this.groupMappings = new Map()); + let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); + if (castedGroupDocs !== undefined) { + castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { + let castedGrouping = await DocListCastAsync(groupDoc.grouping); + let castedKey = StrCast(groupDoc.presentIdStore, null); + if (castedGrouping !== undefined && castedKey !== undefined) { + this.groupMappings.set(castedKey, castedGrouping); + } + }); + } + } + //observable means render is re-called every time variable is changed @observable collapsed: boolean = false; -- cgit v1.2.3-70-g09d2 From 7de0db8000aab06ccc8f973a50734cfdee93a388 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 13 Jun 2019 11:43:21 -0400 Subject: Documentation for saving and loading presentation state --- .../views/presentationview/PresentationElement.tsx | 16 ++++++++--- .../views/presentationview/PresentationView.tsx | 31 +++++++++------------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 53e6f903b..c58570798 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -66,14 +66,15 @@ export default class PresentationElement extends React.Component>; + //get the list that stores docs that keep track of buttons let castedList = Cast(this.props.presButtonBackUp.selectedButtonDocs, listSpec(Doc)); if (!castedList) { this.props.presButtonBackUp.selectedButtonDocs = castedList = new List(); } - + //if this is the first time this doc mounts, push a doc for it to store if (castedList.length <= this.props.index) { castedList.push(new Doc()); + //otherwise update the selected buttons depending on storage. } else { let curDoc: Doc = await castedList[this.props.index]; let selectedButtonOfDoc = Cast(curDoc.selectedButtons, listSpec("boolean"), null); @@ -164,14 +165,20 @@ export default class PresentationElement extends React.Component { let castedList: List = new List(); this.props.presGroupBackUp.groupDocs = castedList; this.props.groupMappings.forEach((docArray: Doc[], id: String) => { + //create a new doc for each group let newGroupDoc = new Doc(); castedList.push(newGroupDoc); + //store the id of the group in the doc newGroupDoc.presentIdStore = id.toString(); + //store the doc array which represents the group in the doc newGroupDoc.grouping = new List(docArray); }); @@ -215,13 +222,14 @@ export default class PresentationElement extends React.Component { - // let castedList = Cast(this.props.presButtonBackUp.selectedButtons, listSpec(Doc), null) as any as List>; let castedList = (await DocListCastAsync(this.props.presButtonBackUp.selectedButtonDocs))!; castedList[this.props.index].selectedButtons = new List(this.selectedButtons); - //this.props.mainDocument.presButtonBackUp = this.props.presButtonBackUp; } /** diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 0ba14e8ab..d3365725b 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -55,6 +55,7 @@ class PresentationViewList extends React.Component { //checking if part of group let storedGuids: string[] = []; let castedGroupDocs = await DocListCastAsync(this.props.presGroupBackUp.groupDocs); + //making sure the docs that were in groups, which were stored, to not get new guids. if (castedGroupDocs !== undefined) { castedGroupDocs.forEach((doc: Doc) => { let storedGuid = StrCast(doc.presentIdStore, null); @@ -70,26 +71,10 @@ class PresentationViewList extends React.Component { }); } - @action - initializeSelectedButtonDocs = (docList: Doc[]) => { - - let castedList = DocListCast(this.props.presButtonBackUp.selectedButtonDocs); - if (castedList.length === 0) { - let newDocArray: List = new List(); - newDocArray.push(new Doc()); - this.props.presButtonBackUp.selectedButtonDocs = newDocArray; - } else { - castedList.push(new Doc()); - } - - - } - render() { const children = DocListCast(this.props.Document.data); this.initializeGroupIds(children); this.props.setChildrenDocs(children); - //this.initializeSelectedButtonDocs(children); return (
@@ -119,10 +104,10 @@ export class PresentationView extends React.Component { componentDidMount() { - // let newDoc = new Doc(); - // let newDoc2 = new Doc(); + //getting both backUp documents let castedGroupBackUp = Cast(this.props.Document.presGroupBackUp, Doc); let castedButtonBackUp = Cast(this.props.Document.presButtonBackUp, Doc); + //if instantiated before if (castedGroupBackUp instanceof Promise) { castedGroupBackUp.then(doc => { let toAssign = doc ? doc : new Doc(); @@ -134,6 +119,7 @@ export class PresentationView extends React.Component { } } }); + //if never instantiated a store doc yet } else { runInAction(() => { let toAssign = new Doc(); @@ -143,6 +129,7 @@ export class PresentationView extends React.Component { }); } + //if instantiated before if (castedButtonBackUp instanceof Promise) { castedButtonBackUp.then(doc => { @@ -151,6 +138,7 @@ export class PresentationView extends React.Component { runInAction(() => this.presButtonBackUp = toAssign); }); + //if never instantiated a store doc yet } else { runInAction(() => { let toAssign = new Doc(); @@ -160,12 +148,17 @@ export class PresentationView extends React.Component { } + + //storing the presentation status,ie. whether it was stopped or playing let presStatusBackUp = BoolCast(this.props.Document.presStatus, null); runInAction(() => this.presStatus = presStatusBackUp); } + /** + * This is the function that is called to retrieve the groups that have been stored and + * push them to the groupMappings. + */ retrieveGroupMappings = async () => { - //runInAction(() => this.groupMappings = new Map()); let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); if (castedGroupDocs !== undefined) { castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { -- cgit v1.2.3-70-g09d2 From bd829aa067912baa08c18c09f5dcfcd3853e45ad Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Jun 2019 11:47:50 -0400 Subject: anchors show up in link group table and metadata values get copied on transfer --- src/client/util/LinkManager.ts | 27 +++++++++++++++++++++++++++ src/client/views/nodes/LinkEditor.tsx | 20 +++++++++++++++----- 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index cc8617052..02ecec88a 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -134,6 +134,33 @@ export class LinkManager { return anchorGroups; } + public findMetadataInGroup(groupType: string) { + let md: Doc[] = []; + let allLinks = LinkManager.Instance.allLinks; + // for every link find its groups + // allLinks.forEach(linkDoc => { + // let anchor1groups = LinkManager.Instance.findRelatedGroupedLinks(Cast(linkDoc["anchor1"], Doc, new Doc)); + // if (anchor1groups.get(groupType)) { + // md.push(linkDoc["anchor1"]["group"]) + // } + // }) + allLinks.forEach(linkDoc => { + let anchor1Groups = Cast(linkDoc["anchor1Groups"], listSpec(Doc), []); + let anchor2Groups = Cast(linkDoc["anchor2Groups"], listSpec(Doc), []); + [...anchor1Groups, ...anchor2Groups].forEach(groupDoc => { + if (groupDoc instanceof Doc) { + if (StrCast(groupDoc["type"]) === groupType) { + md.push(Cast(groupDoc["metadata"], Doc, new Doc)); + } + } else { + // TODO: promise + } + }) + + }) + return md; + } + public deleteGroup(groupType: string) { let deleted = LinkManager.Instance.allGroups.delete(groupType); if (deleted) { diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 3886687f1..8860ac582 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -175,9 +175,14 @@ export class LinkEditor extends React.Component { }) if (index === -1) { // create new document for group + let mdDoc = Docs.TextDocument(); + mdDoc.proto!.anchor1 = this.props.sourceDoc["title"]; + mdDoc.proto!.anchor2 = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc)["title"]; + let groupDoc = Docs.TextDocument(); groupDoc.proto!.type = "New Group"; - // groupDoc.proto!.metadata = Docs.TextDocument(); + groupDoc.proto!.metadata = mdDoc; + this._groups.set(Utils.GenerateGuid(), groupDoc); @@ -277,19 +282,23 @@ export class LinkEditor extends React.Component { // // LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [oppGroupDoc]); // } else { let thisGroupDoc = this._groups.get(groupId); + let thisMdDoc = Cast(thisGroupDoc!["metadata"], Doc, new Doc); let newGroupDoc = Docs.TextDocument(); - newGroupDoc.proto!.type = groupType; + let newMdDoc = Docs.TextDocument(); let keys = LinkManager.Instance.allGroups.get(groupType); if (keys) { keys.forEach(key => { if (thisGroupDoc) { // TODO: clean - let val = thisGroupDoc[key] === undefined ? "" : StrCast(thisGroupDoc[key]); - newGroupDoc[key] = val; + let val = thisMdDoc[key] === undefined ? "" : StrCast(thisMdDoc[key]); + newMdDoc[key] = val; } // mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key]) // oppGroupDoc[key] = thisGroupDoc[key]; }) } + newGroupDoc.proto!.type = groupType; + newGroupDoc.proto!.metadata = newMdDoc; + LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [newGroupDoc]); // TODO: fix to append to list // } @@ -326,7 +335,8 @@ export class LinkEditor extends React.Component { let groupDoc = this._groups.get(groupId); if (keys && groupDoc) { console.log("keys:", ...keys); - let createTable = action(() => Docs.SchemaDocument(keys!, [Cast(groupDoc!["metadata"], Doc, new Doc)], { width: 200, height: 200, title: groupType + " table" })); + let docs: Doc[] = LinkManager.Instance.findMetadataInGroup(groupType); + let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys!], docs, { width: 200, height: 200, title: groupType + " table" })); let ref = React.createRef(); return
} else { -- cgit v1.2.3-70-g09d2 From 8c70b822ddd6f2a92d3f3d30cd54c47efad38605 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Jun 2019 12:05:06 -0400 Subject: updated styling on link editor --- .../collectionFreeForm/CollectionFreeFormLinkView.tsx | 3 ++- src/client/views/nodes/LinkEditor.scss | 18 +++++++++++++----- src/client/views/nodes/LinkEditor.tsx | 17 +++++++++-------- 3 files changed, 24 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 301b769af..a1a222675 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -46,7 +46,8 @@ export class CollectionFreeFormLinkView extends React.Component text += StrCast(l.title) + "(" + StrCast(l.linkDescription) + "), "); - text = text.substr(0, text.length - 2); + // text = text.substr(0, text.length - 2); + text = ""; return ( <> {
{this.renderMetadata(groupId)}
- {groupDoc["type"] === "New Group" ? : - } - - - + {groupDoc["type"] === "New Group" ? : + } + + {/* + */} {this.viewGroupAsTable(groupId, type)}
@@ -338,9 +339,9 @@ export class LinkEditor extends React.Component { let docs: Doc[] = LinkManager.Instance.findMetadataInGroup(groupType); let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys!], docs, { width: 200, height: 200, title: groupType + " table" })); let ref = React.createRef(); - return
+ return
} else { - return <> + return } } -- cgit v1.2.3-70-g09d2 From 15d2dbc6935df7667733c267de07961e51df5f00 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Jun 2019 12:37:47 -0400 Subject: link table minor fixes --- src/client/util/LinkManager.ts | 11 ++++++++++- src/client/views/nodes/LinkEditor.tsx | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 02ecec88a..fab0efb4e 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -147,7 +147,16 @@ export class LinkManager { allLinks.forEach(linkDoc => { let anchor1Groups = Cast(linkDoc["anchor1Groups"], listSpec(Doc), []); let anchor2Groups = Cast(linkDoc["anchor2Groups"], listSpec(Doc), []); - [...anchor1Groups, ...anchor2Groups].forEach(groupDoc => { + anchor1Groups.forEach(groupDoc => { + if (groupDoc instanceof Doc) { + if (StrCast(groupDoc["type"]) === groupType) { + md.push(Cast(groupDoc["metadata"], Doc, new Doc)); + } + } else { + // TODO: promise + } + }) + anchor2Groups.forEach(groupDoc => { if (groupDoc instanceof Doc) { if (StrCast(groupDoc["type"]) === groupType) { md.push(Cast(groupDoc["metadata"], Doc, new Doc)); diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index bab87fc12..370fdee1d 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -286,6 +286,8 @@ export class LinkEditor extends React.Component { let thisMdDoc = Cast(thisGroupDoc!["metadata"], Doc, new Doc); let newGroupDoc = Docs.TextDocument(); let newMdDoc = Docs.TextDocument(); + newMdDoc.proto!.anchor1 = StrCast(thisMdDoc["anchor2"]); + newMdDoc.proto!.anchor2 = StrCast(thisMdDoc["anchor1"]); let keys = LinkManager.Instance.allGroups.get(groupType); if (keys) { keys.forEach(key => { -- cgit v1.2.3-70-g09d2 From bd864051d6bbec3f1ac09ab6c66f9bb62e02411b Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Jun 2019 15:41:08 -0400 Subject: fixed lint issues --- src/client/util/LinkManager.ts | 38 ++++++++++---------- src/client/views/nodes/LinkEditor.tsx | 67 +++++++++++++++++------------------ 2 files changed, 51 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index fab0efb4e..c0c607b01 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -52,17 +52,17 @@ export namespace LinkUtils { export function removeGroupFromAnchor(link: Doc, anchor: Doc, groupType: string) { let groups = []; if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { - groups = Cast(link["anchor1Groups"], listSpec(Doc), []); + groups = Cast(link.proto!.anchor1Groups, listSpec(Doc), []); } else { - groups = Cast(link["anchor2Groups"], listSpec(Doc), []); + groups = Cast(link.proto!.anchor2Groups, listSpec(Doc), []); } let newGroups: Doc[] = []; groups.forEach(groupDoc => { - if (groupDoc instanceof Doc && StrCast(groupDoc["type"]) !== groupType) { + if (groupDoc instanceof Doc && StrCast(groupDoc.type) !== groupType) { newGroups.push(groupDoc); } - }) + }); LinkUtils.setAnchorGroups(link, anchor, newGroups); } } @@ -111,7 +111,7 @@ export class LinkManager { if (groups.length > 0) { groups.forEach(groupDoc => { if (groupDoc instanceof Doc) { - let groupType = StrCast(groupDoc["type"]); + let groupType = StrCast(groupDoc.type); let group = anchorGroups.get(groupType); // TODO: clean this up lol if (group) group.push(link); else group = [link]; @@ -120,7 +120,7 @@ export class LinkManager { // promise doc } - }) + }); } else { // if link is in no groups then put it in default group @@ -130,7 +130,7 @@ export class LinkManager { anchorGroups.set("*", group); } - }) + }); return anchorGroups; } @@ -145,28 +145,28 @@ export class LinkManager { // } // }) allLinks.forEach(linkDoc => { - let anchor1Groups = Cast(linkDoc["anchor1Groups"], listSpec(Doc), []); - let anchor2Groups = Cast(linkDoc["anchor2Groups"], listSpec(Doc), []); + let anchor1Groups = Cast(linkDoc.anchor1Groups, listSpec(Doc), []); + let anchor2Groups = Cast(linkDoc.anchor2Groups, listSpec(Doc), []); anchor1Groups.forEach(groupDoc => { if (groupDoc instanceof Doc) { - if (StrCast(groupDoc["type"]) === groupType) { - md.push(Cast(groupDoc["metadata"], Doc, new Doc)); + if (StrCast(groupDoc.type) === groupType) { + md.push(Cast(groupDoc.metadata, Doc, new Doc)); } } else { // TODO: promise } - }) + }); anchor2Groups.forEach(groupDoc => { if (groupDoc instanceof Doc) { - if (StrCast(groupDoc["type"]) === groupType) { - md.push(Cast(groupDoc["metadata"], Doc, new Doc)); + if (StrCast(groupDoc.type) === groupType) { + md.push(Cast(groupDoc.metadata, Doc, new Doc)); } } else { // TODO: promise } - }) + }); - }) + }); return md; } @@ -174,9 +174,9 @@ export class LinkManager { let deleted = LinkManager.Instance.allGroups.delete(groupType); if (deleted) { LinkManager.Instance.allLinks.forEach(linkDoc => { - LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc["anchor1"], Doc, new Doc), groupType); - LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc["anchor2"], Doc, new Doc), groupType); - }) + LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType); + LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc), groupType); + }); } } diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 370fdee1d..386d0cc3e 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -56,12 +56,12 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s let options = []; results.forEach(result => { options.push(
{ this.props.setGroup(this.props.groupId, result); this.setGroupType(result); this.setSearchTerm("") }}>{result}
) + onClick={() => { this.props.setGroup(this.props.groupId, result); this.setGroupType(result); this.setSearchTerm(""); }}>{result}); }); if (!exactFound && this._searchTerm !== "") { options.push(
{ this.createGroup(this._searchTerm); this.setGroupType(this._searchTerm); this.setSearchTerm("") }}>Define new "{this._searchTerm}" relationship
) + onClick={() => { this.createGroup(this._searchTerm); this.setGroupType(this._searchTerm); this.setSearchTerm(""); }}>Define new "{this._searchTerm}" relationship); } return options; @@ -71,12 +71,12 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s return (
{ this.setSearchTerm(e.target.value); this.setGroupType(e.target.value) }}> + onChange={e => { this.setSearchTerm(e.target.value); this.setGroupType(e.target.value); }}>
{this.renderOptions()}
- ) + ); } } @@ -97,7 +97,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc groupMdKeys[index] = value; } else { - console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys) + console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys); } } @@ -120,7 +120,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc groupMdKeys.splice(index, 1); } else { - console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys) + console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys); } } this._key = ""; @@ -134,7 +134,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc this.editMetadataValue(e.target.value)}> - ) + ); } } @@ -163,7 +163,7 @@ export class LinkEditor extends React.Component { } else { // promise doc } - }) + }); this._groups = groups; } @@ -171,20 +171,20 @@ export class LinkEditor extends React.Component { addGroup = (): void => { console.log("before adding", ...Array.from(this._groups.keys())); + // 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"; - }) + return groupDoc.type === "New Group"; + }); if (index === -1) { // create new document for group let mdDoc = Docs.TextDocument(); - mdDoc.proto!.anchor1 = this.props.sourceDoc["title"]; - mdDoc.proto!.anchor2 = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc)["title"]; + mdDoc.proto!.anchor1 = this.props.sourceDoc.title; + mdDoc.proto!.anchor2 = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc).title; let groupDoc = Docs.TextDocument(); groupDoc.proto!.type = "New Group"; groupDoc.proto!.metadata = mdDoc; - this._groups.set(Utils.GenerateGuid(), groupDoc); let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; @@ -207,12 +207,9 @@ export class LinkEditor extends React.Component { this._groups.set(groupId, groupDoc); - let gd = this._groups.get(groupId); - if (gd) - console.log("just created", StrCast(gd["type"])); LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); - console.log("set", Array.from(this._groups.values()).length) + console.log("set", Array.from(this._groups.values()).length); } let anchor1groups: string[] = []; @@ -222,7 +219,7 @@ export class LinkEditor extends React.Component { } else { console.log("promise"); } - }) + }); let anchor2groups: string[] = []; Cast(this.props.linkDoc.anchor2Groups, listSpec(Doc), []).forEach(doc => { if (doc instanceof Doc) { @@ -230,8 +227,8 @@ export class LinkEditor extends React.Component { } else { console.log("promise"); } - }) - console.log("groups for anchors; anchor1: [", ...anchor1groups, "] ; anchor2: [", ...anchor2groups, "]") + }); + console.log("groups for anchors; anchor1: [", ...anchor1groups, "] ; anchor2: [", ...anchor2groups, "]"); } removeGroupFromLink = (groupId: string, groupType: string) => { @@ -260,11 +257,11 @@ export class LinkEditor extends React.Component { // if group already exists on opposite anchor, copy value let index = groupList.findIndex(groupDoc => { if (groupDoc instanceof Doc) { - return StrCast(groupDoc["type"]) === groupType; + return StrCast(groupDoc.type) === groupType; } else { return false; } - }) + }); // TODO: clean // if (index > 0) { // let thisGroupDoc = this._groups.get(groupId); @@ -283,11 +280,11 @@ export class LinkEditor extends React.Component { // // LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [oppGroupDoc]); // } else { let thisGroupDoc = this._groups.get(groupId); - let thisMdDoc = Cast(thisGroupDoc!["metadata"], Doc, new Doc); + let thisMdDoc = Cast(thisGroupDoc!.metadata, Doc, new Doc); let newGroupDoc = Docs.TextDocument(); let newMdDoc = Docs.TextDocument(); - newMdDoc.proto!.anchor1 = StrCast(thisMdDoc["anchor2"]); - newMdDoc.proto!.anchor2 = StrCast(thisMdDoc["anchor1"]); + newMdDoc.proto!.anchor1 = StrCast(thisMdDoc.anchor2); + newMdDoc.proto!.anchor2 = StrCast(thisMdDoc.anchor1); let keys = LinkManager.Instance.allGroups.get(groupType); if (keys) { keys.forEach(key => { @@ -297,7 +294,7 @@ export class LinkEditor extends React.Component { } // mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key]) // oppGroupDoc[key] = thisGroupDoc[key]; - }) + }); } newGroupDoc.proto!.type = groupType; newGroupDoc.proto!.metadata = newMdDoc; @@ -309,7 +306,7 @@ export class LinkEditor extends React.Component { } renderGroup(groupId: string, groupDoc: Doc) { - let type = StrCast(groupDoc["type"]); + let type = StrCast(groupDoc.type); if ((type && LinkManager.Instance.allGroups.get(type)) || type === "New Group") { return (
@@ -319,7 +316,7 @@ export class LinkEditor extends React.Component {
{this.renderMetadata(groupId)}
- {groupDoc["type"] === "New Group" ? : + {groupDoc.type === "New Group" ? : } {/* @@ -327,9 +324,9 @@ export class LinkEditor extends React.Component { {this.viewGroupAsTable(groupId, type)}
- ) + ); } else { - return <> + return <>; } } @@ -341,9 +338,9 @@ export class LinkEditor extends React.Component { let docs: Doc[] = LinkManager.Instance.findMetadataInGroup(groupType); let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys!], docs, { width: 200, height: 200, title: groupType + " table" })); let ref = React.createRef(); - return
+ return
; } else { - return + return ; } } @@ -372,8 +369,8 @@ export class LinkEditor extends React.Component { groupMdKeys.forEach((key, index) => { metadata.push( - ) - }) + ); + }); } } return metadata; @@ -384,7 +381,7 @@ export class LinkEditor extends React.Component { let groups: Array = []; this._groups.forEach((groupDoc, groupId) => { - groups.push(this.renderGroup(groupId, groupDoc)) + groups.push(this.renderGroup(groupId, groupDoc)); }); return ( -- cgit v1.2.3-70-g09d2 From 0d0782362d4549b80c27c3ce5d8439c2f6fa4d7b Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Jun 2019 16:05:26 -0400 Subject: fixed delete handlers for link groups --- src/client/util/LinkManager.ts | 57 +++++++++++++++++----------------- src/client/views/nodes/LinkEditor.scss | 2 +- src/client/views/nodes/LinkEditor.tsx | 34 ++++++++++---------- 3 files changed, 46 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index c0c607b01..2f40c77e7 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -20,49 +20,48 @@ export namespace LinkUtils { } } - // 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[]) { // console.log("setting groups for anchor", anchor["title"]); if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { link.anchor1Groups = new List(groups); + + let print: string[] = []; + Cast(link.anchor1Groups, listSpec(Doc), []).forEach(doc => { + if (doc instanceof Doc) { + print.push(StrCast(doc.type)); + } + }); + console.log("set anchor's groups as", print); } else { link.anchor2Groups = new List(groups); + + let print: string[] = []; + Cast(link.anchor2Groups, listSpec(Doc), []).forEach(doc => { + if (doc instanceof Doc) { + print.push(StrCast(doc.type)); + } + }); + console.log("set anchor's groups as", print); } } export function removeGroupFromAnchor(link: Doc, anchor: Doc, groupType: string) { - let groups = []; - if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { - groups = Cast(link.proto!.anchor1Groups, listSpec(Doc), []); - } else { - groups = Cast(link.proto!.anchor2Groups, listSpec(Doc), []); - } + let groups = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)) ? + Cast(link.proto!.anchor1Groups, listSpec(Doc), []) : Cast(link.proto!.anchor2Groups, listSpec(Doc), []); let newGroups: Doc[] = []; groups.forEach(groupDoc => { if (groupDoc instanceof Doc && StrCast(groupDoc.type) !== groupType) { newGroups.push(groupDoc); - } + } // TODO: promise }); + + // let grouptypes: string[] = []; + // newGroups.forEach(groupDoc => { + // grouptypes.push(StrCast(groupDoc.type)); + // }); + // console.log("remove anchor's groups as", grouptypes); + LinkUtils.setAnchorGroups(link, anchor, newGroups); } } @@ -92,7 +91,7 @@ export class LinkManager { } @observable public allLinks: Array = []; // list of link docs - @observable public allGroups: Map> = new Map(); // map of group type to list of its metadata keys + @observable public groupMetadataKeys: Map> = new Map(); // map of group type to list of its metadata keys public findAllRelatedLinks(anchor: Doc): Array { return LinkManager.Instance.allLinks.filter( @@ -171,7 +170,7 @@ export class LinkManager { } public deleteGroup(groupType: string) { - let deleted = LinkManager.Instance.allGroups.delete(groupType); + let deleted = LinkManager.Instance.groupMetadataKeys.delete(groupType); if (deleted) { LinkManager.Instance.allLinks.forEach(linkDoc => { LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType); diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index df7bd6086..01f0cb82a 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -127,7 +127,7 @@ display: flex; justify-content: space-between; .linkEditor-groupOpts { - width: calc(33% - 3px); + width: calc(20% - 3px); height: 20px; // margin-left: 6px; padding: 0; diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 386d0cc3e..5097d625e 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -37,14 +37,14 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s @action createGroup(value: string) { - LinkManager.Instance.allGroups.set(value, []); + LinkManager.Instance.groupMetadataKeys.set(value, []); this.props.setGroup(this.props.groupId, value); } renderOptions = (): JSX.Element[] => { let allGroups: string[], searchTerm: string, results: string[], exactFound: boolean; if (this._searchTerm !== "") { - allGroups = Array.from(LinkManager.Instance.allGroups.keys()); + allGroups = Array.from(LinkManager.Instance.groupMetadataKeys.keys()); searchTerm = this._searchTerm.toUpperCase(); results = allGroups.filter(group => group.toUpperCase().indexOf(searchTerm) > -1); exactFound = results.findIndex(group => group.toUpperCase() === searchTerm) > -1; @@ -90,7 +90,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc @action editMetadataKey = (value: string): void => { // TODO: check that metadata doesnt already exist in group - let groupMdKeys = new Array(...LinkManager.Instance.allGroups.get(this.props.groupType)!); + let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!); if (groupMdKeys) { let index = groupMdKeys.indexOf(this._key); if (index > -1) { @@ -102,7 +102,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc } this._key = value; - LinkManager.Instance.allGroups.set(this.props.groupType, groupMdKeys); + LinkManager.Instance.groupMetadataKeys.set(this.props.groupType, groupMdKeys); } @action @@ -113,7 +113,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc @action removeMetadata = (): void => { - let groupMdKeys = new Array(...LinkManager.Instance.allGroups.get(this.props.groupType)!); + let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!); if (groupMdKeys) { let index = groupMdKeys.indexOf(this._key); if (index > -1) { @@ -124,7 +124,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc } } this._key = ""; - LinkManager.Instance.allGroups.set(this.props.groupType, groupMdKeys); + LinkManager.Instance.groupMetadataKeys.set(this.props.groupType, groupMdKeys); } render() { @@ -132,7 +132,7 @@ class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc
this.editMetadataKey(e.target.value)}>: this.editMetadataValue(e.target.value)}> - +
); } @@ -199,7 +199,7 @@ export class LinkEditor extends React.Component { @action setGroupType = (groupId: string, groupType: string): void => { console.log("setting for ", groupId); - let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; + // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; let groupDoc = this._groups.get(groupId); if (groupDoc) { console.log("found group doc"); @@ -208,7 +208,7 @@ export class LinkEditor extends React.Component { this._groups.set(groupId, groupDoc); - LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); + LinkUtils.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); console.log("set", Array.from(this._groups.values()).length); } @@ -285,7 +285,7 @@ export class LinkEditor extends React.Component { let newMdDoc = Docs.TextDocument(); newMdDoc.proto!.anchor1 = StrCast(thisMdDoc.anchor2); newMdDoc.proto!.anchor2 = StrCast(thisMdDoc.anchor1); - let keys = LinkManager.Instance.allGroups.get(groupType); + let keys = LinkManager.Instance.groupMetadataKeys.get(groupType); if (keys) { keys.forEach(key => { if (thisGroupDoc) { // TODO: clean @@ -307,7 +307,7 @@ export class LinkEditor extends React.Component { renderGroup(groupId: string, groupDoc: Doc) { let type = StrCast(groupDoc.type); - if ((type && LinkManager.Instance.allGroups.get(type)) || type === "New Group") { + if ((type && LinkManager.Instance.groupMetadataKeys.get(type)) || type === "New Group") { return (
@@ -319,8 +319,8 @@ export class LinkEditor extends React.Component { {groupDoc.type === "New Group" ? : } - {/* - */} + + {this.viewGroupAsTable(groupId, type)}
@@ -331,7 +331,7 @@ export class LinkEditor extends React.Component { } viewGroupAsTable(groupId: string, groupType: string) { - let keys = LinkManager.Instance.allGroups.get(groupType); + let keys = LinkManager.Instance.groupMetadataKeys.get(groupType); let groupDoc = this._groups.get(groupId); if (keys && groupDoc) { console.log("keys:", ...keys); @@ -347,7 +347,7 @@ export class LinkEditor extends React.Component { @action addMetadata = (groupType: string): void => { - let mdKeys = LinkManager.Instance.allGroups.get(groupType); + let mdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType); if (mdKeys) { if (mdKeys.indexOf("new key") === -1) { mdKeys.push("new key"); @@ -355,7 +355,7 @@ export class LinkEditor extends React.Component { } else { mdKeys = ["new key"]; } - LinkManager.Instance.allGroups.set(groupType, mdKeys); + LinkManager.Instance.groupMetadataKeys.set(groupType, mdKeys); } renderMetadata(groupId: string) { @@ -364,7 +364,7 @@ export class LinkEditor extends React.Component { if (groupDoc) { let mdDoc = Cast(groupDoc.proto!.metadata, Doc, new Doc); let groupType = StrCast(groupDoc.proto!.type); - let groupMdKeys = LinkManager.Instance.allGroups.get(groupType); + let groupMdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType); if (groupMdKeys) { groupMdKeys.forEach((key, index) => { metadata.push( -- cgit v1.2.3-70-g09d2 From 8bcd3567df7c49523638f0b935ecd09b1acad45d Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 13 Jun 2019 18:07:35 -0400 Subject: cannot create the same link twice --- src/client/documents/Documents.ts | 1 + src/client/util/LinkManager.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9517cbbda..9cb41aecc 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -86,6 +86,7 @@ const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; export namespace DocUtils { export function MakeLink(source: Doc, target: Doc) { + if (LinkManager.Instance.doesLinkExist(source, target)) return; // let protoSrc = source.proto ? source.proto : source; // let protoTarg = target.proto ? target.proto : target; UndoManager.RunInBatch(() => { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 2f40c77e7..929fcbf21 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -10,6 +10,7 @@ import { Doc } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; import { List } from "../../new_fields/List"; import { string } from "prop-types"; +import { Docs } from "../documents/Documents"; export namespace LinkUtils { export function findOppositeAnchor(link: Doc, anchor: Doc): Doc { @@ -179,4 +180,13 @@ export class LinkManager { } } + public doesLinkExist(anchor1: Doc, anchor2: Doc) { + let allLinks = LinkManager.Instance.allLinks; + 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)); + }); + return index !== -1; + } + } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From cebfbc2ce39befaa5c2454a740a3250286b676de Mon Sep 17 00:00:00 2001 From: madelinegr Date: Thu, 13 Jun 2019 20:07:05 -0400 Subject: zoom partial work --- .../collectionFreeForm/CollectionFreeFormView.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1a1614ac7..dc1bb5866 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -271,10 +271,30 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { newState.initializers[id] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); this.setPan(newPanX, newPanY); + this.setScaleToZoom(doc); this.props.Document.panTransformType = "Ease"; this.props.focus(this.props.Document); } + setScaleToZoom = (doc: Doc) => { + 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 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; + } + getDocumentViewProps(document: Doc): DocumentViewProps { return { -- cgit v1.2.3-70-g09d2 From 19d5016acc3ff058a9665babb202e945c1fac766 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Fri, 14 Jun 2019 12:05:51 -0400 Subject: commented out code --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index dc1bb5866..5d26cb0c2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -271,9 +271,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { newState.initializers[id] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); this.setPan(newPanX, newPanY); - this.setScaleToZoom(doc); this.props.Document.panTransformType = "Ease"; this.props.focus(this.props.Document); + //this.setScaleToZoom(doc); + } setScaleToZoom = (doc: Doc) => { -- cgit v1.2.3-70-g09d2 From f54496c7aa930e385e77aaf37df8d51db733e3a2 Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 14 Jun 2019 15:24:35 -0400 Subject: cleaned up link code --- src/client/util/LinkManager.ts | 166 ++++++----------- src/client/views/nodes/LinkBox.scss | 122 ++++++------- src/client/views/nodes/LinkBox.tsx | 52 +----- src/client/views/nodes/LinkEditor.scss | 106 +++++------ src/client/views/nodes/LinkEditor.tsx | 319 +++++++++++++-------------------- src/client/views/nodes/LinkMenu.scss | 76 +------- src/client/views/nodes/LinkMenu.tsx | 54 ++---- 7 files changed, 311 insertions(+), 584 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 929fcbf21..aaed7388d 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -1,71 +1,9 @@ -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 { observable } from "mobx"; import { StrCast, Cast } from "../../new_fields/Types"; -import { Doc } from "../../new_fields/Doc"; +import { Doc, DocListCast } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; import { List } from "../../new_fields/List"; -import { string } from "prop-types"; -import { Docs } from "../documents/Documents"; -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 setAnchorGroups(link: Doc, anchor: Doc, groups: Doc[]) { - // console.log("setting groups for anchor", anchor["title"]); - if (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) { - link.anchor1Groups = new List(groups); - - let print: string[] = []; - Cast(link.anchor1Groups, listSpec(Doc), []).forEach(doc => { - if (doc instanceof Doc) { - print.push(StrCast(doc.type)); - } - }); - console.log("set anchor's groups as", print); - } else { - link.anchor2Groups = new List(groups); - - let print: string[] = []; - Cast(link.anchor2Groups, listSpec(Doc), []).forEach(doc => { - if (doc instanceof Doc) { - print.push(StrCast(doc.type)); - } - }); - console.log("set anchor's groups as", print); - } - } - - export function removeGroupFromAnchor(link: Doc, anchor: Doc, groupType: string) { - let groups = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)) ? - Cast(link.proto!.anchor1Groups, listSpec(Doc), []) : Cast(link.proto!.anchor2Groups, listSpec(Doc), []); - - let newGroups: Doc[] = []; - groups.forEach(groupDoc => { - if (groupDoc instanceof Doc && StrCast(groupDoc.type) !== groupType) { - newGroups.push(groupDoc); - } // TODO: promise - }); - - // let grouptypes: string[] = []; - // newGroups.forEach(groupDoc => { - // grouptypes.push(StrCast(groupDoc.type)); - // }); - // console.log("remove anchor's groups as", grouptypes); - - LinkUtils.setAnchorGroups(link, anchor, newGroups); - } -} /* * link doc: @@ -94,6 +32,7 @@ export class LinkManager { @observable public allLinks: Array = []; // list of link docs @observable public groupMetadataKeys: Map> = new Map(); // map of group type to list of its metadata keys + // finds all links that contain the given anchor 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))); @@ -102,27 +41,19 @@ export class LinkManager { // returns map of group type to anchor's links in that group type public findRelatedGroupedLinks(anchor: Doc): Map> { let related = this.findAllRelatedLinks(anchor); - let anchorGroups = new Map>(); related.forEach(link => { + let groups = LinkManager.Instance.getAnchorGroups(link, anchor); - // get groups of given anchor categorizes this link/opposite anchor in - let groups = (Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc))) ? Cast(link.anchor1Groups, listSpec(Doc), []) : Cast(link.anchor2Groups, listSpec(Doc), []); if (groups.length > 0) { groups.forEach(groupDoc => { - if (groupDoc instanceof Doc) { - let groupType = StrCast(groupDoc.type); - let group = anchorGroups.get(groupType); // TODO: clean this up lol - if (group) group.push(link); - else group = [link]; - anchorGroups.set(groupType, group); - } else { - // promise doc - } - + let groupType = StrCast(groupDoc.type); + let group = anchorGroups.get(groupType); + if (group) group.push(link); + else group = [link]; + anchorGroups.set(groupType, group); }); - } - else { + } else { // if link is in no groups then put it in default group let group = anchorGroups.get("*"); if (group) group.push(link); @@ -134,52 +65,38 @@ export class LinkManager { return anchorGroups; } - public findMetadataInGroup(groupType: string) { + // returns a list of all metadata docs associated with the given group type + public findAllMetadataDocsInGroup(groupType: string): Array { let md: Doc[] = []; let allLinks = LinkManager.Instance.allLinks; - // for every link find its groups - // allLinks.forEach(linkDoc => { - // let anchor1groups = LinkManager.Instance.findRelatedGroupedLinks(Cast(linkDoc["anchor1"], Doc, new Doc)); - // if (anchor1groups.get(groupType)) { - // md.push(linkDoc["anchor1"]["group"]) - // } - // }) allLinks.forEach(linkDoc => { - let anchor1Groups = Cast(linkDoc.anchor1Groups, listSpec(Doc), []); - let anchor2Groups = Cast(linkDoc.anchor2Groups, listSpec(Doc), []); - anchor1Groups.forEach(groupDoc => { - if (groupDoc instanceof Doc) { - if (StrCast(groupDoc.type) === groupType) { - md.push(Cast(groupDoc.metadata, Doc, new Doc)); - } - } else { - // TODO: promise - } - }); - anchor2Groups.forEach(groupDoc => { - if (groupDoc instanceof Doc) { - if (StrCast(groupDoc.type) === groupType) { - md.push(Cast(groupDoc.metadata, Doc, new Doc)); - } - } else { - // TODO: promise - } - }); - + let anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc)); + let anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc)); + anchor1Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) md.push(Cast(groupDoc.metadata, Doc, new Doc)); }); + anchor2Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) md.push(Cast(groupDoc.metadata, Doc, new Doc)); }); }); return md; } - public deleteGroup(groupType: string) { + // 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 => { - LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType); - LinkUtils.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc), groupType); + 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; let index = allLinks.findIndex(linkDoc => { @@ -189,4 +106,31 @@ export class LinkManager { return index !== -1; } + // finds the opposite anchor of a given anchor in a link + public findOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc { + if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { + return Cast(linkDoc.anchor2, Doc, new Doc); + } else { + return Cast(linkDoc.anchor1, Doc, new Doc); + } + } + + // 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); + } + } + } \ No newline at end of file diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss index 639f83b38..08fefaf4d 100644 --- a/src/client/views/nodes/LinkBox.scss +++ b/src/client/views/nodes/LinkBox.scss @@ -1,66 +1,62 @@ @import "../globalCssVariables"; -.link-container { - width: 100%; - height: 50px; +.link-menu-item { + border-top: 0.5px solid $light-color-secondary; + padding: 6px; + position: relative; display: flex; - flex-direction: row; - border-top: 0.5px solid #bababa; -} - -.info-container { - width: 65%; - padding-top: 5px; - padding-left: 5px; - display: flex; - flex-direction: column -} - -.link-name { - font-size: 11px; -} - -.doc-name { - font-size: 8px; -} - -.button-container { - width: 35%; - padding-top: 8px; - display: flex; - flex-direction: row; -} - -.button { - height: 20px; - width: 20px; - margin: 8px 4px; - border-radius: 50%; - opacity: 0.9; - pointer-events: auto; - background-color: $dark-color; - color: $light-color; - text-transform: uppercase; - letter-spacing: 2px; - font-size: 60%; - transition: transform 0.2s; -} - -.button:hover { - background: $main-accent; - cursor: pointer; -} - -// .fa-icon-view { -// margin-left: 3px; -// margin-top: 5px; -// } - -.fa-icon-edit { - margin-left: 6px; - margin-top: 6px; -} - -.fa-icon-delete { - margin-left: 7px; - margin-top: 6px; + font-size: 12px; + + .link-menu-item-content { + width: 100%; + } + + &:last-child { + border-bottom: 0.5px solid $light-color-secondary; + } + &:hover { + .link-menu-item-buttons { + display: flex; + } + .link-menu-item-content { + width: calc(100% - 42px); + } + } +} + +.link-menu-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/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 5597bb1aa..1a7cce4a3 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -4,13 +4,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observer } from "mobx-react"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; import './LinkBox.scss'; import React = require("react"); import { Doc } from '../../../new_fields/Doc'; -import { Cast, NumCast } from '../../../new_fields/Types'; -import { listSpec } from '../../../new_fields/Schema'; -import { action } from 'mobx'; +import { StrCast } from '../../../new_fields/Types'; library.add(faEye); @@ -20,9 +17,8 @@ library.add(faArrowRight); interface Props { linkDoc: Doc; - linkName: String; - pairedDoc: Doc; - type: String; + sourceDoc: Doc; + destinationDoc: Doc; showEditor: () => void; } @@ -30,58 +26,28 @@ interface Props { export class LinkBox extends React.Component { @undoBatch - followLink = async (e: React.PointerEvent): Promise => { + onFollowLink = async (e: React.PointerEvent): Promise => { e.stopPropagation(); - DocumentManager.Instance.jumpToDocument(this.props.pairedDoc, e.altKey); + DocumentManager.Instance.jumpToDocument(this.props.destinationDoc, e.altKey); } - onEditButtonPressed = (e: React.PointerEvent): void => { + onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); - this.props.showEditor(); } - // @action - // onDeleteButtonPressed = async (e: React.PointerEvent): Promise => { - // e.stopPropagation(); - // const [linkedFrom, linkedTo] = await Promise.all([Cast(this.props.linkDoc.linkedFrom, Doc), Cast(this.props.linkDoc.linkedTo, Doc)]); - // if (linkedFrom) { - // const linkedToDocs = Cast(linkedFrom.linkedToDocs, listSpec(Doc)); - // if (linkedToDocs) { - // linkedToDocs.splice(linkedToDocs.indexOf(this.props.linkDoc), 1); - // } - // } - // if (linkedTo) { - // const linkedFromDocs = Cast(linkedTo.linkedFromDocs, listSpec(Doc)); - // if (linkedFromDocs) { - // linkedFromDocs.splice(linkedFromDocs.indexOf(this.props.linkDoc), 1); - // } - // } - // } - render() { - return ( - //
-

{this.props.linkName}

-
-
-

{this.props.type}{this.props.pairedDoc.Title}

+

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

- {/*
-
*/} -
-
-
-
- {/*
-
*/} +
+
); diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 01f0cb82a..6aac39f45 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -1,92 +1,63 @@ @import "../globalCssVariables"; -.edit-container { + +.linkEditor { width: 100%; height: auto; - display: flex; - flex-direction: column; + font-size: 12px; // TODO } -.name-input { - margin-bottom: 10px; - padding: 5px; - font-size: 12px; - border: 1px solid #bababa; +.linkEditor-back { + margin-bottom: 6px; } -.description-input { - font-size: 11px; - padding: 5px; - margin-bottom: 10px; - border: 1px solid #bababa; -} +.linkEditor-groupsLabel { + display: flex; + justify-content: space-between; -.save-button { - width: 50px; - height: 22px; - pointer-events: auto; - background-color: $dark-color; - color: $light-color; - text-transform: uppercase; - letter-spacing: 2px; - padding: 2px; - font-size: 10px; - margin: 0 auto; - transition: transform 0.2s; - text-align: center; - line-height: 20px; + button { + width: 20px; + height: 20px; + margin-left: 6px; + padding: 0; + font-size: 14px; + } } -.save-button:hover { - background: $main-accent; - cursor: pointer; +.linkEditor-linkedTo { + border-bottom: 0.5px solid $light-color-secondary; + padding-bottom: 6px; + margin-bottom: 6px; } -.linkEditor { - font-size: 12px; // TODO - - .linkEditor-back { - // background-color: $dark-color; - // color: $light-color; - margin-bottom: 6px; - } +.linkEditor-group { + background-color: $light-color-secondary; + padding: 6px; + margin: 3px 0; + border-radius: 3px; - .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; margin-bottom: 6px; + .linkEditor-group-row-label { margin-right: 6px; } } + .linkEditor-metadata-row { display: flex; justify-content: space-between; margin-bottom: 6px; + + .linkEditor-error { + border-color: red; + } + input { width: calc(50% - 18px); height: 20px; } + button { width: 20px; height: 20px; @@ -97,10 +68,12 @@ } } + .linkEditor-dropdown { width: 100%; position: relative; z-index: 999; + .linkEditor-options-wrapper { width: 100%; position: absolute; @@ -109,12 +82,14 @@ display: flex; flex-direction: column; } + .linkEditor-option { background-color: $light-color-secondary; border: 1px solid $intermediate-color; border-top: 0; padding: 3px; cursor: pointer; + &:hover { background-color: $intermediate-color; font-weight: bold; @@ -126,19 +101,18 @@ height: 20px; display: flex; justify-content: space-between; + .linkEditor-groupOpts { width: calc(20% - 3px); height: 20px; - // margin-left: 6px; padding: 0; font-size: 10px; - &:first-child { // delete - font-size: 14px; - } - &:disabled { // delete + + &:disabled { background-color: gray; } } + .linkEditor-groupOpts button { width: 100%; height: 20px; diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 5097d625e..484682c22 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -4,61 +4,52 @@ import { observer } from "mobx-react"; import './LinkEditor.scss'; 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, LinkUtils } from "../../util/LinkManager"; +import { LinkManager } from "../../util/LinkManager"; import { Docs } from "../../documents/Documents"; import { Utils } from "../../../Utils"; import { faArrowLeft, faEllipsisV, faTable } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { string } from "prop-types"; import { SetupDrag } from "../../util/DragManager"; library.add(faArrowLeft); library.add(faEllipsisV); library.add(faTable); + +interface GroupTypesDropdownProps { + groupId: string; + groupType: string; + setGroup: (groupId: string, group: string) => void; +} // this dropdown could be generalized @observer -class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: string, setGroup: (groupId: string, group: string) => void }> { +class GroupTypesDropdown extends React.Component { @observable private _searchTerm: string = ""; @observable private _groupType: string = this.props.groupType; - @action - setSearchTerm(value: string) { - this._searchTerm = value; - } + @action setSearchTerm = (value: string): void => { this._searchTerm = value; }; + @action setGroupType = (value: string): void => { this._groupType = value; }; @action - setGroupType(value: string) { - this._groupType = value; + createGroup = (groupType: string): void => { + this.props.setGroup(this.props.groupId, groupType); + LinkManager.Instance.groupMetadataKeys.set(groupType, []); } - @action - createGroup(value: string) { - LinkManager.Instance.groupMetadataKeys.set(value, []); - this.props.setGroup(this.props.groupId, value); - } + renderOptions = (): JSX.Element[] | JSX.Element => { + if (this._searchTerm === "") return <>; - renderOptions = (): JSX.Element[] => { - let allGroups: string[], searchTerm: string, results: string[], exactFound: boolean; - if (this._searchTerm !== "") { - allGroups = Array.from(LinkManager.Instance.groupMetadataKeys.keys()); - searchTerm = this._searchTerm.toUpperCase(); - results = allGroups.filter(group => group.toUpperCase().indexOf(searchTerm) > -1); - exactFound = results.findIndex(group => group.toUpperCase() === searchTerm) > -1; - } else { - results = []; - exactFound = false; - } + let allGroupTypes = Array.from(LinkManager.Instance.groupMetadataKeys.keys()); + 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 = []; - results.forEach(result => { - options.push(
{ this.props.setGroup(this.props.groupId, result); this.setGroupType(result); this.setSearchTerm(""); }}>{result}
); + let options = groupOptions.map(groupType => { + return
{ this.props.setGroup(this.props.groupId, 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 if (!exactFound && this._searchTerm !== "") { options.push(
{ this.createGroup(this._searchTerm); this.setGroupType(this._searchTerm); this.setSearchTerm(""); }}>Define new "{this._searchTerm}" relationship
); @@ -81,57 +72,66 @@ class LinkGroupsDropdown extends React.Component<{ groupId: string, groupType: s } - +interface LinkMetadataEditorProps { + groupType: string; + mdDoc: Doc; + mdKey: string; + mdValue: string; +} @observer -class LinkMetadataEditor extends React.Component<{ groupType: string, mdDoc: Doc, mdKey: string, mdValue: string }> { +class LinkMetadataEditor extends React.Component { @observable private _key: string = this.props.mdKey; @observable private _value: string = this.props.mdValue; + @observable private _keyError: boolean = false; @action - editMetadataKey = (value: string): void => { - // TODO: check that metadata doesnt already exist in group + setMetadataKey = (value: string): void => { let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!); - if (groupMdKeys) { - let index = groupMdKeys.indexOf(this._key); - if (index > -1) { - groupMdKeys[index] = value; - } - else { - console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys); - } + + // don't allow user to create existing key + let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase()); + if (newIndex > -1) { + this._keyError = true; + this._key = value; + return; + } else { + this._keyError = false; } + // set new value for key + let currIndex = groupMdKeys.findIndex(key => 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); } @action - editMetadataValue = (value: string): void => { - this.props.mdDoc[this._key] = value; - this._value = value; + setMetadataValue = (value: string): void => { + if (!this._keyError) { + this._value = value; + this.props.mdDoc[this._key] = value; + } } @action removeMetadata = (): void => { let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!); - if (groupMdKeys) { - let index = groupMdKeys.indexOf(this._key); - if (index > -1) { - groupMdKeys.splice(index, 1); - } - else { - console.log("OLD KEY WAS NOT FOUND", ...groupMdKeys); - } - } - this._key = ""; + + 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); + this._key = ""; } render() { return (
- this.editMetadataKey(e.target.value)}>: - this.editMetadataValue(e.target.value)}> + this.setMetadataKey(e.target.value)}>: + this.setMetadataValue(e.target.value)}>
); @@ -144,175 +144,127 @@ interface LinkEditorProps { linkDoc: Doc; showLinks: () => void; } - @observer export class LinkEditor extends React.Component { - @observable private _groups: Map = new Map(); // map of temp group id to the corresponding group doc + // map of temporary group id to the corresponding group doc + @observable private _groups: Map = new Map(); constructor(props: LinkEditorProps) { super(props); let groups = new Map(); - let groupList = (Doc.AreProtosEqual(props.sourceDoc, Cast(props.linkDoc.anchor1, Doc, new Doc))) ? - Cast(props.linkDoc.anchor1Groups, listSpec(Doc), []) : Cast(props.linkDoc.anchor2Groups, listSpec(Doc), []); + let groupList = LinkManager.Instance.getAnchorGroups(props.linkDoc, props.sourceDoc); groupList.forEach(groupDoc => { - if (groupDoc instanceof Doc) { - let id = Utils.GenerateGuid(); - groups.set(id, groupDoc); - } else { - // promise doc - } + let id = Utils.GenerateGuid(); + groups.set(id, groupDoc); }); this._groups = groups; } @action addGroup = (): void => { - console.log("before adding", ...Array.from(this._groups.keys())); - // 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) { - // create new document for group - let mdDoc = Docs.TextDocument(); - mdDoc.proto!.anchor1 = this.props.sourceDoc.title; - mdDoc.proto!.anchor2 = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc).title; + if (index > -1) return; - let groupDoc = Docs.TextDocument(); - groupDoc.proto!.type = "New Group"; - groupDoc.proto!.metadata = mdDoc; + // 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; - this._groups.set(Utils.GenerateGuid(), groupDoc); + // create new group document + let groupDoc = Docs.TextDocument(); + groupDoc.proto!.type = "New Group"; + groupDoc.proto!.metadata = mdDoc; - let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; - LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); - } + this._groups.set(Utils.GenerateGuid(), groupDoc); - - // console.log("set anchor groups for", this.props.sourceDoc["title"]); - console.log("after adding", ...Array.from(this._groups.keys())); + 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())); } @action setGroupType = (groupId: string, groupType: string): void => { - console.log("setting for ", groupId); - // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc; let groupDoc = this._groups.get(groupId); if (groupDoc) { - console.log("found group doc"); groupDoc.proto!.type = groupType; - this._groups.set(groupId, groupDoc); - - - LinkUtils.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); - console.log("set", Array.from(this._groups.values()).length); + LinkManager.Instance.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); } - - let anchor1groups: string[] = []; - Cast(this.props.linkDoc.anchor1Groups, listSpec(Doc), []).forEach(doc => { - if (doc instanceof Doc) { - anchor1groups.push(StrCast(doc.proto!.type)); - } else { - console.log("promise"); - } - }); - let anchor2groups: string[] = []; - Cast(this.props.linkDoc.anchor2Groups, listSpec(Doc), []).forEach(doc => { - if (doc instanceof Doc) { - anchor2groups.push(StrCast(doc.proto!.type)); - } else { - console.log("promise"); - } - }); - console.log("groups for anchors; anchor1: [", ...anchor1groups, "] ; anchor2: [", ...anchor2groups, "]"); } - removeGroupFromLink = (groupId: string, groupType: string) => { - // this._groups.delete(groupId); + removeGroupFromLink = (groupId: string, groupType: string): void => { let groupDoc = this._groups.get(groupId); - if (groupDoc) { - LinkUtils.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType); - this._groups.delete(groupId); - } - // LinkUtils.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values())); - console.log("\nremoved", groupId, "remaining", ...Array.from(this._groups.keys()), "\n"); + 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) => { + deleteGroup = (groupId: string, groupType: string): void => { let groupDoc = this._groups.get(groupId); - if (groupDoc) { - LinkManager.Instance.deleteGroup(groupType); - this._groups.delete(groupId); - } + if (!groupDoc) console.error("LinkEditor: group not found"); + LinkManager.Instance.deleteGroup(groupType); + this._groups.delete(groupId); } - copyGroup = (groupId: string, groupType: string) => { - let oppAnchor = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - let groupList = (Doc.AreProtosEqual(oppAnchor, Cast(this.props.linkDoc.anchor1, Doc, new Doc))) ? - Cast(this.props.linkDoc.anchor1Groups, listSpec(Doc), []) : Cast(this.props.linkDoc.anchor2Groups, listSpec(Doc), []); - // if group already exists on opposite anchor, copy value - let index = groupList.findIndex(groupDoc => { - if (groupDoc instanceof Doc) { - return StrCast(groupDoc.type) === groupType; - } else { - return false; - } - }); - // TODO: clean - // if (index > 0) { - // let thisGroupDoc = this._groups.get(groupId); - // let oppGroupDoc = groupList[index]; - // let keys = LinkManager.Instance.allGroups.get(groupType); - // if (keys) { - // keys.forEach(key => { - // if (thisGroupDoc && oppGroupDoc instanceof Doc) { // TODO: clean - // let val = thisGroupDoc[key] === undefined ? "" : StrCast(thisGroupDoc[key]); - // oppGroupDoc[key] = val; - // } - // // mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key]) - // // oppGroupDoc[key] = thisGroupDoc[key]; - // }) - // } - // // LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [oppGroupDoc]); - // } else { - let thisGroupDoc = this._groups.get(groupId); - let thisMdDoc = Cast(thisGroupDoc!.metadata, Doc, new Doc); - let newGroupDoc = Docs.TextDocument(); - let newMdDoc = Docs.TextDocument(); - newMdDoc.proto!.anchor1 = StrCast(thisMdDoc.anchor2); - newMdDoc.proto!.anchor2 = StrCast(thisMdDoc.anchor1); + 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 => { - if (thisGroupDoc) { // TODO: clean - let val = thisMdDoc[key] === undefined ? "" : StrCast(thisMdDoc[key]); - newMdDoc[key] = val; - } - // mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key]) - // oppGroupDoc[key] = thisGroupDoc[key]; + let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]); + destMdDoc[key] = val; }); } - newGroupDoc.proto!.type = groupType; - newGroupDoc.proto!.metadata = newMdDoc; - LinkUtils.setAnchorGroups(this.props.linkDoc, oppAnchor, [newGroupDoc]); // TODO: fix to append to list - // } + // create new group doc with new metadata doc + let destGroupDoc = Docs.TextDocument(); + destGroupDoc.proto!.type = groupType; + destGroupDoc.proto!.metadata = destMdDoc; - // else create group on opposite anchor + // 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); + } + + 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 ; + } } - renderGroup(groupId: string, groupDoc: Doc) { + renderGroup = (groupId: string, groupDoc: Doc): JSX.Element => { let type = StrCast(groupDoc.type); if ((type && LinkManager.Instance.groupMetadataKeys.get(type)) || type === "New Group") { return (

type:

- +
{this.renderMetadata(groupId)}
@@ -330,35 +282,20 @@ export class LinkEditor extends React.Component { } } - viewGroupAsTable(groupId: string, groupType: string) { - let keys = LinkManager.Instance.groupMetadataKeys.get(groupType); - let groupDoc = this._groups.get(groupId); - if (keys && groupDoc) { - console.log("keys:", ...keys); - let docs: Doc[] = LinkManager.Instance.findMetadataInGroup(groupType); - let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys!], docs, { width: 200, height: 200, title: groupType + " table" })); - let ref = React.createRef(); - return
; - } else { - return ; - } - } - @action addMetadata = (groupType: string): void => { let mdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType); if (mdKeys) { - if (mdKeys.indexOf("new key") === -1) { - mdKeys.push("new key"); - } + // 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); } - renderMetadata(groupId: string) { + renderMetadata = (groupId: string): JSX.Element[] => { let metadata: Array = []; let groupDoc = this._groups.get(groupId); if (groupDoc) { @@ -377,7 +314,7 @@ export class LinkEditor extends React.Component { } render() { - let destination = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); + let destination = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); let groups: Array = []; this._groups.forEach((groupDoc, groupId) => { diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index 7e031b897..09a830c9e 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -1,84 +1,14 @@ @import "../globalCssVariables"; -#linkMenu-container { +.linkMenu { width: 100%; height: auto; - display: flex; - flex-direction: column; } -#linkMenu-searchBar { - width: 100%; - padding: 5px; - margin-bottom: 10px; - font-size: 12px; - border: 1px solid #bababa; -} - -#linkMenu-list { - margin-top: 5px; - width: 100%; - height: 100px; +.linkMenu-list { + max-height: 200px; overflow-y: scroll; } -.link-menu-group { - .link-menu-item { - border-top: 0.5px solid $light-color-secondary; - padding: 6px; - position: relative; - display: flex; - - .link-menu-item-content { - width: 100%; - } - &:last-child { - border-bottom: 0.5px solid $light-color-secondary; - } - &:hover .link-menu-item-buttons { - display: flex; - } - &:hover .link-menu-item-content { - width: calc(100% - 42px); - } - } - .link-menu-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 47bd6c3eb..ebca54c92 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -6,12 +6,8 @@ import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; 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, LinkUtils } from "../../util/LinkManager"; -import { number, string } from "prop-types"; -import { listSpec } from "../../../new_fields/Schema"; -import { Utils } from "../../../Utils"; interface Props { docView: DocumentView; @@ -23,57 +19,42 @@ export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; - // renderLinkItems(links: Doc[], key: string, type: string) { - // return links.map(link => { - // let doc = FieldValue(Cast(link[key], Doc)); - // if (doc) { - // return this._editingLink = link)} type={type} />; - // } - // }); - // } - - renderGroup(links: Doc[]) { + renderGroup = (group: Doc[]): Array => { let source = this.props.docView.Document; - return links.map(link => { - let destination = LinkUtils.findOppositeAnchor(link, source); - let doc = FieldValue(Cast(destination, Doc)); - if (doc) { - return this._editingLink = link)} type={""} />; - } + return group.map(linkDoc => { + let destination = LinkUtils.findOppositeAnchor(linkDoc, source); + return this._editingLink = linkDoc)} />; }); } - renderLinks = (links: Map>): Array => { + renderAllGroups = (groups: Map>): Array => { let linkItems: Array = []; - - links.forEach((links, group) => { + groups.forEach((group, groupType) => { linkItems.push( -
-

{group}:

+
+

{groupType}:

- {this.renderGroup(links)} + {this.renderGroup(group)}
- ) + ); }); - if (linkItems.length === 0) { - linkItems.push(

no links have been created yet

); - } + // source doc has no links + if (linkItems.length === 0) linkItems.push(

No links have been created yet. Drag the linking button onto another document to create a link.

); return linkItems; } render() { - let related: Map = LinkManager.Instance.findRelatedGroupedLinks(this.props.docView.props.Document); + let sourceDoc = this.props.docView.props.Document; + let groups: Map = LinkManager.Instance.findRelatedGroupedLinks(sourceDoc); if (this._editingLink === undefined) { return ( -
+
{/* */} -
- {/* {this.renderLinkItems(linkTo, "linkedTo", "Destination: ")} - {this.renderLinkItems(linkFrom, "linkedFrom", "Source: ")} */} - {this.renderLinks(related)} +
+ {this.renderAllGroups(groups)}
); @@ -82,6 +63,5 @@ export class LinkMenu extends React.Component { this._editingLink = undefined)}> ); } - } } \ No newline at end of file -- 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') 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 1afb8d18e0f63e7e9ab05ccf79f5f34533fdec05 Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 14 Jun 2019 16:38:25 -0400 Subject: links can be expanded in menu to view metadata --- src/client/views/nodes/LinkBox.scss | 30 ++++++++++++++++------ src/client/views/nodes/LinkBox.tsx | 51 +++++++++++++++++++++++++++---------- src/client/views/nodes/LinkMenu.tsx | 8 +++--- 3 files changed, 64 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss index 08fefaf4d..77462f611 100644 --- a/src/client/views/nodes/LinkBox.scss +++ b/src/client/views/nodes/LinkBox.scss @@ -1,29 +1,43 @@ @import "../globalCssVariables"; -.link-menu-item { - border-top: 0.5px solid $light-color-secondary; +.linkMenu-item { + border-top: 0.5px solid $main-accent; padding: 6px; position: relative; display: flex; font-size: 12px; - .link-menu-item-content { + .linkMenu-item-content { width: 100%; } + + .link-metadata { + margin-top: 6px; + padding: 3px; + border-top: 0.5px solid $light-color-secondary; + .link-metadata-row { + margin-left: 6px; + } + } &:last-child { - border-bottom: 0.5px solid $light-color-secondary; + border-bottom: 0.5px solid $main-accent; } &:hover { - .link-menu-item-buttons { + .linkMenu-item-buttons { display: flex; } - .link-menu-item-content { - width: calc(100% - 42px); + .linkMenu-item-content { + &.expand-two { + width: calc(100% - 46px); + } + &.expand-three { + width: calc(100% - 78px); + } } } } -.link-menu-item-buttons { +.linkMenu-item-buttons { display: none; position: absolute; top: 50%; diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 1a7cce4a3..9fbe83126 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faEye, faTimes, faArrowRight } from '@fortawesome/free-solid-svg-icons'; +import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observer } from "mobx-react"; import { DocumentManager } from "../../util/DocumentManager"; @@ -7,15 +7,14 @@ import { undoBatch } from "../../util/UndoManager"; import './LinkBox.scss'; import React = require("react"); import { Doc } from '../../../new_fields/Doc'; -import { StrCast } from '../../../new_fields/Types'; +import { StrCast, Cast } from '../../../new_fields/Types'; +import { observable, action } from 'mobx'; +import { LinkManager } from '../../util/LinkManager'; +library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); -library.add(faEye); -library.add(faEdit); -library.add(faTimes); -library.add(faArrowRight); - interface Props { + groupType: string; linkDoc: Doc; sourceDoc: Doc; destinationDoc: Doc; @@ -24,6 +23,8 @@ interface Props { @observer export class LinkBox extends React.Component { + @observable private _showMore: boolean = false; + @action toggleShowMore() { this._showMore = !this._showMore; } @undoBatch onFollowLink = async (e: React.PointerEvent): Promise => { @@ -36,19 +37,43 @@ export class LinkBox extends React.Component { this.props.showEditor(); } + renderMetadata = (): JSX.Element => { + let groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); + let index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase()); + let groupDoc = index > -1 ? groups[index] : undefined; + + 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 => { + return (
{key}: {StrCast(mdDoc[key])}
); + }); + } + + return (
{mdRows}
); + } + render() { + + let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType); + let canExpand = keys ? keys.length > 0 : false; + return ( -
-
+
+

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

+
+ {canExpand ?
this.toggleShowMore()}> +
: <>} +
+
+
+ {this._showMore ? this.renderMetadata() : <>}
-
-
-
-
); } diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 2fcbd25fa..aef56df67 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -19,11 +19,11 @@ export class LinkMenu extends React.Component { @observable private _editingLink?: Doc; - renderGroup = (group: Doc[]): Array => { + 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)} />; + return this._editingLink = linkDoc)} />; }); } @@ -34,13 +34,13 @@ export class LinkMenu extends React.Component {

{groupType}:

- {this.renderGroup(group)} + {this.renderGroup(group, groupType)}
); }); - // source doc has no links + // if source doc has no links push message if (linkItems.length === 0) linkItems.push(

No links have been created yet. Drag the linking button onto another document to create a link.

); return linkItems; -- cgit v1.2.3-70-g09d2 From d3e734140c52e69f3d07f1ebe145e554a062addb Mon Sep 17 00:00:00 2001 From: Fawn Date: Fri, 14 Jun 2019 17:08:05 -0400 Subject: can drag follow button on link to move anchor --- src/client/views/nodes/LinkBox.tsx | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 9fbe83126..09df1eac5 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -10,6 +10,8 @@ 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 } from '../../util/DragManager'; +import { SelectionManager } from '../../util/SelectionManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -23,6 +25,7 @@ interface Props { @observer export class LinkBox extends React.Component { + private _drag = React.createRef(); @observable private _showMore: boolean = false; @action toggleShowMore() { this._showMore = !this._showMore; } @@ -54,6 +57,30 @@ export class LinkBox extends React.Component { return (
{mdRows}
); } + 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); + + DragLinksAsDocuments(this._drag.current, e.x, e.y, SelectionManager.SelectedDocuments()[0].props.Document); + } + e.stopPropagation(); + } + render() { let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType); @@ -68,13 +95,13 @@ export class LinkBox extends React.Component { {canExpand ?
this.toggleShowMore()}>
: <>}
-
+
{this._showMore ? this.renderMetadata() : <>}
-
+
); } } \ No newline at end of file -- 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') 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 b4bd43f6e79c9dec30842262f270ca6122f1184a Mon Sep 17 00:00:00 2001 From: Fawn Date: Sat, 15 Jun 2019 17:17:45 -0400 Subject: cleaned up some leftover linkedfromdocs/linkedtodocs --- src/client/documents/Documents.ts | 31 ++--------------- src/client/util/LinkManager.ts | 3 +- src/client/views/DocumentDecorations.tsx | 3 -- .../views/collections/CollectionDockingView.tsx | 5 +-- src/client/views/nodes/DocumentView.tsx | 40 +++++++++------------- 5 files changed, 24 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9cb41aecc..268dbc927 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -87,21 +87,11 @@ const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; export namespace DocUtils { export function MakeLink(source: Doc, target: Doc) { if (LinkManager.Instance.doesLinkExist(source, target)) return; - // let protoSrc = source.proto ? source.proto : source; - // let protoTarg = target.proto ? target.proto : target; - UndoManager.RunInBatch(() => { - // let groupDoc1 = Docs.TextDocument(); - // groupDoc1.proto!.type = "*"; - // groupDoc1.proto!.metadata = Docs.TextDocument(); - // let groupDoc2 = Docs.TextDocument(); - // groupDoc2.proto!.type = "*"; - // groupDoc2.proto!.metadata = Docs.TextDocument(); + UndoManager.RunInBatch(() => { 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!.anchor1 = source; linkDoc.proto!.anchor1Page = source.curPage; linkDoc.proto!.anchor1Groups = new List([]); @@ -110,23 +100,6 @@ export namespace DocUtils { linkDoc.proto!.anchor2Page = target.curPage; linkDoc.proto!.anchor2Groups = new List([]); - // 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) { - // protoTarg.linkedFromDocs = linkedFrom = new List(); - // } - // linkedFrom.push(linkDoc); - - // let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); - // if (!linkedTo) { - // protoSrc.linkedToDocs = linkedTo = new List(); - // } - // linkedTo.push(linkDoc); - LinkManager.Instance.allLinks.push(linkDoc); return linkDoc; diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index aaed7388d..23ba9d2e4 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -30,7 +30,8 @@ export class LinkManager { } @observable public allLinks: Array = []; // list of link docs - @observable public groupMetadataKeys: Map> = new Map(); // map of group type to list of its metadata keys + @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 // finds all links that contain the given anchor public findAllRelatedLinks(anchor: Doc): Array { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index eb45c770e..6ed263ac8 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -511,9 +511,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let linkButton = null; if (SelectionManager.SelectedDocuments().length > 0) { let selFirst = SelectionManager.SelectedDocuments()[0]; - // let linkToSize = Cast(selFirst.props.Document.linkedToDocs, listSpec(Doc), []).length; - // let linkFromSize = Cast(selFirst.props.Document.linkedFromDocs, listSpec(Doc), []).length; - // let linkCount = linkToSize + linkFromSize; let linkCount = LinkManager.Instance.findAllRelatedLinks(selFirst.props.Document).length; linkButton = ( { @@ -338,9 +339,9 @@ export class CollectionDockingView extends React.Component [doc.linkedFromDocs, doc.LinkedToDocs, doc.title], + tab.reactionDisposer = reaction(() => [LinkManager.Instance.findAllRelatedLinks(doc), doc.title], () => { - counter.innerHTML = DocListCast(doc.linkedFromDocs).length + DocListCast(doc.linkedToDocs).length; + counter.innerHTML = LinkManager.Instance.findAllRelatedLinks(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/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index fc6974e6c..c1a32ad82 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -31,6 +31,7 @@ import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { ContextMenuProps } from '../ContextMenuItem'; import { list, object, createSimpleSchema } from 'serializr'; +import { LinkManager } from '../../util/LinkManager'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); @@ -49,16 +50,16 @@ library.add(faCrosshairs); library.add(faDesktop); -const linkSchema = createSchema({ - title: "string", - linkDescription: "string", - linkTags: "string", - linkedTo: Doc, - linkedFrom: Doc -}); +// const linkSchema = createSchema({ +// title: "string", +// linkDescription: "string", +// linkTags: "string", +// linkedTo: Doc, +// linkedFrom: Doc +// }); -type LinkDoc = makeInterface<[typeof linkSchema]>; -const LinkDoc = makeInterface(linkSchema); +// type LinkDoc = makeInterface<[typeof linkSchema]>; +// const LinkDoc = makeInterface(linkSchema); export interface DocumentViewProps { ContainingCollectionView: Opt; @@ -216,8 +217,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 linkedToDocs = await DocListCastAsync(this.props.Document.linkedToDocs, []); - let linkedFromDocs = await DocListCastAsync(this.props.Document.linkedFromDocs, []); + let linkedDocs = LinkManager.Instance.findAllRelatedLinks(this.props.Document); let expandedDocs: Doc[] = []; expandedDocs = subBulletDocs ? [...subBulletDocs, ...expandedDocs] : expandedDocs; expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs; @@ -252,18 +252,12 @@ export class DocumentView extends DocComponent(Docu this.props.collapseToPoint && this.props.collapseToPoint(scrpt, expandedProtoDocs); } } - else if (linkedToDocs.length || linkedFromDocs.length) { - let linkedFwdDocs = [ - linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : expandedDocs[0], - linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : expandedDocs[0]]; - - let linkedFwdPage = [ - linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : undefined, - linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : undefined]; - if (!linkedFwdDocs.some(l => l instanceof Promise)) { - let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 0].maximizeLocation, "inTab"); - DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0]); - } + else if (linkedDocs.length) { + let linkedDoc = linkedDocs.length ? linkedDocs[0] : expandedDocs[0]; + let linkedPages = [linkedDocs.length ? NumCast(linkedDocs[0].anchor1Page, undefined) : NumCast(linkedDocs[0].anchor2Page, undefined), + linkedDocs.length ? NumCast(linkedDocs[0].anchor2Page, undefined) : NumCast(linkedDocs[0].anchor1Page, undefined)]; + let maxLocation = StrCast(linkedDoc.maximizeLocation, "inTab"); + DocumentManager.Instance.jumpToDocument(linkedDoc, ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedPages[altKey ? 1 : 0]); } } } -- cgit v1.2.3-70-g09d2 From 70eaadb2773ae78f99d856c4986b8f27ebbb36ad Mon Sep 17 00:00:00 2001 From: Fawn Date: Mon, 17 Jun 2019 11:32:38 -0400 Subject: single link can be dragged from link menu --- src/client/util/DragManager.ts | 12 ++++++++++++ src/client/views/nodes/LinkBox.tsx | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index b32c25b0a..82d30e0e6 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -43,6 +43,18 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () return onItemDown; } +export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: number, linkDoc: Doc, sourceDoc: Doc) { + let draggeddoc = LinkManager.Instance.findOppositeAnchor(linkDoc, sourceDoc); + let moddrag = await Cast(draggeddoc.annotationOn, Doc); + let dragData = new DragManager.DocumentDragData(moddrag ? [moddrag] : [draggeddoc]); + DragManager.StartDocumentDrag([dragEle], dragData, x, y, { + handlers: { + dragComplete: action(emptyFunction), + }, + hideSource: false + }); +} + export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 09df1eac5..8d07547ed 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -10,7 +10,7 @@ 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 } from '../../util/DragManager'; +import { DragLinksAsDocuments, DragLinkAsDocument } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -76,7 +76,7 @@ export class LinkBox extends React.Component { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - DragLinksAsDocuments(this._drag.current, e.x, e.y, SelectionManager.SelectedDocuments()[0].props.Document); + DragLinkAsDocument(this._drag.current, e.x, e.y, this.props.linkDoc, this.props.sourceDoc); } e.stopPropagation(); } -- cgit v1.2.3-70-g09d2 From ae86fd1237873e7aa3144e7a0c6890ae60507d66 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Mon, 17 Jun 2019 20:03:03 -0400 Subject: Presentation Selection UI a bit, with bugs --- src/client/views/MainView.tsx | 7 +- .../views/presentationview/PresentationView.tsx | 117 ++++++++++++++------- 2 files changed, 85 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f78879efe..7d2aa3199 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -32,6 +32,7 @@ import { listSpec } from '../../new_fields/Schema'; import { Id } from '../../new_fields/FieldSymbols'; import { HistoryUtil } from '../util/History'; import { CollectionBaseView } from './collections/CollectionBaseView'; +import { List } from '../../new_fields/List'; @observer @@ -46,7 +47,7 @@ export class MainView extends React.Component { private set mainContainer(doc: Opt) { if (doc) { if (!("presentationView" in doc)) { - doc.presentationView = Docs.TreeDocument([], { title: "Presentation" }); + doc.presentationView = new List([Docs.TreeDocument([], { title: "Presentation" })]); } CurrentUserUtils.UserDocument.activeWorkspace = doc; } @@ -203,7 +204,7 @@ export class MainView extends React.Component { zoomToScale={emptyFunction} getScale={returnOne} />; - let castRes = mainCont ? FieldValue(Cast(mainCont.presentationView, Doc)) : undefined; + let castRes = mainCont ? FieldValue(Cast(mainCont.presentationView, listSpec(Doc))) : undefined; console.log("GETTING mainContent()"); console.log(castRes instanceof Promise); console.log(castRes); @@ -211,7 +212,7 @@ export class MainView extends React.Component { {({ measureRef }) =>
{content} - {castRes ? : null} + {castRes ? : null}
} ; diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 6cf5fad7e..ff5c6df9c 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -13,18 +13,22 @@ import { CurrentUserUtils } from "../../../server/authentication/models/current_ import PresentationElement, { buttonIndex } from "./PresentationElement"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faArrowRight, faArrowLeft, faPlay, faStop } from '@fortawesome/free-solid-svg-icons'; +import { faArrowRight, faArrowLeft, faPlay, faStop, faPlus, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { Docs } from "../../documents/Documents"; library.add(faArrowLeft); library.add(faArrowRight); library.add(faPlay); library.add(faStop); +library.add(faPlus); +library.add(faTimes); export interface PresViewProps { - Document: Doc; + Documents: List; } -interface PresListProps extends PresViewProps { +interface PresListProps { + mainDocument: Doc; deleteDocument(index: number): void; gotoDocument(index: number, fromDoc: number): Promise; groupMappings: Map; @@ -85,15 +89,17 @@ class PresentationViewList extends React.Component { }); } + + render() { - const children = DocListCast(this.props.Document.data); + const children = DocListCast(this.props.mainDocument.data); this.initializeGroupIds(children); this.initializeScaleViews(children); this.props.setChildrenDocs(children); return (
- {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={index} mainDocument={this.props.Document} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} presButtonBackUp={this.props.presButtonBackUp} presGroupBackUp={this.props.presGroupBackUp} />)} + {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={index} mainDocument={this.props.mainDocument} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} presButtonBackUp={this.props.presButtonBackUp} presGroupBackUp={this.props.presGroupBackUp} />)}
); } @@ -115,17 +121,32 @@ export class PresentationView extends React.Component { //back-up so that presentation stays the way it's when refreshed @observable presGroupBackUp: Doc = new Doc(); @observable presButtonBackUp: Doc = new Doc(); + @observable curPresentation: Doc = new Doc(); + @observable presentationsMapping: Map = new Map(); + @observable selectedPresentation: HTMLSelectElement = new HTMLSelectElement(); + + + //initilize class variables + constructor(props: PresViewProps) { + super(props); + PresentationView.Instance = this; + } + async componentWillMount() { + let docAtZero = await this.props.Documents[0]; + runInAction(() => this.curPresentation = docAtZero); + } + componentDidMount() { //getting both backUp documents - let castedGroupBackUp = Cast(this.props.Document.presGroupBackUp, Doc); - let castedButtonBackUp = Cast(this.props.Document.presButtonBackUp, Doc); + let castedGroupBackUp = Cast(this.curPresentation.presGroupBackUp, Doc); + let castedButtonBackUp = Cast(this.curPresentation.presButtonBackUp, Doc); //if instantiated before if (castedGroupBackUp instanceof Promise) { castedGroupBackUp.then(doc => { let toAssign = doc ? doc : new Doc(); - this.props.Document.presGroupBackUp = toAssign; + this.curPresentation.presGroupBackUp = toAssign; runInAction(() => this.presGroupBackUp = toAssign); if (doc) { if (toAssign[Id] === doc[Id]) { @@ -138,7 +159,7 @@ export class PresentationView extends React.Component { runInAction(() => { let toAssign = new Doc(); this.presGroupBackUp = toAssign; - this.props.Document.presGroupBackUp = toAssign; + this.curPresentation.presGroupBackUp = toAssign; }); @@ -148,7 +169,7 @@ export class PresentationView extends React.Component { if (castedButtonBackUp instanceof Promise) { castedButtonBackUp.then(doc => { let toAssign = doc ? doc : new Doc(); - this.props.Document.presButtonBackUp = toAssign; + this.curPresentation.presButtonBackUp = toAssign; runInAction(() => this.presButtonBackUp = toAssign); }); @@ -157,14 +178,14 @@ export class PresentationView extends React.Component { runInAction(() => { let toAssign = new Doc(); this.presButtonBackUp = toAssign; - this.props.Document.presButtonBackUp = toAssign; + this.curPresentation.presButtonBackUp = toAssign; }); } //storing the presentation status,ie. whether it was stopped or playing - let presStatusBackUp = BoolCast(this.props.Document.presStatus, null); + let presStatusBackUp = BoolCast(this.curPresentation.presStatus, null); runInAction(() => this.presStatus = presStatusBackUp); } @@ -188,9 +209,9 @@ export class PresentationView extends React.Component { //observable means render is re-called every time variable is changed @observable collapsed: boolean = false; - closePresentation = action(() => this.props.Document.width = 0); + closePresentation = action(() => this.curPresentation.width = 0); next = async () => { - const current = NumCast(this.props.Document.selectedDoc); + const current = NumCast(this.curPresentation.selectedDoc); //asking to get document at current index let docAtCurrentNext = await this.getDocAtIndex(current + 1); if (docAtCurrentNext === undefined) { @@ -213,7 +234,7 @@ export class PresentationView extends React.Component { } back = async () => { - const current = NumCast(this.props.Document.selectedDoc); + const current = NumCast(this.curPresentation.selectedDoc); //requesting for the doc at current index let docAtCurrent = await this.getDocAtIndex(current); if (docAtCurrent === undefined) { @@ -379,7 +400,7 @@ export class PresentationView extends React.Component { * Async function that supposedly return the doc that is located at given index. */ getDocAtIndex = async (index: number) => { - const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + const list = FieldValue(Cast(this.curPresentation.data, listSpec(Doc))); if (!list) { return undefined; } @@ -387,7 +408,7 @@ export class PresentationView extends React.Component { return undefined; } - this.props.Document.selectedDoc = index; + this.curPresentation.selectedDoc = index; //awaiting async call to finish to get Doc instance const doc = await list[index]; return doc; @@ -395,21 +416,21 @@ export class PresentationView extends React.Component { @action public RemoveDoc = (index: number) => { - const value = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + const value = FieldValue(Cast(this.curPresentation.data, listSpec(Doc))); if (value) { value.splice(index, 1); } } @action public gotoDocument = async (index: number, fromDoc: number) => { - const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + const list = FieldValue(Cast(this.curPresentation.data, listSpec(Doc))); if (!list) { return; } if (index < 0 || index >= list.length) { return; } - this.props.Document.selectedDoc = index; + this.curPresentation.selectedDoc = index; if (!this.presStatus) { this.presStatus = true; @@ -425,11 +446,7 @@ export class PresentationView extends React.Component { } - //initilize class variables - constructor(props: PresViewProps) { - super(props); - PresentationView.Instance = this; - } + /** * Adds a document to the presentation view @@ -437,14 +454,14 @@ export class PresentationView extends React.Component { @action public PinDoc(doc: Doc) { //add this new doc to props.Document - const data = Cast(this.props.Document.data, listSpec(Doc)); + const data = Cast(this.curPresentation.data, listSpec(Doc)); if (data) { data.push(doc); } else { - this.props.Document.data = new List([doc]); + this.curPresentation.data = new List([doc]); } - this.props.Document.width = 300; + this.curPresentation.width = 300; } @action @@ -468,10 +485,10 @@ export class PresentationView extends React.Component { } else { this.presStatus = true; this.startPresentation(0); - const current = NumCast(this.props.Document.selectedDoc); + const current = NumCast(this.curPresentation.selectedDoc); this.gotoDocument(0, current); } - this.props.Document.presStatus = this.presStatus; + this.curPresentation.presStatus = this.presStatus; } @action @@ -484,7 +501,7 @@ export class PresentationView extends React.Component { //doc.presentId = Utils.GenerateGuid(); doc.opacity = 1; }); - this.props.Document.selectedDoc = 0; + this.curPresentation.selectedDoc = 0; if (this.childrenDocs.length === 0) { return; } @@ -518,23 +535,51 @@ export class PresentationView extends React.Component { } + @action + addNewPresentation = () => { + let title = "Presentation " + (this.props.Documents.length + 1); + let newPresentationDoc = Docs.TreeDocument([], { title: title }); + this.props.Documents.push(newPresentationDoc); + this.curPresentation = newPresentationDoc; + } + + @action + getSelectedPresentation = (e: React.ChangeEvent) => { + this.curPresentation = this.presentationsMapping.get(e.target.value)!; + } + + render() { - let titleStr = StrCast(this.props.Document.title); - let width = NumCast(this.props.Document.width); + let titleStr = StrCast(this.curPresentation.title); + let width = NumCast(this.curPresentation.width); + let presentationList = DocListCast(this.props.Documents); + + + console.log("width: ", width); + console.log("title : ", titleStr); //TODO: next and back should be icons return (
-
{titleStr}
- + {/*
{titleStr}
*/} + + + +
{this.renderPlayPauseButton()}
- +
); } -- 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') 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 6fcd0d8d6fb1471b8af460f6d80bdf0d0e681566 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 18 Jun 2019 15:17:27 -0400 Subject: added button to delete a link --- src/client/views/nodes/LinkEditor.scss | 21 +++++++++++++++------ src/client/views/nodes/LinkEditor.tsx | 18 +++++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 6aac39f45..154b4abe3 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -10,6 +10,21 @@ margin-bottom: 6px; } +.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-groupsLabel { display: flex; justify-content: space-between; @@ -23,12 +38,6 @@ } } -.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; diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 484682c22..29ead7388 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -7,14 +7,12 @@ import { Doc } from "../../../new_fields/Doc"; import { LinkManager } from "../../util/LinkManager"; import { Docs } from "../../documents/Documents"; import { Utils } from "../../../Utils"; -import { faArrowLeft, faEllipsisV, faTable } from '@fortawesome/free-solid-svg-icons'; +import { faArrowLeft, faEllipsisV, faTable, faTrash } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { SetupDrag } from "../../util/DragManager"; -library.add(faArrowLeft); -library.add(faEllipsisV); -library.add(faTable); +library.add(faArrowLeft, faEllipsisV, faTable, faTrash); interface GroupTypesDropdownProps { @@ -162,6 +160,13 @@ export class LinkEditor extends React.Component { this._groups = groups; } + @action + deleteLink = (): void => { + let index = LinkManager.Instance.allLinks.indexOf(this.props.linkDoc); + LinkManager.Instance.allLinks.splice(index, 1); + this.props.showLinks(); + } + @action addGroup = (): void => { // new group only gets added if there is not already a group with type "new group" @@ -324,7 +329,10 @@ export class LinkEditor extends React.Component { return (
-

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

+
+

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

+ +
Relationships: -- cgit v1.2.3-70-g09d2 From 8e5afb5bbb47324a381b5184254e77eba7bd8536 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 18 Jun 2019 16:30:24 -0400 Subject: can click on button link to node in different context than source --- .../CollectionFreeFormLinkView.scss | 1 + .../CollectionFreeFormLinkView.tsx | 28 +++++++++++++--------- .../CollectionFreeFormLinksView.tsx | 6 ++--- 3 files changed, 21 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index 7a0fd2b31..fc5212edd 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -9,6 +9,7 @@ opacity: 0.5; transform: translate(10000px,10000px); pointer-events: all; + cursor: pointer; } .collectionfreeformlinkview-linkText { stroke: rgb(0,0,0); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 36ffac9c8..4d477454b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -6,6 +6,7 @@ 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; @@ -18,6 +19,7 @@ export interface CollectionFreeFormLinkViewProps { sourceView: DocumentView; targetView: DocumentView; sameContext: boolean; + addDocTab: (document: Doc, where: string) => void; } @observer @@ -42,6 +44,13 @@ export class CollectionFreeFormLinkView extends React.Component { + // TODO: would be nicer to open docview in context + e.stopPropagation(); + console.log("follow"); + this.props.addDocTab(this.props.targetView.props.Document, "onRight"); + } + render() { // let l = this.props.LinkDocs; // let a = this.props.A; @@ -58,23 +67,20 @@ export class CollectionFreeFormLinkView extends React.Component text += StrCast(l.title) + "(" + StrCast(l.linkDescription) + "), "); - // text = ""; + let containing = ""; + if (this.props.targetView.props.ContainingCollectionView) { + containing = StrCast(this.props.targetView.props.ContainingCollectionView.props.Document.title); + } + + let text = "link to " + StrCast(this.props.targetView.props.Document.title) + (containing === "" ? "" : (" in the context of " + containing)); return ( <> - {!this.props.sameContext ? : <>} + {!this.props.sameContext ? : <>} + {!this.props.sameContext ? {text} : <>} {/* */} {/* diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index fc92c81d5..86625863f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -190,12 +190,12 @@ export class CollectionFreeFormLinksView extends React.Component { // 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 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 inContainer = u.sameContext ? sourceIn || targetIn : sourceIn; if (inContainer) { // console.log("key", key, StrCast(u.sourceView.Document.title), StrCast(u.targetView.Document.title)); - return ; + return ; } else { return
; } -- cgit v1.2.3-70-g09d2 From 4ffcff69a2fc767c6a03d46d7296b6a8c7ffd281 Mon Sep 17 00:00:00 2001 From: madelinegr Date: Tue, 18 Jun 2019 19:13:45 -0400 Subject: Presentations Listed, Option to Change Added, and --- .../views/presentationview/PresentationElement.tsx | 28 ++++++++- .../views/presentationview/PresentationView.tsx | 69 +++++++++++++++++++--- 2 files changed, 85 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 00dc07921..8ec6348f2 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -56,7 +56,13 @@ export enum buttonIndex { @observer export default class PresentationElement extends React.Component { - @observable selectedButtons: boolean[] = new Array(6); + @observable selectedButtons: boolean[]; + + + constructor(props: PresentationElementProps) { + super(props); + this.selectedButtons = new Array(6); + } /** * Getter to get the status of the buttons. @@ -67,6 +73,16 @@ export default class PresentationElement extends React.Component { + //get the list that stores docs that keep track of buttons let castedList = Cast(this.props.presButtonBackUp.selectedButtonDocs, listSpec(Doc)); if (!castedList) { @@ -74,17 +90,21 @@ export default class PresentationElement extends React.Component this.selectedButtons = selectedButtonOfDoc); + console.log("New Selected Buttons: ", this.selectedButtons); } } - } /** @@ -337,6 +357,8 @@ export default class PresentationElement extends React.Component { this.initializeGroupIds(children); this.initializeScaleViews(children); this.props.setChildrenDocs(children); + console.log(this.props.mainDocument, " re-rendering"); return (
@@ -123,7 +124,9 @@ export class PresentationView extends React.Component { @observable presButtonBackUp: Doc = new Doc(); @observable curPresentation: Doc = new Doc(); @observable presentationsMapping: Map = new Map(); - @observable selectedPresentation: HTMLSelectElement = new HTMLSelectElement(); + @observable presentationsKeyMapping: Map = new Map(); + @observable selectedPresentation: HTMLSelectElement | undefined; + @observable currentSelectedPresValue: string | undefined; //initilize class variables @@ -134,12 +137,32 @@ export class PresentationView extends React.Component { async componentWillMount() { + this.props.Documents.forEach(async (doc, index: number) => { + let curDoc: Doc = await doc; + let newGuid = Utils.GenerateGuid(); + this.presentationsKeyMapping.set(curDoc, newGuid); + this.presentationsMapping.set(newGuid, curDoc); + if (index === 0) { + runInAction(() => this.currentSelectedPresValue = newGuid); + runInAction(() => this.curPresentation = curDoc); + } + }); + } + + async componentDidMount() { + let docAtZero = await this.props.Documents[0]; runInAction(() => this.curPresentation = docAtZero); + + this.setPresentationBackUps(); + + } - componentDidMount() { + + setPresentationBackUps = async () => { //getting both backUp documents + let castedGroupBackUp = Cast(this.curPresentation.presGroupBackUp, Doc); let castedButtonBackUp = Cast(this.curPresentation.presButtonBackUp, Doc); //if instantiated before @@ -154,7 +177,12 @@ export class PresentationView extends React.Component { } } }); + //if never instantiated a store doc yet + } else if (castedGroupBackUp instanceof Doc) { + let castedDoc: Doc = await castedGroupBackUp; + runInAction(() => this.presGroupBackUp = castedDoc); + this.retrieveGroupMappings(); } else { runInAction(() => { let toAssign = new Doc(); @@ -170,10 +198,16 @@ export class PresentationView extends React.Component { castedButtonBackUp.then(doc => { let toAssign = doc ? doc : new Doc(); this.curPresentation.presButtonBackUp = toAssign; + console.log("Called the promise one!!"); runInAction(() => this.presButtonBackUp = toAssign); }); //if never instantiated a store doc yet + } else if (castedButtonBackUp instanceof Doc) { + let castedDoc: Doc = await castedButtonBackUp; + runInAction(() => this.presButtonBackUp = castedDoc); + console.log("Called the important action"); + } else { runInAction(() => { let toAssign = new Doc(); @@ -541,11 +575,30 @@ export class PresentationView extends React.Component { let newPresentationDoc = Docs.TreeDocument([], { title: title }); this.props.Documents.push(newPresentationDoc); this.curPresentation = newPresentationDoc; + let newGuid = Utils.GenerateGuid(); + this.presentationsMapping.set(newGuid, newPresentationDoc); + this.presentationsKeyMapping.set(newPresentationDoc, newGuid); + this.currentSelectedPresValue = newGuid; + this.setPresentationBackUps(); + + // if (this.selectedPresentation) { + // this.selectedPresentation.selectedIndex = 1; + // console.log("Selected Pres: ", this.selectedPresentation); + // console.log("New value: ", this.selectedPresentation.value); + // console.log("New Index: ", this.selectedPresentation.selectedIndex); + + + // } + } @action getSelectedPresentation = (e: React.ChangeEvent) => { - this.curPresentation = this.presentationsMapping.get(e.target.value)!; + let selectedGuid = e.target.value; + this.curPresentation = this.presentationsMapping.get(selectedGuid)!; + this.currentSelectedPresValue = selectedGuid; + this.setPresentationBackUps(); + } @@ -555,19 +608,17 @@ export class PresentationView extends React.Component { let presentationList = DocListCast(this.props.Documents); - console.log("width: ", width); - console.log("title : ", titleStr); //TODO: next and back should be icons return (
{/*
{titleStr}
*/} - this.selectedPresentation = e}> {presentationList.map((doc: Doc, index: number) => { - let newGuid = Utils.GenerateGuid(); - this.presentationsMapping.set(newGuid, doc); - return ; + let mappedGuid = this.presentationsKeyMapping.get(doc); + let docGuid: string = mappedGuid ? mappedGuid.toString() : ""; + return ; })} -- cgit v1.2.3-70-g09d2 From fb62f3b2e39bbe2dd3da5eaffedbaa8e60f06dbb Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Wed, 19 Jun 2019 12:35:54 -0400 Subject: Grouping for different presentations fixed --- .../views/presentationview/PresentationView.tsx | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 01cddbc45..2ebbb84ea 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -233,6 +233,11 @@ export class PresentationView extends React.Component { castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { let castedGrouping = await DocListCastAsync(groupDoc.grouping); let castedKey = StrCast(groupDoc.presentIdStore, null); + if (castedGrouping) { + castedGrouping.forEach((doc: Doc) => { + doc.presentId = castedKey; + }); + } if (castedGrouping !== undefined && castedKey !== undefined) { this.groupMappings.set(castedKey, castedGrouping); } @@ -481,6 +486,38 @@ export class PresentationView extends React.Component { } + resetGroupIds = async () => { + let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); + if (castedGroupDocs !== undefined) { + castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { + let castedGrouping = await DocListCastAsync(groupDoc.grouping); + if (castedGrouping) { + castedGrouping.forEach((doc: Doc) => { + doc.presentId = Utils.GenerateGuid(); + }); + } + // let castedKey = StrCast(groupDoc.presentIdStore, null); + // if (castedGrouping !== undefined && castedKey !== undefined) { + // this.groupMappings.set(castedKey, castedGrouping); + // } + }); + } + } + + // reloadGroupIds = async () => { + // let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); + // if (castedGroupDocs !== undefined) { + // castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { + // let castedGrouping = await DocListCastAsync(groupDoc.grouping); + // let castedKey = StrCast(groupDoc.presentIdStore, null); + // if (castedGrouping !== undefined && castedKey !== undefined) { + // this.groupMappings.set(castedKey, castedGrouping); + // } + // }); + // } + // } + + /** * Adds a document to the presentation view @@ -578,6 +615,7 @@ export class PresentationView extends React.Component { let newGuid = Utils.GenerateGuid(); this.presentationsMapping.set(newGuid, newPresentationDoc); this.presentationsKeyMapping.set(newPresentationDoc, newGuid); + this.resetGroupIds(); this.currentSelectedPresValue = newGuid; this.setPresentationBackUps(); @@ -596,6 +634,7 @@ export class PresentationView extends React.Component { getSelectedPresentation = (e: React.ChangeEvent) => { let selectedGuid = e.target.value; this.curPresentation = this.presentationsMapping.get(selectedGuid)!; + this.resetGroupIds(); this.currentSelectedPresValue = selectedGuid; this.setPresentationBackUps(); -- cgit v1.2.3-70-g09d2 From f362dbfc237536c6c4a8c6d088c3dc818080f7c2 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 19 Jun 2019 12:50:58 -0400 Subject: both tail ends of a cut link appear on hover/focus of an anchor --- src/client/documents/Documents.ts | 12 ++++- src/client/util/DragManager.ts | 9 ++++ .../CollectionFreeFormLinkView.tsx | 21 +------- .../CollectionFreeFormLinkWithProxyView.tsx | 60 ++++++++++++++++++++++ .../CollectionFreeFormLinksView.tsx | 59 ++++++++++++--------- 5 files changed, 116 insertions(+), 45 deletions(-) create mode 100644 src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 002de8b5f..79ba433c8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -99,8 +99,18 @@ export namespace DocUtils { linkDocProto.anchor2 = target; linkDocProto.anchor2Page = target.curPage; linkDocProto.anchor2Groups = new List([]); + linkDocProto.context = targetContext; + let proxy1 = Docs.TextDocument({ width: 300, height: 100, borderRounding: 0 }); + let proxy1Proto = Doc.GetProto(proxy1); + let proxy2 = Docs.TextDocument({ width: 300, height: 100, borderRounding: 0 }); + let proxy2Proto = Doc.GetProto(proxy2); + + linkDocProto.proxy1 = proxy1; // src: 1 targ: 2 + linkDocProto.proxy2 = proxy2; // src: 2 targ: 1 + + LinkManager.Instance.allLinks.push(linkDoc); return linkDoc; @@ -377,7 +387,7 @@ export namespace Docs { } /* - + this template requires an additional style setting on the collectionView-cont to make the layout relative .collectionView-cont { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 82d30e0e6..4787ac40f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -45,6 +45,9 @@ 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]); DragManager.StartDocumentDrag([dragEle], dragData, x, y, { @@ -58,6 +61,9 @@ export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: num export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; + + // TODO: if not in same context then don't drag + if (srcTarg) { let linkDocs = LinkManager.Instance.findAllRelatedLinks(srcTarg); if (linkDocs) { @@ -74,6 +80,9 @@ 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; + // }; DragManager.StartDocumentDrag([dragEle], dragData, x, y, { handlers: { dragComplete: action(emptyFunction), diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 4d477454b..f995a35e3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -18,8 +18,6 @@ export interface CollectionFreeFormLinkViewProps { sourceView: DocumentView; targetView: DocumentView; - sameContext: boolean; - addDocTab: (document: Doc, where: string) => void; } @observer @@ -44,12 +42,6 @@ export class CollectionFreeFormLinkView extends React.Component { - // TODO: would be nicer to open docview in context - e.stopPropagation(); - console.log("follow"); - this.props.addDocTab(this.props.targetView.props.Document, "onRight"); - } render() { // let l = this.props.LinkDocs; @@ -62,25 +54,14 @@ export class CollectionFreeFormLinkView extends React.Component - {!this.props.sameContext ? : <>} - {!this.props.sameContext ? {text} : <>} + {/* */} {/* diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx new file mode 100644 index 000000000..81a00ba95 --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx @@ -0,0 +1,60 @@ +import { observer } from "mobx-react"; +import { Doc, HeightSym, WidthSym } from "../../../../new_fields/Doc"; +import { BoolCast, NumCast, StrCast } from "../../../../new_fields/Types"; +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"; +import { observable } from "mobx"; + +export interface CollectionFreeFormLinkViewProps { + sourceView: DocumentView; + targetView: DocumentView; + proxyDoc: Doc; + addDocTab: (document: Doc, where: string) => void; +} + +@observer +export class CollectionFreeFormLinkWithProxyView extends React.Component { + + // @observable private _proxyX: number = NumCast(this.props.proxyDoc.x); + // @observable private _proxyY: number = NumCast(this.props.proxyDoc.y); + + followButton = (e: React.PointerEvent): void => { + // TODO: would be nicer to open docview in context + e.stopPropagation(); + console.log("follow"); + this.props.addDocTab(this.props.targetView.props.Document, "onRight"); + } + + render() { + let a1 = this.props.sourceView; + let a2 = this.props.proxyDoc; + 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.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 containing = ""; + // if (this.props.targetView.props.ContainingCollectionView) { + // containing = StrCast(this.props.targetView.props.ContainingCollectionView.props.Document.title); + // } + + // let text = "link to " + StrCast(this.props.targetView.props.Document.title) + (containing === "" ? "" : (" in the context of " + containing)); + return ( + <> + + {/* + {text} */} + + ); + } +} + +//onPointerDown={this.followButton} \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 86625863f..eaef1f32a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -11,6 +11,8 @@ import { CollectionViewProps } from "../CollectionSubView"; import "./CollectionFreeFormLinksView.scss"; import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView"; import React = require("react"); +import { CollectionFreeFormLinkWithProxyView } from "./CollectionFreeFormLinkWithProxyView"; +import { Docs } from "../../../documents/Documents"; @observer export class CollectionFreeFormLinksView extends React.Component { @@ -159,47 +161,56 @@ export class CollectionFreeFormLinksView extends React.Component { - // console.log("FIND UNIQUE PAIRS"); let connections = DocumentManager.Instance.LinkedDocumentViews; - let unique: Array<{ sourceView: DocumentView, targetView: DocumentView, sameContext: boolean }> = []; + 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 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; - 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 }); + // 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 { - // 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 }); - } + unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc }); + unique.add({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc }); } }); - console.log("\n UNIQUE"); + let uniqueList: JSX.Element[] = []; 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 ? 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 inContainer = u.sameContext ? sourceIn || targetIn : sourceIn; + let sameContext = u.sourceView.props.ContainingCollectionView === u.targetView.props.ContainingCollectionView; + let inContainer = sameContext ? sourceIn || targetIn : sourceIn; + if (inContainer) { - // console.log("key", key, StrCast(u.sourceView.Document.title), StrCast(u.targetView.Document.title)); - return ; - } else { - return
; + // let alias = Doc.MakeAlias(proxy); + if (sameContext) { + uniqueList.push(); + } else { + 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); + + let context = u.targetView.props.ContainingCollectionView ? (" in the context of " + StrCast(u.targetView.props.ContainingCollectionView.props.Document.title)) : ""; + let text = proxyKey + " link to " + StrCast(u.targetView.props.Document.title) + context; + + let proxyProto = Doc.GetProto(proxy); + proxyProto.data = text; + + this.props.addDocument(proxy, false); + uniqueList.push(); + } } }); + return uniqueList; } render() { -- cgit v1.2.3-70-g09d2 From a288a2fd0a30a3a16dd01bc4e12dcf6bc117c766 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Wed, 19 Jun 2019 15:25:24 -0400 Subject: 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. --- .../views/presentationview/PresentationElement.tsx | 11 ++- .../views/presentationview/PresentationView.tsx | 89 +++++++++++++++------- 2 files changed, 70 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 8ec6348f2..a74cbbd65 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -98,10 +98,8 @@ export default class PresentationElement extends React.Component this.selectedButtons = selectedButtonOfDoc); - console.log("New Selected Buttons: ", this.selectedButtons); } } @@ -325,6 +323,10 @@ export default class PresentationElement extends React.Component { + + /** * Method that initializes presentation ids for the * docs that is in the presentation, when presentation list * gets re-rendered. It makes sure to not assign ids to the * docs that are in the group, so that mapping won't be disrupted. */ + @action initializeGroupIds = async (docList: Doc[]) => { docList.forEach(async (doc: Doc, index: number) => { @@ -89,14 +92,11 @@ class PresentationViewList extends React.Component { }); } - - render() { const children = DocListCast(this.props.mainDocument.data); this.initializeGroupIds(children); this.initializeScaleViews(children); this.props.setChildrenDocs(children); - console.log(this.props.mainDocument, " re-rendering"); return (
@@ -125,8 +125,10 @@ export class PresentationView extends React.Component { @observable curPresentation: Doc = new Doc(); @observable presentationsMapping: Map = new Map(); @observable presentationsKeyMapping: Map = new Map(); - @observable selectedPresentation: HTMLSelectElement | undefined; @observable currentSelectedPresValue: string | undefined; + @observable PresTitleInputOpen: boolean = false; + @observable titleInputElement: HTMLInputElement | undefined; + //@observable presTitle: string = "Presentation"; //initilize class variables @@ -156,7 +158,6 @@ export class PresentationView extends React.Component { this.setPresentationBackUps(); - } @@ -198,7 +199,6 @@ export class PresentationView extends React.Component { castedButtonBackUp.then(doc => { let toAssign = doc ? doc : new Doc(); this.curPresentation.presButtonBackUp = toAssign; - console.log("Called the promise one!!"); runInAction(() => this.presButtonBackUp = toAssign); }); @@ -206,7 +206,6 @@ export class PresentationView extends React.Component { } else if (castedButtonBackUp instanceof Doc) { let castedDoc: Doc = await castedButtonBackUp; runInAction(() => this.presButtonBackUp = castedDoc); - console.log("Called the important action"); } else { runInAction(() => { @@ -551,7 +550,7 @@ export class PresentationView extends React.Component { @action startOrResetPres = () => { if (this.presStatus) { - this.presStatus = false; + //this.presStatus = false; this.resetPresentation(); } else { this.presStatus = true; @@ -566,18 +565,28 @@ export class PresentationView extends React.Component { resetPresentation = () => { //this.groupMappings = new Map(); //let selectedButtons: boolean[]; - this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { - //selectedButtons = component.selected; - //selectedButtons.forEach((val: boolean, index: number) => selectedButtons[index] = false); - //doc.presentId = Utils.GenerateGuid(); + // this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { + // //selectedButtons = component.selected; + // //selectedButtons.forEach((val: boolean, index: number) => selectedButtons[index] = false); + // //doc.presentId = Utils.GenerateGuid(); + // doc.opacity = 1; + // doc.viewScale = 1; + // }); + + + this.childrenDocs.forEach((doc: Doc) => { doc.opacity = 1; + doc.viewScale = 1; }); this.curPresentation.selectedDoc = 0; + this.presStatus = false; + this.curPresentation.presStatus = this.presStatus; if (this.childrenDocs.length === 0) { return; } DocumentManager.Instance.zoomIntoScale(this.childrenDocs[0], 1); - this.childrenDocs[0].viewScale = 1; + + // this.childrenDocs[0].viewScale = 1; } @@ -607,18 +616,21 @@ export class PresentationView extends React.Component { } @action - addNewPresentation = () => { - let title = "Presentation " + (this.props.Documents.length + 1); - let newPresentationDoc = Docs.TreeDocument([], { title: title }); + addNewPresentation = (presTitle: string) => { + //let title = "Presentation " + (this.props.Documents.length + 1); + let newPresentationDoc = Docs.TreeDocument([], { title: presTitle }); this.props.Documents.push(newPresentationDoc); this.curPresentation = newPresentationDoc; let newGuid = Utils.GenerateGuid(); this.presentationsMapping.set(newGuid, newPresentationDoc); this.presentationsKeyMapping.set(newPresentationDoc, newGuid); this.resetGroupIds(); + this.resetPresentation(); this.currentSelectedPresValue = newGuid; this.setPresentationBackUps(); + + // if (this.selectedPresentation) { // this.selectedPresentation.selectedIndex = 1; // console.log("Selected Pres: ", this.selectedPresentation); @@ -635,16 +647,44 @@ export class PresentationView extends React.Component { let selectedGuid = e.target.value; this.curPresentation = this.presentationsMapping.get(selectedGuid)!; this.resetGroupIds(); + this.resetPresentation(); this.currentSelectedPresValue = selectedGuid; this.setPresentationBackUps(); + + } + + renderSelectOrPresSelection = () => { + let presentationList = DocListCast(this.props.Documents); + if (this.PresTitleInputOpen) { + return this.titleInputElement = e!} type="text" className="presentationView-title" placeholder="Enter Name!" onKeyDown={this.submitPresentationTitle} />; + } else { + return ; + } + } + + @action + submitPresentationTitle = (e: React.KeyboardEvent) => { + if (e.keyCode === 13) { + let presTitle = this.titleInputElement!.value; + this.titleInputElement!.value = ""; + this.PresTitleInputOpen = false; + if (presTitle === "") { + presTitle = "Presentation"; + } + this.addNewPresentation(presTitle); + } } render() { - let titleStr = StrCast(this.curPresentation.title); let width = NumCast(this.curPresentation.width); - let presentationList = DocListCast(this.props.Documents); @@ -652,16 +692,11 @@ export class PresentationView extends React.Component { return (
- {/*
{titleStr}
*/} - + {this.renderSelectOrPresSelection()} - +
-- cgit v1.2.3-70-g09d2 From 4c1383e47f2203a00bc7f3d73c209f3149d6a772 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Wed, 19 Jun 2019 15:53:05 -0400 Subject: ... --- src/client/views/presentationview/PresentationElement.tsx | 2 +- src/client/views/presentationview/PresentationView.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index a74cbbd65..a84bbbf3c 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -56,7 +56,7 @@ export enum buttonIndex { @observer export default class PresentationElement extends React.Component { - @observable selectedButtons: boolean[]; + @observable private selectedButtons: boolean[]; constructor(props: PresentationElementProps) { diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 97ec4e2fa..ad3a4bffe 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -453,10 +453,11 @@ export class PresentationView extends React.Component { } @action - public RemoveDoc = (index: number) => { + public RemoveDoc = async (index: number) => { const value = FieldValue(Cast(this.curPresentation.data, listSpec(Doc))); if (value) { - value.splice(index, 1); + let removedDoc = await value.splice(index, 1)[0]; + this.presElementsMappings.delete(removedDoc); } } @action -- cgit v1.2.3-70-g09d2 From 6fc6054dc7aea144fd967a8cb3fe7d8fe5ec6d6d Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Wed, 19 Jun 2019 19:13:30 -0400 Subject: 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 --- .../views/presentationview/PresentationView.tsx | 71 +++++++++++++++++----- 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index ad3a4bffe..2b3f5e199 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -13,7 +13,7 @@ import { CurrentUserUtils } from "../../../server/authentication/models/current_ import PresentationElement, { buttonIndex } from "./PresentationElement"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faArrowRight, faArrowLeft, faPlay, faStop, faPlus, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { faArrowRight, faArrowLeft, faPlay, faStop, faPlus, faTimes, faMinus } from '@fortawesome/free-solid-svg-icons'; import { Docs } from "../../documents/Documents"; library.add(faArrowLeft); @@ -22,6 +22,7 @@ library.add(faPlay); library.add(faStop); library.add(faPlus); library.add(faTimes); +library.add(faMinus); export interface PresViewProps { Documents: List; @@ -100,7 +101,7 @@ class PresentationViewList extends React.Component { return (
- {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={index} mainDocument={this.props.mainDocument} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} presButtonBackUp={this.props.presButtonBackUp} presGroupBackUp={this.props.presGroupBackUp} />)} + {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={doc[Id]} mainDocument={this.props.mainDocument} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} presButtonBackUp={this.props.presButtonBackUp} presGroupBackUp={this.props.presGroupBackUp} />)}
); } @@ -458,6 +459,40 @@ export class PresentationView extends React.Component { if (value) { let removedDoc = await value.splice(index, 1)[0]; this.presElementsMappings.delete(removedDoc); + + let removedDocPresentId = StrCast(removedDoc.presentId); + if (this.groupMappings.has(removedDocPresentId)) { + let removedDocsGroup = this.groupMappings.get(removedDocPresentId); + if (removedDocsGroup) { + removedDocsGroup.splice(removedDocsGroup.indexOf(removedDoc), 1); + if (removedDocsGroup.length === 0) { + this.groupMappings.delete(removedDocPresentId); + } + } + } + let castedList = Cast(this.presButtonBackUp.selectedButtonDocs, listSpec(Doc)); + if (castedList) { + castedList.splice(index, 1); + } + let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); + if (castedGroupDocs) { + castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { + let castedKey = StrCast(groupDoc.presentIdStore, null); + if (castedKey === removedDocPresentId) { + let castedGrouping = await DocListCastAsync(groupDoc.grouping); + if (castedGrouping) { + castedGrouping.splice(castedGrouping.indexOf(removedDoc), 1); + if (castedGrouping.length === 0) { + castedGroupDocs!.splice(castedGroupDocs!.indexOf(groupDoc), 1); + } + } + } + + }); + + } + + } } @action @@ -532,7 +567,7 @@ export class PresentationView extends React.Component { this.curPresentation.data = new List([doc]); } - this.curPresentation.width = 300; + this.curPresentation.width = 400; } @action @@ -630,17 +665,6 @@ export class PresentationView extends React.Component { this.currentSelectedPresValue = newGuid; this.setPresentationBackUps(); - - - // if (this.selectedPresentation) { - // this.selectedPresentation.selectedIndex = 1; - // console.log("Selected Pres: ", this.selectedPresentation); - // console.log("New value: ", this.selectedPresentation.value); - // console.log("New Index: ", this.selectedPresentation.selectedIndex); - - - // } - } @action @@ -664,7 +688,7 @@ export class PresentationView extends React.Component { {presentationList.map((doc: Doc, index: number) => { let mappedGuid = this.presentationsKeyMapping.get(doc); let docGuid: string = mappedGuid ? mappedGuid.toString() : ""; - return ; + return ; })} ; } @@ -683,10 +707,24 @@ export class PresentationView extends React.Component { } } + @action + removePresentation = () => { + if (this.presentationsMapping.size !== 1) { + let presentationList = Cast(this.props.Documents, listSpec(Doc)); + let removedDoc = this.presentationsMapping.get(this.currentSelectedPresValue!); + this.presentationsKeyMapping.delete(removedDoc!); + this.presentationsMapping.delete(this.currentSelectedPresValue!); + let remainingPresentations = this.presentationsMapping.values(); + let nextDoc = remainingPresentations.next().value; + this.currentSelectedPresValue = this.presentationsKeyMapping.get(nextDoc)!.toString(); + presentationList!.splice(presentationList!.indexOf(removedDoc!), 1); + } + } + render() { - let width = NumCast(this.curPresentation.width); + let width = NumCast(this.curPresentation.width); //TODO: next and back should be icons @@ -698,6 +736,7 @@ export class PresentationView extends React.Component { +
-- cgit v1.2.3-70-g09d2 From c5e401cb0a7fec2279ceecbc8d1429dcdd2f04b9 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 19 Jun 2019 22:27:21 -0400 Subject: buttons on cut links functional except for when dragged from link menu --- src/client/documents/Documents.ts | 47 +++++++-- src/client/util/DragManager.ts | 7 ++ src/client/util/LinkManager.ts | 15 ++- .../CollectionFreeFormLinkView.scss | 59 ++++++++--- .../CollectionFreeFormLinkView.tsx | 2 +- .../CollectionFreeFormLinkWithProxyView.tsx | 109 +++++++++++++++++---- .../CollectionFreeFormLinksView.tsx | 42 +++++--- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 14 ++- src/client/views/nodes/FieldView.tsx | 6 ++ src/client/views/nodes/LinkBox.scss | 76 -------------- src/client/views/nodes/LinkBox.tsx | 107 -------------------- src/client/views/nodes/LinkButtonBox.scss | 18 ++++ src/client/views/nodes/LinkButtonBox.tsx | 63 ++++++++++++ src/client/views/nodes/LinkMenu.tsx | 4 +- src/client/views/nodes/LinkMenuItem.scss | 76 ++++++++++++++ src/client/views/nodes/LinkMenuItem.tsx | 107 ++++++++++++++++++++ src/new_fields/LinkButtonField.ts | 35 +++++++ 18 files changed, 548 insertions(+), 242 deletions(-) delete mode 100644 src/client/views/nodes/LinkBox.scss delete mode 100644 src/client/views/nodes/LinkBox.tsx create mode 100644 src/client/views/nodes/LinkButtonBox.scss create mode 100644 src/client/views/nodes/LinkButtonBox.tsx create mode 100644 src/client/views/nodes/LinkMenuItem.scss create mode 100644 src/client/views/nodes/LinkMenuItem.tsx create mode 100644 src/new_fields/LinkButtonField.ts (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 79ba433c8..4d4fa2645 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -26,7 +26,7 @@ import { OmitKeys } from "../../Utils"; import { ImageField, VideoField, AudioField, PdfField, WebField } from "../../new_fields/URLField"; import { HtmlField } from "../../new_fields/HtmlField"; import { List } from "../../new_fields/List"; -import { Cast, NumCast } from "../../new_fields/Types"; +import { Cast, NumCast, StrCast } from "../../new_fields/Types"; import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; @@ -36,6 +36,10 @@ 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 { DocumentManager } from "../util/DocumentManager"; +import { Id } from "../../new_fields/FieldSymbols"; var requestImageSize = require('request-image-size'); var path = require('path'); @@ -102,14 +106,32 @@ export namespace DocUtils { linkDocProto.context = targetContext; - let proxy1 = Docs.TextDocument({ width: 300, height: 100, borderRounding: 0 }); - let proxy1Proto = Doc.GetProto(proxy1); - let proxy2 = Docs.TextDocument({ width: 300, height: 100, borderRounding: 0 }); - let proxy2Proto = Doc.GetProto(proxy2); + let sourceViews = DocumentManager.Instance.getDocumentViews(source); + let targetViews = DocumentManager.Instance.getDocumentViews(target); + sourceViews.forEach(sv => { + targetViews.forEach(tv => { - linkDocProto.proxy1 = proxy1; // src: 1 targ: 2 - linkDocProto.proxy2 = proxy2; // src: 2 targ: 1 + // 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); @@ -131,6 +153,7 @@ export namespace Docs { let audioProto: Doc; let pdfProto: Doc; let iconProto: Doc; + let linkProto: Doc; const textProtoId = "textProto"; const histoProtoId = "histoProto"; const pdfProtoId = "pdfProto"; @@ -141,6 +164,7 @@ export namespace Docs { const videoProtoId = "videoProto"; const audioProtoId = "audioProto"; const iconProtoId = "iconProto"; + const linkProtoId = "linkProto"; export function initProtos(): Promise { return DocServer.GetRefFields([textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId]).then(fields => { @@ -154,6 +178,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(); }); } @@ -186,6 +211,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 CreateTextPrototype(): Doc { let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), { x: 0, y: 0, width: 300, backgroundColor: "#f1efeb" }); @@ -272,6 +302,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 PdfDocument(url: string, options: DocumentOptions = {}) { return CreateInstance(pdfProto, new PdfField(new URL(url)), options); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 4787ac40f..be00778e7 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -7,6 +7,8 @@ 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 { DocumentManager } from "./DocumentManager"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { @@ -223,6 +225,11 @@ 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 let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 23ba9d2e4..544f2edda 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -1,4 +1,4 @@ -import { observable } from "mobx"; +import { observable, action } from "mobx"; import { StrCast, Cast } from "../../new_fields/Types"; import { Doc, DocListCast } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; @@ -32,6 +32,7 @@ export class LinkManager { @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 // finds all links that contain the given anchor public findAllRelatedLinks(anchor: Doc): Array { @@ -134,4 +135,16 @@ export class LinkManager { } } + @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; + } + } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index fc5212edd..d8d518147 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -1,19 +1,50 @@ -.collectionfreeformlinkview-linkLine { - stroke: black; +// .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); - opacity: 0.5; pointer-events: all; + + &.linkview-line { + stroke: black; + stroke-width: 2px; + opacity: 0.5; + } } -.collectionfreeformlinkview-linkCircle { - stroke: rgb(0,0,0); - opacity: 0.5; - transform: translate(10000px,10000px); - pointer-events: all; + +.linkview-button { + width: 200px; + height: 100px; + border-radius: 5px; + padding: 10px; + position: relative; + background-color: black; cursor: pointer; -} -.collectionfreeformlinkview-linkText { - stroke: rgb(0,0,0); - opacity: 0.5; - transform: translate(10000px,10000px); - pointer-events: all; + + p { + width: calc(100% - 20px); + color: white; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index f995a35e3..13b5dc575 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -57,7 +57,7 @@ export class CollectionFreeFormLinkView extends React.Component - diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx index 81a00ba95..a4d122af2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx @@ -7,13 +7,17 @@ import React = require("react"); import v5 = require("uuid/v5"); import { DocumentView } from "../../nodes/DocumentView"; import { Docs } from "../../../documents/Documents"; -import { observable } from "mobx"; +import { observable, action } from "mobx"; +import { CollectionDockingView } from "../CollectionDockingView"; +import { dropActionType, DragManager } from "../../../util/DragManager"; +import { emptyFunction } from "../../../../Utils"; +import { DocumentManager } from "../../../util/DocumentManager"; export interface CollectionFreeFormLinkViewProps { sourceView: DocumentView; targetView: DocumentView; proxyDoc: Doc; - addDocTab: (document: Doc, where: string) => void; + // addDocTab: (document: Doc, where: string) => void; } @observer @@ -21,37 +25,104 @@ export class CollectionFreeFormLinkWithProxyView extends React.Component(); + private _downX: number = 0; + private _downY: number = 0; + @observable _x: number = 0; + @observable _y: number = 0; + // @observable private _proxyDoc: Doc = Docs.TextDocument(); // used for positioning + + @action + componentDidMount() { + let a2 = this.props.proxyDoc; + this._x = NumCast(a2.x) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2); + this._y = NumCast(a2.y) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.height) / NumCast(a2.zoomBasis, 1) / 2); + } + followButton = (e: React.PointerEvent): void => { - // TODO: would be nicer to open docview in context e.stopPropagation(); - console.log("follow"); - this.props.addDocTab(this.props.targetView.props.Document, "onRight"); + let open = this.props.targetView.props.ContainingCollectionView ? this.props.targetView.props.ContainingCollectionView.props.Document : this.props.targetView.props.Document; + CollectionDockingView.Instance.AddRightSplit(open); + DocumentManager.Instance.jumpToDocument(this.props.targetView.props.Document, e.altKey); + } + + @action + setPosition(x: number, y: number) { + this._x = x; + this._y = y; + } + + startDragging(x: number, y: number) { + if (this._ref.current) { + let dragData = new DragManager.DocumentDragData([this.props.proxyDoc]); + + DragManager.StartLinkProxyDrag(this._ref.current, dragData, x, y, { + handlers: { + dragComplete: action(() => { + let a2 = this.props.proxyDoc; + let offset = NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2; + let x = NumCast(a2.x);// + NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2; + let y = NumCast(a2.y);// + NumCast(a2.height) / NumCast(a2.zoomBasis, 1) / 2; + this.setPosition(x, y); + + // this is a hack :'( theres prob a better way to make the input doc not render + let views = DocumentManager.Instance.getDocumentViews(this.props.proxyDoc); + views.forEach(dv => { + dv.props.removeDocument && dv.props.removeDocument(dv.props.Document); + }); + }), + }, + hideSource: true //? + }); + } + } + + onPointerDown = (e: React.PointerEvent): void => { + this._downX = e.clientX; + this._downY = e.clientY; + + e.stopPropagation(); + document.removeEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); + } + + onPointerMove = (e: PointerEvent): void => { + if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + this.startDragging(this._downX, this._downY); + } + e.stopPropagation(); + e.preventDefault(); + } + onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); } render() { let a1 = this.props.sourceView; - let a2 = this.props.proxyDoc; 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.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 containing = ""; - // if (this.props.targetView.props.ContainingCollectionView) { - // containing = StrCast(this.props.targetView.props.ContainingCollectionView.props.Document.title); - // } + let context = this.props.targetView.props.ContainingCollectionView ? + (" in the context of " + StrCast(this.props.targetView.props.ContainingCollectionView.props.Document.title)) : ""; + let text = "link to " + StrCast(this.props.targetView.props.Document.title) + context; - // let text = "link to " + StrCast(this.props.targetView.props.Document.title) + (containing === "" ? "" : (" in the context of " + containing)); return ( <> - - {/* - {text} */} + x2={`${this._x}`} y2={`${this._y}`} /> + +
+

{text}

+
+
); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index eaef1f32a..bde68001b 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 } from "mobx"; +import { computed, IReactionDisposer, reaction, action } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; @@ -13,6 +13,8 @@ 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 { @@ -195,18 +197,32 @@ export class CollectionFreeFormLinksView extends React.Component); } else { - 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); - - let context = u.targetView.props.ContainingCollectionView ? (" in the context of " + StrCast(u.targetView.props.ContainingCollectionView.props.Document.title)) : ""; - let text = proxyKey + " link to " + StrCast(u.targetView.props.Document.title) + context; - - let proxyProto = Doc.GetProto(proxy); - proxyProto.data = text; - - this.props.addDocument(proxy, false); - uniqueList.push(); + 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(); } } }); diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 02396c3af..940b00a90 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -12,6 +12,7 @@ import "./DocumentView.scss"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; import { IconBox } from "./IconBox"; +import { LinkButtonBox } from "./LinkButtonBox"; import { KeyValueBox } from "./KeyValueBox"; import { PDFBox } from "./PDFBox"; import { VideoBox } from "./VideoBox"; @@ -103,7 +104,7 @@ export class DocumentContentsView extends React.Component(Docu var scaling = this.props.ContentScaling(); var nativeHeight = this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; + + // // for linkbutton docs + // let isLinkButton = BoolCast(this.props.Document.isLinkButton); + // let activeDvs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)); + // let display = isLinkButton ? activeDvs.reduce((found, dv) => { + // let matchSv = this.props.Document.sourceViewId === StrCast(dv.props.Document[Id]); + // let matchTv = this.props.Document.targetViewId === StrCast(dv.props.Document[Id]); + // let match = matchSv || matchTv; + // return match || found; + // }, false) : true; + return (
(Docu background: this.Document.backgroundColor || "", width: nativeWidth, height: nativeHeight, - transform: `scale(${scaling}, ${scaling})` + transform: `scale(${scaling}, ${scaling})`, + // display: display ? "block" : "none" }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5a83de8e3..6fecb34d7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -18,6 +18,8 @@ import { FormattedTextBox } from "./FormattedTextBox"; import { IconBox } from "./IconBox"; import { ImageBox } from "./ImageBox"; import { VideoBox } from "./VideoBox"; +import { LinkButtonBox } from "./LinkButtonBox"; +import { LinkButtonField } from "../../../new_fields/LinkButtonField"; // @@ -49,6 +51,7 @@ export interface FieldViewProps { @observer export class FieldView extends React.Component { public static LayoutString(fieldType: { name: string }, fieldStr: string = "data") { + console.log("LAYOUT STRING", fieldType.name, fieldStr); return `<${fieldType.name} {...props} fieldKey={"${fieldStr}"} />`; } @@ -74,6 +77,9 @@ export class FieldView extends React.Component { else if (field instanceof IconField) { return ; } + else if (field instanceof LinkButtonField) { + return ; + } else if (field instanceof VideoField) { return ; } diff --git a/src/client/views/nodes/LinkBox.scss b/src/client/views/nodes/LinkBox.scss deleted file mode 100644 index 77462f611..000000000 --- a/src/client/views/nodes/LinkBox.scss +++ /dev/null @@ -1,76 +0,0 @@ -@import "../globalCssVariables"; -.linkMenu-item { - border-top: 0.5px solid $main-accent; - padding: 6px; - position: relative; - display: flex; - font-size: 12px; - - .linkMenu-item-content { - width: 100%; - } - - .link-metadata { - margin-top: 6px; - padding: 3px; - border-top: 0.5px solid $light-color-secondary; - .link-metadata-row { - margin-left: 6px; - } - } - - &:last-child { - border-bottom: 0.5px solid $main-accent; - } - &:hover { - .linkMenu-item-buttons { - display: flex; - } - .linkMenu-item-content { - &.expand-two { - width: calc(100% - 46px); - } - &.expand-three { - width: calc(100% - 78px); - } - } - } -} - -.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/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx deleted file mode 100644 index 8d07547ed..000000000 --- a/src/client/views/nodes/LinkBox.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { observer } from "mobx-react"; -import { DocumentManager } from "../../util/DocumentManager"; -import { undoBatch } from "../../util/UndoManager"; -import './LinkBox.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'; -library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); - - -interface Props { - groupType: string; - linkDoc: Doc; - sourceDoc: Doc; - destinationDoc: Doc; - showEditor: () => void; -} - -@observer -export class LinkBox extends React.Component { - private _drag = React.createRef(); - @observable private _showMore: boolean = false; - @action toggleShowMore() { this._showMore = !this._showMore; } - - @undoBatch - onFollowLink = async (e: React.PointerEvent): Promise => { - e.stopPropagation(); - DocumentManager.Instance.jumpToDocument(this.props.destinationDoc, e.altKey); - } - - onEdit = (e: React.PointerEvent): void => { - e.stopPropagation(); - this.props.showEditor(); - } - - renderMetadata = (): JSX.Element => { - let groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); - let index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase()); - let groupDoc = index > -1 ? groups[index] : undefined; - - 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 => { - return (
{key}: {StrCast(mdDoc[key])}
); - }); - } - - return (
{mdRows}
); - } - - 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); - - DragLinkAsDocument(this._drag.current, e.x, e.y, this.props.linkDoc, this.props.sourceDoc); - } - e.stopPropagation(); - } - - render() { - - let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType); - let canExpand = keys ? keys.length > 0 : false; - - return ( -
-
-
-

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

-
- {canExpand ?
this.toggleShowMore()}> -
: <>} -
-
-
-
- {this._showMore ? this.renderMetadata() : <>} -
- -
- ); - } -} \ No newline at end of file diff --git a/src/client/views/nodes/LinkButtonBox.scss b/src/client/views/nodes/LinkButtonBox.scss new file mode 100644 index 000000000..24bfd2c9f --- /dev/null +++ b/src/client/views/nodes/LinkButtonBox.scss @@ -0,0 +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-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 new file mode 100644 index 000000000..8a7c1ed8b --- /dev/null +++ b/src/client/views/nodes/LinkButtonBox.tsx @@ -0,0 +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 diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index aef56df67..7e4c15312 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -1,7 +1,7 @@ import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { DocumentView } from "./DocumentView"; -import { LinkBox } from "./LinkBox"; +import { LinkMenuItem } from "./LinkMenuItem"; import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); @@ -23,7 +23,7 @@ export class LinkMenu extends React.Component { let source = this.props.docView.Document; return group.map(linkDoc => { let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, source); - return this._editingLink = linkDoc)} />; + return this._editingLink = linkDoc)} />; }); } diff --git a/src/client/views/nodes/LinkMenuItem.scss b/src/client/views/nodes/LinkMenuItem.scss new file mode 100644 index 000000000..77462f611 --- /dev/null +++ b/src/client/views/nodes/LinkMenuItem.scss @@ -0,0 +1,76 @@ +@import "../globalCssVariables"; +.linkMenu-item { + border-top: 0.5px solid $main-accent; + padding: 6px; + position: relative; + display: flex; + font-size: 12px; + + .linkMenu-item-content { + width: 100%; + } + + .link-metadata { + margin-top: 6px; + padding: 3px; + border-top: 0.5px solid $light-color-secondary; + .link-metadata-row { + margin-left: 6px; + } + } + + &:last-child { + border-bottom: 0.5px solid $main-accent; + } + &:hover { + .linkMenu-item-buttons { + display: flex; + } + .linkMenu-item-content { + &.expand-two { + width: calc(100% - 46px); + } + &.expand-three { + width: calc(100% - 78px); + } + } + } +} + +.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 new file mode 100644 index 000000000..c68365584 --- /dev/null +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -0,0 +1,107 @@ +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; +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 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'; +library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); + + +interface LinkMenuItemProps { + groupType: string; + linkDoc: Doc; + sourceDoc: Doc; + destinationDoc: Doc; + showEditor: () => void; +} + +@observer +export class LinkMenuItem extends React.Component { + private _drag = React.createRef(); + @observable private _showMore: boolean = false; + @action toggleShowMore() { this._showMore = !this._showMore; } + + @undoBatch + onFollowLink = async (e: React.PointerEvent): Promise => { + e.stopPropagation(); + DocumentManager.Instance.jumpToDocument(this.props.destinationDoc, e.altKey); + } + + onEdit = (e: React.PointerEvent): void => { + e.stopPropagation(); + this.props.showEditor(); + } + + renderMetadata = (): JSX.Element => { + let groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); + let index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase()); + let groupDoc = index > -1 ? groups[index] : undefined; + + 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 => { + return (
{key}: {StrCast(mdDoc[key])}
); + }); + } + + return (
{mdRows}
); + } + + 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); + + DragLinkAsDocument(this._drag.current, e.x, e.y, this.props.linkDoc, this.props.sourceDoc); + } + e.stopPropagation(); + } + + render() { + + let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType); + let canExpand = keys ? keys.length > 0 : false; + + return ( +
+
+
+

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

+
+ {canExpand ?
this.toggleShowMore()}> +
: <>} +
+
+
+
+ {this._showMore ? this.renderMetadata() : <>} +
+ +
+ ); + } +} \ No newline at end of file diff --git a/src/new_fields/LinkButtonField.ts b/src/new_fields/LinkButtonField.ts new file mode 100644 index 000000000..92e1ed922 --- /dev/null +++ b/src/new_fields/LinkButtonField.ts @@ -0,0 +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"; + +export type LinkButtonData = { + sourceViewId: string, + targetViewId: string +}; + +const LinkButtonSchema = createSimpleSchema({ + sourceViewId: true, + targetViewId: true +}); + +@Deserializable("linkButton") +export class LinkButtonField extends ObjectField { + @serializable(object(LinkButtonSchema)) + readonly data: LinkButtonData; + + constructor(data: LinkButtonData) { + super(); + this.data = data; + } + + [Copy]() { + return new LinkButtonField(this.data); + } + + [ToScriptString]() { + return "invalid"; + } +} -- cgit v1.2.3-70-g09d2 From 73f03785f938542a91b28b35043f2feda2bc1432 Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 20 Jun 2019 11:26:33 -0400 Subject: merge --- .../collections/collectionFreeForm/CollectionFreeFormLinksView.tsx | 4 ++++ src/client/views/nodes/DocumentView.tsx | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index bde68001b..3c2ccecfc 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -167,12 +167,16 @@ export class CollectionFreeFormLinksView extends React.Component = 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) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c424384a4..1d74b47a1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -447,6 +447,11 @@ 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); } @@ -491,7 +496,7 @@ 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} -- cgit v1.2.3-70-g09d2 From a0246ef84396545f79fc4a8b21de1a56cbf06aca Mon Sep 17 00:00:00 2001 From: Fawn Date: Thu, 20 Jun 2019 11:34:28 -0400 Subject: merge --- .../collections/collectionFreeForm/CollectionFreeFormLinksView.tsx | 6 ------ src/client/views/nodes/DocumentView.tsx | 6 ------ 2 files changed, 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index 211c90c29..3c2ccecfc 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -214,7 +214,6 @@ export class CollectionFreeFormLinksView extends React.Component); // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id])); @@ -228,11 +227,6 @@ export class CollectionFreeFormLinksView extends React.Component); -======= - return match || found; - }, false)) { - drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] }); ->>>>>>> e9d62f4ca0dbeb57e46239047041a8a04da7b504 } } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1d87205ab..dbbae2d59 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -31,12 +31,9 @@ import "./DocumentView.scss"; import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { ContextMenuProps } from '../ContextMenuItem'; -<<<<<<< HEAD import { list, object, createSimpleSchema } from 'serializr'; import { LinkManager } from '../../util/LinkManager'; -======= import { RouteStore } from '../../../server/RouteStore'; ->>>>>>> e9d62f4ca0dbeb57e46239047041a8a04da7b504 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(fa.faTrash); @@ -556,7 +553,6 @@ export class DocumentView extends DocComponent(Docu render() { var scaling = this.props.ContentScaling(); var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; -<<<<<<< HEAD // // for linkbutton docs // let isLinkButton = BoolCast(this.props.Document.isLinkButton); @@ -568,9 +564,7 @@ export class DocumentView extends DocComponent(Docu // return match || found; // }, false) : true; -======= var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; ->>>>>>> e9d62f4ca0dbeb57e46239047041a8a04da7b504 return (
Date: Thu, 20 Jun 2019 12:54:41 -0400 Subject: Documentation and reset Presentation at removal fixed --- .../views/presentationview/PresentationElement.tsx | 3 +- .../views/presentationview/PresentationView.tsx | 123 +++++++++++++-------- 2 files changed, 79 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index a84bbbf3c..b12dfd9d5 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -12,7 +12,6 @@ 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"; @@ -72,11 +71,13 @@ export default class PresentationElement extends React.Component { //back-up so that presentation stays the way it's when refreshed @observable presGroupBackUp: Doc = new Doc(); @observable presButtonBackUp: Doc = new Doc(); + + //Keeping track of the doc for the current presentation @observable curPresentation: Doc = new Doc(); + //Mapping of guids to presentations. @observable presentationsMapping: Map = new Map(); + //Mapping of presentations to guid, so that select option values can be given. @observable presentationsKeyMapping: Map = new Map(); + //Variable to keep track of guid of the current presentation @observable currentSelectedPresValue: string | undefined; + //A flag to keep track if title input is open, which is used in rendering. @observable PresTitleInputOpen: boolean = false; + //Variable that holds reference to title input, so that new presentations get titles assigned. @observable titleInputElement: HTMLInputElement | undefined; - //@observable presTitle: string = "Presentation"; - //initilize class variables constructor(props: PresViewProps) { @@ -138,13 +143,17 @@ export class PresentationView extends React.Component { PresentationView.Instance = this; } - + //The first lifecycle function that gets called to set up the current presentation. async componentWillMount() { this.props.Documents.forEach(async (doc, index: number) => { + + //For each presentation received from mainContainer, a mapping is created. let curDoc: Doc = await doc; let newGuid = Utils.GenerateGuid(); this.presentationsKeyMapping.set(curDoc, newGuid); this.presentationsMapping.set(newGuid, curDoc); + + //The Presentation at first index gets set as default start presentation if (index === 0) { runInAction(() => this.currentSelectedPresValue = newGuid); runInAction(() => this.curPresentation = curDoc); @@ -152,8 +161,9 @@ export class PresentationView extends React.Component { }); } + //Second lifecycle function that gets called when component mounts. It makes sure to + //get the back-up information from previous session for the current presentation. async componentDidMount() { - let docAtZero = await this.props.Documents[0]; runInAction(() => this.curPresentation = docAtZero); @@ -162,6 +172,10 @@ export class PresentationView extends React.Component { } + /** + * The function that retrieves the backUps for the current Presentation if present, + * otherwise initializes. + */ setPresentationBackUps = async () => { //getting both backUp documents @@ -195,7 +209,6 @@ export class PresentationView extends React.Component { } //if instantiated before - if (castedButtonBackUp instanceof Promise) { castedButtonBackUp.then(doc => { let toAssign = doc ? doc : new Doc(); @@ -304,12 +317,14 @@ export class PresentationView extends React.Component { // 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); + if (current > 0) { + 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); + } } } } @@ -453,14 +468,22 @@ export class PresentationView extends React.Component { return doc; } + /** + * The function that removes a doc from a presentation. It also makes sure to + * do necessary updates to backUps and mappings stored locally. + */ @action public RemoveDoc = async (index: number) => { const value = FieldValue(Cast(this.curPresentation.data, listSpec(Doc))); if (value) { let removedDoc = await value.splice(index, 1)[0]; + + //removing the Presentation Element stored for it this.presElementsMappings.delete(removedDoc); let removedDocPresentId = StrCast(removedDoc.presentId); + + //Removing it from local mapping of the groups if (this.groupMappings.has(removedDocPresentId)) { let removedDocsGroup = this.groupMappings.get(removedDocPresentId); if (removedDocsGroup) { @@ -470,10 +493,14 @@ export class PresentationView extends React.Component { } } } + + //removing it from the backUp of selected Buttons let castedList = Cast(this.presButtonBackUp.selectedButtonDocs, listSpec(Doc)); if (castedList) { castedList.splice(index, 1); } + + //removing it from the backup of groups let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); if (castedGroupDocs) { castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { @@ -495,6 +522,9 @@ export class PresentationView extends React.Component { } } + + //The function that is called when a document is clicked or reached through next or back. + //it'll also execute the necessary actions if presentation is playing. @action public gotoDocument = async (index: number, fromDoc: number) => { const list = FieldValue(Cast(this.curPresentation.data, listSpec(Doc))); @@ -520,7 +550,8 @@ export class PresentationView extends React.Component { } - + //Function that is called to resetGroupIds, so that documents get new groupIds at + //first load, when presentation is changed. resetGroupIds = async () => { let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); if (castedGroupDocs !== undefined) { @@ -531,29 +562,10 @@ export class PresentationView extends React.Component { doc.presentId = Utils.GenerateGuid(); }); } - // let castedKey = StrCast(groupDoc.presentIdStore, null); - // if (castedGrouping !== undefined && castedKey !== undefined) { - // this.groupMappings.set(castedKey, castedGrouping); - // } }); } } - // reloadGroupIds = async () => { - // let castedGroupDocs = await DocListCastAsync(this.presGroupBackUp.groupDocs); - // if (castedGroupDocs !== undefined) { - // castedGroupDocs.forEach(async (groupDoc: Doc, index: number) => { - // let castedGrouping = await DocListCastAsync(groupDoc.grouping); - // let castedKey = StrCast(groupDoc.presentIdStore, null); - // if (castedGrouping !== undefined && castedKey !== undefined) { - // this.groupMappings.set(castedKey, castedGrouping); - // } - // }); - // } - // } - - - /** * Adds a document to the presentation view **/ @@ -570,11 +582,14 @@ export class PresentationView extends React.Component { this.curPresentation.width = 400; } + //Function that sets the store of the children docs. @action setChildrenDocs = (docList: Doc[]) => { this.childrenDocs = docList; } + //The function that is called to render the play or pause button depending on + //if presentation is running or not. renderPlayPauseButton = () => { if (this.presStatus) { return ; @@ -583,10 +598,10 @@ export class PresentationView extends React.Component { } } + //The function that starts or resets presentaton functionally, depending on status flag. @action startOrResetPres = () => { if (this.presStatus) { - //this.presStatus = false; this.resetPresentation(); } else { this.presStatus = true; @@ -597,19 +612,10 @@ export class PresentationView extends React.Component { this.curPresentation.presStatus = this.presStatus; } + //The function that resets the presentation by removing every action done by it. It also + //stops the presentaton. @action resetPresentation = () => { - //this.groupMappings = new Map(); - //let selectedButtons: boolean[]; - // this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { - // //selectedButtons = component.selected; - // //selectedButtons.forEach((val: boolean, index: number) => selectedButtons[index] = false); - // //doc.presentId = Utils.GenerateGuid(); - // doc.opacity = 1; - // doc.viewScale = 1; - // }); - - this.childrenDocs.forEach((doc: Doc) => { doc.opacity = 1; doc.viewScale = 1; @@ -621,11 +627,11 @@ export class PresentationView extends React.Component { return; } DocumentManager.Instance.zoomIntoScale(this.childrenDocs[0], 1); - - // this.childrenDocs[0].viewScale = 1; - } + + //The function that starts the presentation, also checking if actions should be applied + //directly at start. startPresentation = (startIndex: number) => { let selectedButtons: boolean[]; this.presElementsMappings.forEach((component: PresentationElement, doc: Doc) => { @@ -651,6 +657,11 @@ export class PresentationView extends React.Component { } + /** + * The function that is called to add a new presentation to the presentationView. + * It sets up te mappings and local copies of it. Resets the groupings and presentation. + * Makes the new presentation current selected, and retrieve the back-Ups if present. + */ @action addNewPresentation = (presTitle: string) => { //let title = "Presentation " + (this.props.Documents.length + 1); @@ -667,6 +678,11 @@ export class PresentationView extends React.Component { } + /** + * The function that is called to change the current selected presentation. + * Changes the presentation, also resetting groupings and presentation in process. + * Plus retrieving the backUps for the newly selected presentation. + */ @action getSelectedPresentation = (e: React.ChangeEvent) => { let selectedGuid = e.target.value; @@ -679,6 +695,9 @@ export class PresentationView extends React.Component { } + /** + * The function that is called to render either select for presentations, or title inputting. + */ renderSelectOrPresSelection = () => { let presentationList = DocListCast(this.props.Documents); if (this.PresTitleInputOpen) { @@ -694,6 +713,10 @@ export class PresentationView extends React.Component { } } + /** + * The function that is called on enter press of title input. It gives the + * new presentation the title user entered. If nothing is entered, gives a default title. + */ @action submitPresentationTitle = (e: React.KeyboardEvent) => { if (e.keyCode === 13) { @@ -707,6 +730,10 @@ export class PresentationView extends React.Component { } } + /** + * The function that is called to remove a presentation from all its copies, and the main Container's + * list. Sets up the next presentation as current. + */ @action removePresentation = () => { if (this.presentationsMapping.size !== 1) { @@ -716,7 +743,11 @@ export class PresentationView extends React.Component { this.presentationsMapping.delete(this.currentSelectedPresValue!); let remainingPresentations = this.presentationsMapping.values(); let nextDoc = remainingPresentations.next().value; + this.curPresentation = nextDoc; + this.resetGroupIds(); + this.resetPresentation(); this.currentSelectedPresValue = this.presentationsKeyMapping.get(nextDoc)!.toString(); + this.setPresentationBackUps(); presentationList!.splice(presentationList!.indexOf(removedDoc!), 1); } } -- 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') 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 e88538bb8af2ba648da2326d0f6edd3e0186766e Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Thu, 20 Jun 2019 15:45:07 -0400 Subject: Title changing to presentations added --- .../views/presentationview/PresentationView.tsx | 38 +++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 474001523..905117cd1 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -13,7 +13,7 @@ import { CurrentUserUtils } from "../../../server/authentication/models/current_ import PresentationElement, { buttonIndex } from "./PresentationElement"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faArrowRight, faArrowLeft, faPlay, faStop, faPlus, faTimes, faMinus } from '@fortawesome/free-solid-svg-icons'; +import { faArrowRight, faArrowLeft, faPlay, faStop, faPlus, faTimes, faMinus, faEdit } from '@fortawesome/free-solid-svg-icons'; import { Docs } from "../../documents/Documents"; library.add(faArrowLeft); @@ -23,6 +23,8 @@ library.add(faStop); library.add(faPlus); library.add(faTimes); library.add(faMinus); +library.add(faEdit); + export interface PresViewProps { Documents: List; @@ -136,6 +138,7 @@ export class PresentationView extends React.Component { @observable PresTitleInputOpen: boolean = false; //Variable that holds reference to title input, so that new presentations get titles assigned. @observable titleInputElement: HTMLInputElement | undefined; + @observable PresTitleChangeOpen: boolean = false; //initilize class variables constructor(props: PresViewProps) { @@ -664,7 +667,6 @@ export class PresentationView extends React.Component { */ @action addNewPresentation = (presTitle: string) => { - //let title = "Presentation " + (this.props.Documents.length + 1); let newPresentationDoc = Docs.TreeDocument([], { title: presTitle }); this.props.Documents.push(newPresentationDoc); this.curPresentation = newPresentationDoc; @@ -700,7 +702,7 @@ export class PresentationView extends React.Component { */ renderSelectOrPresSelection = () => { let presentationList = DocListCast(this.props.Documents); - if (this.PresTitleInputOpen) { + if (this.PresTitleInputOpen || this.PresTitleChangeOpen) { return this.titleInputElement = e!} type="text" className="presentationView-title" placeholder="Enter Name!" onKeyDown={this.submitPresentationTitle} />; } else { return 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 64ffa0accfc872c81035079527952aabaf56c6f6 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Tue, 25 Jun 2019 13:16:45 -0400 Subject: Small Css Fix On weight --- src/client/views/presentationview/PresentationView.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.scss b/src/client/views/presentationview/PresentationView.scss index 5f2b80474..a35a5849b 100644 --- a/src/client/views/presentationview/PresentationView.scss +++ b/src/client/views/presentationview/PresentationView.scss @@ -47,6 +47,7 @@ padding-bottom: 3px; font-size: 25px; display: inline-block; + width: calc(100% - 160px); } .presentation-icon { -- 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') 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 2a698e88da5ef0a9fee1ff4ee69746f1242798c9 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 25 Jun 2019 18:32:17 -0400 Subject: fixed render links in treeview --- src/client/views/collections/CollectionTreeView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f5c5219a7..ca77f7c45 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -270,7 +270,7 @@ class TreeView extends React.Component { renderLinks = () => { 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 addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before); let groups = LinkManager.Instance.getRelatedGroupedLinks(this.props.document); groups.forEach((groupLinkDocs, groupType) => { let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document)); -- cgit v1.2.3-70-g09d2 From 2d300b0cd3d02c900865c61eacd539efed5289e6 Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 25 Jun 2019 20:18:14 -0400 Subject: fixed link metadata rendering bug --- src/client/documents/Documents.ts | 11 +- src/client/util/LinkManager.ts | 2 +- .../CollectionFreeFormLinkView.scss | 31 ----- .../CollectionFreeFormLinkView.tsx | 1 - .../CollectionFreeFormLinkWithProxyView.tsx | 131 --------------------- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 11 -- src/client/views/nodes/LinkButtonBox.scss | 18 --- src/client/views/nodes/LinkButtonBox.tsx | 63 ---------- src/client/views/nodes/LinkEditor.tsx | 45 ++++--- src/new_fields/LinkButtonField.ts | 35 ------ 11 files changed, 35 insertions(+), 316 deletions(-) delete mode 100644 src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx delete mode 100644 src/client/views/nodes/LinkButtonBox.scss delete mode 100644 src/client/views/nodes/LinkButtonBox.tsx delete mode 100644 src/new_fields/LinkButtonField.ts (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d2300e4d2..547687921 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -88,7 +88,7 @@ export namespace DocUtils { // 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)) { - console.log("LINK EXISTS"); return; + return; } UndoManager.RunInBatch(() => { @@ -186,11 +186,6 @@ 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 CreateTextPrototype(): Doc { let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(), { x: 0, y: 0, width: 300, backgroundColor: "#f1efeb" }); @@ -277,9 +272,7 @@ 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 PdfDocument(url: string, options: DocumentOptions = {}) { return CreateInstance(pdfProto, new PdfField(new URL(url)), options); } diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 60de7fc52..db814082f 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -156,7 +156,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); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss index 239c2ce56..fc5212edd 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss @@ -17,34 +17,3 @@ transform: translate(10000px,10000px); pointer-events: all; } - -.linkview-ele { - transform: translate(10000px,10000px); - pointer-events: all; - - &.linkview-line { - stroke: black; - stroke-width: 2px; - opacity: 0.5; - } -} - -.linkview-button { - width: 200px; - height: 100px; - border-radius: 5px; - padding: 10px; - position: relative; - background-color: black; - cursor: pointer; - - p { - width: calc(100% - 20px); - color: white; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - -} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 5dc3b5c16..b546d1b78 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -9,7 +9,6 @@ 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; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx deleted file mode 100644 index a4d122af2..000000000 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkWithProxyView.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import { observer } from "mobx-react"; -import { Doc, HeightSym, WidthSym } from "../../../../new_fields/Doc"; -import { BoolCast, NumCast, StrCast } from "../../../../new_fields/Types"; -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"; -import { observable, action } from "mobx"; -import { CollectionDockingView } from "../CollectionDockingView"; -import { dropActionType, DragManager } from "../../../util/DragManager"; -import { emptyFunction } from "../../../../Utils"; -import { DocumentManager } from "../../../util/DocumentManager"; - -export interface CollectionFreeFormLinkViewProps { - sourceView: DocumentView; - targetView: DocumentView; - proxyDoc: Doc; - // addDocTab: (document: Doc, where: string) => void; -} - -@observer -export class CollectionFreeFormLinkWithProxyView extends React.Component { - - // @observable private _proxyX: number = NumCast(this.props.proxyDoc.x); - // @observable private _proxyY: number = NumCast(this.props.proxyDoc.y); - private _ref = React.createRef(); - private _downX: number = 0; - private _downY: number = 0; - @observable _x: number = 0; - @observable _y: number = 0; - // @observable private _proxyDoc: Doc = Docs.TextDocument(); // used for positioning - - @action - componentDidMount() { - let a2 = this.props.proxyDoc; - this._x = NumCast(a2.x) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2); - this._y = NumCast(a2.y) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.height) / NumCast(a2.zoomBasis, 1) / 2); - } - - - followButton = (e: React.PointerEvent): void => { - e.stopPropagation(); - let open = this.props.targetView.props.ContainingCollectionView ? this.props.targetView.props.ContainingCollectionView.props.Document : this.props.targetView.props.Document; - CollectionDockingView.Instance.AddRightSplit(open); - DocumentManager.Instance.jumpToDocument(this.props.targetView.props.Document, e.altKey); - } - - @action - setPosition(x: number, y: number) { - this._x = x; - this._y = y; - } - - startDragging(x: number, y: number) { - if (this._ref.current) { - let dragData = new DragManager.DocumentDragData([this.props.proxyDoc]); - - DragManager.StartLinkProxyDrag(this._ref.current, dragData, x, y, { - handlers: { - dragComplete: action(() => { - let a2 = this.props.proxyDoc; - let offset = NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2; - let x = NumCast(a2.x);// + NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2; - let y = NumCast(a2.y);// + NumCast(a2.height) / NumCast(a2.zoomBasis, 1) / 2; - this.setPosition(x, y); - - // this is a hack :'( theres prob a better way to make the input doc not render - let views = DocumentManager.Instance.getDocumentViews(this.props.proxyDoc); - views.forEach(dv => { - dv.props.removeDocument && dv.props.removeDocument(dv.props.Document); - }); - }), - }, - hideSource: true //? - }); - } - } - - onPointerDown = (e: React.PointerEvent): void => { - this._downX = e.clientX; - this._downY = e.clientY; - - e.stopPropagation(); - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - - onPointerMove = (e: PointerEvent): void => { - if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - this.startDragging(this._downX, this._downY); - } - e.stopPropagation(); - e.preventDefault(); - } - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - - render() { - let a1 = this.props.sourceView; - 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 context = this.props.targetView.props.ContainingCollectionView ? - (" in the context of " + StrCast(this.props.targetView.props.ContainingCollectionView.props.Document.title)) : ""; - let text = "link to " + StrCast(this.props.targetView.props.Document.title) + context; - - return ( - <> - - -
-

{text}

-
-
- - ); - } -} - -//onPointerDown={this.followButton} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 940b00a90..02396c3af 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -12,7 +12,6 @@ import "./DocumentView.scss"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; import { IconBox } from "./IconBox"; -import { LinkButtonBox } from "./LinkButtonBox"; import { KeyValueBox } from "./KeyValueBox"; import { PDFBox } from "./PDFBox"; import { VideoBox } from "./VideoBox"; @@ -104,7 +103,7 @@ export class DocumentContentsView extends React.Component(Docu var scaling = this.props.ContentScaling(); var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; - // // for linkbutton docs - // let isLinkButton = BoolCast(this.props.Document.isLinkButton); - // let activeDvs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)); - // let display = isLinkButton ? activeDvs.reduce((found, dv) => { - // let matchSv = this.props.Document.sourceViewId === StrCast(dv.props.Document[Id]); - // let matchTv = this.props.Document.targetViewId === StrCast(dv.props.Document[Id]); - // let match = matchSv || matchTv; - // return match || found; - // }, false) : true; - var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; return (
(Docu width: nativeWidth, height: nativeHeight, transform: `scale(${scaling}, ${scaling})`, - // display: display ? "block" : "none" }} onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} diff --git a/src/client/views/nodes/LinkButtonBox.scss b/src/client/views/nodes/LinkButtonBox.scss deleted file mode 100644 index 6be2dcf60..000000000 --- a/src/client/views/nodes/LinkButtonBox.scss +++ /dev/null @@ -1,18 +0,0 @@ -// .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 diff --git a/src/client/views/nodes/LinkButtonBox.tsx b/src/client/views/nodes/LinkButtonBox.tsx deleted file mode 100644 index 440847ead..000000000 --- a/src/client/views/nodes/LinkButtonBox.tsx +++ /dev/null @@ -1,63 +0,0 @@ -// 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 a6511c3fe..eed34b21f 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -71,10 +71,12 @@ class GroupTypesDropdown extends React.Component { interface LinkMetadataEditorProps { + id: string; groupType: string; mdDoc: Doc; mdKey: string; mdValue: string; + changeMdIdKey: (id: string, newKey: string) => void; } @observer class LinkMetadataEditor extends React.Component { @@ -86,8 +88,6 @@ class LinkMetadataEditor extends React.Component { setMetadataKey = (value: string): void => { let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType); - // console.log("set", ...groupMdKeys, typeof (groupMdKeys[0])); - // don't allow user to create existing key let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase()); if (newIndex > -1) { @@ -105,6 +105,7 @@ class LinkMetadataEditor extends React.Component { if (currIndex === -1) console.error("LinkMetadataEditor: key was not found"); groupMdKeys[currIndex] = value; + this.props.changeMdIdKey(this.props.id, value); this._key = value; LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, [...groupMdKeys]); } @@ -133,7 +134,7 @@ class LinkMetadataEditor extends React.Component { return (
this.setMetadataKey(e.target.value)}>: - this.setMetadataValue(e.target.value)}> + this.setMetadataValue(e.target.value)}>
); @@ -148,6 +149,17 @@ interface LinkGroupEditorProps { @observer export class LinkGroupEditor extends React.Component { + private _metadataIds: Map = new Map(); + + constructor(props: LinkGroupEditorProps) { + super(props); + + let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.type)); + groupMdKeys.forEach(key => { + this._metadataIds.set(key, Utils.GenerateGuid()); + }); + } + @action setGroupType = (groupType: string): void => { this.props.groupDoc.type = groupType; @@ -188,12 +200,18 @@ export class LinkGroupEditor extends React.Component { @action addMetadata = (groupType: string): void => { + this._metadataIds.set("new key", Utils.GenerateGuid()); 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); } + // for key rendering purposes + changeMdIdKey = (id: string, newKey: string) => { + this._metadataIds.set(newKey, id); + } + renderMetadata = (): JSX.Element[] => { let metadata: Array = []; let groupDoc = this.props.groupDoc; @@ -201,25 +219,24 @@ export class LinkGroupEditor extends React.Component { let groupType = StrCast(groupDoc.type); let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType); - if (groupMdKeys) { - groupMdKeys.forEach((key, index) => { - metadata.push( - - ); - }); - } + groupMdKeys.forEach((key) => { + let val = StrCast(mdDoc[key]); + metadata.push( + + ); + }); return metadata; } viewGroupAsTable = (groupType: string): JSX.Element => { let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + let index = keys.indexOf(""); + if (index > -1) keys.splice(index, 1); let cols = ["anchor1", "anchor2", ...[...keys]]; - // keys.forEach(k => cols.push(k)); - // console.log("COLS", ...cols); let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); let createTable = action(() => Docs.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); let ref = React.createRef(); - return
; + return
; } render() { @@ -233,7 +250,7 @@ export class LinkGroupEditor extends React.Component { - + ); } else { diff --git a/src/new_fields/LinkButtonField.ts b/src/new_fields/LinkButtonField.ts deleted file mode 100644 index e6d1de749..000000000 --- a/src/new_fields/LinkButtonField.ts +++ /dev/null @@ -1,35 +0,0 @@ -// 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 -// }; - -// const LinkButtonSchema = createSimpleSchema({ -// sourceViewId: true, -// targetViewId: true -// }); - -// @Deserializable("linkButton") -// export class LinkButtonField extends ObjectField { -// @serializable(object(LinkButtonSchema)) -// readonly data: LinkButtonData; - -// constructor(data: LinkButtonData) { -// super(); -// this.data = data; -// } - -// [Copy]() { -// return new LinkButtonField(this.data); -// } - -// [ToScriptString]() { -// return "invalid"; -// } -// } -- cgit v1.2.3-70-g09d2 From ca8a78de9957ad27d345ad51fdaee9dae3f096bd Mon Sep 17 00:00:00 2001 From: Fawn Date: Tue, 25 Jun 2019 20:44:34 -0400 Subject: can't link to containing collection --- src/client/documents/Documents.ts | 7 ++++--- src/client/util/DragManager.ts | 16 ++-------------- src/client/views/nodes/LinkEditor.tsx | 5 +++-- src/new_fields/Doc.ts | 3 --- 4 files changed, 9 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 547687921..b11b5fdf2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -35,6 +35,7 @@ import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; import { LinkManager } from "../util/LinkManager"; +import { DocumentManager } from "../util/DocumentManager"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -87,9 +88,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, title: string = "", description: string = "", tags: string = "Default") { - if (LinkManager.Instance.doesLinkExist(source, target)) { - return; - } + if (LinkManager.Instance.doesLinkExist(source, target)) return; + let sv = DocumentManager.Instance.getDocumentView(source); + if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return; UndoManager.RunInBatch(() => { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 4be3d82d3..55d8c570f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -63,8 +63,6 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; - // TODO: if not in same context then don't drag - if (srcTarg) { let linkDocs = LinkManager.Instance.getAllRelatedLinks(srcTarg); if (linkDocs) { @@ -232,25 +230,20 @@ export namespace DragManager { (dropData: { [id: string]: any }) => { dropData.droppedDocuments = dragData.draggedDocuments.map(d => { let dv = DocumentManager.Instance.getDocumentView(d); - // console.log("DRAG", StrCast(d.title)); if (dv) { if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) { return d; } else { - // return d; let r = Doc.MakeAlias(d); - // DocUtils.MakeLink(sourceDoc, r); + // DocUtils.MakeLink(r, sourceDoc); return r; } } else { - // return d; let r = Doc.MakeAlias(d); - // DocUtils.MakeLink(sourceDoc, r); + // DocUtils.MakeLink(r, sourceDoc); return r; } - // return (dv && dv.props.ContainingCollectionView !== SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) || !dv ? - // Doc.MakeAlias(d) : d; }); }); @@ -290,11 +283,6 @@ 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 let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index eed34b21f..232331204 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -133,8 +133,8 @@ class LinkMetadataEditor extends React.Component { render() { return (
- this.setMetadataKey(e.target.value)}>: - this.setMetadataValue(e.target.value)}> + this.setMetadataKey(e.target.value)}>: + this.setMetadataValue(e.target.value)}>
); @@ -221,6 +221,7 @@ export class LinkGroupEditor extends React.Component { groupMdKeys.forEach((key) => { let val = StrCast(mdDoc[key]); + console.log(key, val); metadata.push( ); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index f6fd44d61..d7411e63e 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -260,13 +260,10 @@ export namespace Doc { } } else { if (field instanceof RefField) { - console.log("equals field, ref", key); copy[key] = field; } else if (field instanceof ObjectField) { - console.log("copy field, object", key); copy[key] = ObjectField.MakeCopy(field); } else { - console.log("equals field", key); copy[key] = field; } } -- 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') 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 d0ff42632f8a155303e11945a1a974a15052f0db Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 26 Jun 2019 11:40:36 -0400 Subject: link menu styling --- src/client/util/LinkManager.ts | 44 +--------------------- .../CollectionFreeFormLinksView.tsx | 21 +---------- src/client/views/nodes/DocumentView.tsx | 2 - src/client/views/nodes/LinkEditor.tsx | 1 - src/client/views/nodes/LinkMenu.scss | 25 +++++++++--- src/client/views/nodes/LinkMenuGroup.tsx | 21 ++++++++++- src/client/views/nodes/LinkMenuItem.scss | 2 + 7 files changed, 44 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index db814082f..97c816001 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -24,10 +24,6 @@ import { CurrentUserUtils } from "../../server/authentication/models/current_use * - user defined kvps */ export class LinkManager { - // static Instance: LinkManager; - // private constructor() { - // LinkManager.Instance = this; - // } private static _instance: LinkManager; public static get Instance(): LinkManager { @@ -36,12 +32,11 @@ export class LinkManager { private constructor() { } + // the linkmanagerdoc stores a list of docs representing all linkdocs in 'allLinks' and a list of strings representing all group types in 'allGroupTypes' + // lists of strings representing the metadata keys for each group type is stored under a key that is the same as the group type 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) : [] : []; @@ -160,14 +155,6 @@ export class LinkManager { 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 getRelatedGroupedLinks(anchor: Doc): Map> { let related = this.getAllRelatedLinks(anchor); @@ -195,19 +182,6 @@ 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"), []) : []; @@ -254,18 +228,4 @@ export class LinkManager { return Cast(linkDoc.anchor1, Doc, new Doc); } } - - - // @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; - // } - } \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index bb8e8a5c2..ebeb1fcee 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -94,24 +94,12 @@ export class CollectionFreeFormLinksView extends React.Component { - // console.log("CONNECTION", StrCast(d.a.props.Document.title), StrCast(d.b.props.Document.title)); - // }); - - // console.log("CONNECTIONS"); - let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => { 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 => { - // 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 }); - }); - }); + 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)); @@ -132,13 +120,6 @@ 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() { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c71d7ed68..d77e08089 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -162,9 +162,7 @@ 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/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 80eadf668..87ebeefdb 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -224,7 +224,6 @@ export class LinkGroupEditor extends React.Component { groupMdKeys.forEach((key) => { let val = StrCast(mdDoc[key]); - console.log(key, val); metadata.push( ); diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index ae3446e25..1dd933c32 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -20,13 +20,28 @@ } .linkMenu-group-name { - padding: 4px 6px; - line-height: 12px; - border-radius: 5px; - font-weight: bold; + display: flex; &:hover { - background-color: lightgray; + p { + background-color: lightgray; + width: calc(100% - 26px); + } + .linkEditor-tableButton { + display: block; + } + } + + p { + width: 100%; + padding: 4px 6px; + line-height: 12px; + border-radius: 5px; + font-weight: bold; + } + + .linkEditor-tableButton { + display: none; } } } diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx index 71326f703..732e76997 100644 --- a/src/client/views/nodes/LinkMenuGroup.tsx +++ b/src/client/views/nodes/LinkMenuGroup.tsx @@ -8,8 +8,10 @@ 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 { DragLinksAsDocuments, DragManager, SetupDrag } from "../../util/DragManager"; import { emptyFunction } from "../../../Utils"; +import { Docs } from "../../documents/Documents"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; interface LinkMenuGroupProps { sourceDoc: Doc; @@ -22,6 +24,7 @@ interface LinkMenuGroupProps { export class LinkMenuGroup extends React.Component { private _drag = React.createRef(); + private _table = React.createRef(); onLinkButtonDown = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -55,6 +58,17 @@ export class LinkMenuGroup extends React.Component { e.stopPropagation(); } + viewGroupAsTable = (groupType: string): JSX.Element => { + let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType); + let index = keys.indexOf(""); + if (index > -1) keys.splice(index, 1); + let cols = ["anchor1", "anchor2", ...[...keys]]; + let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType); + let createTable = action(() => Docs.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" })); + let ref = React.createRef(); + return
; + } + render() { let groupItems = this.props.group.map(linkDoc => { let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); @@ -64,7 +78,10 @@ export class LinkMenuGroup extends React.Component { return (
-

{this.props.groupType}:

+
+

{this.props.groupType}:

+ {this.viewGroupAsTable(this.props.groupType)} +
{groupItems}
diff --git a/src/client/views/nodes/LinkMenuItem.scss b/src/client/views/nodes/LinkMenuItem.scss index 25d167231..175a93cb2 100644 --- a/src/client/views/nodes/LinkMenuItem.scss +++ b/src/client/views/nodes/LinkMenuItem.scss @@ -1,4 +1,5 @@ @import "../globalCssVariables"; + .linkMenu-item { // border-top: 0.5px solid $main-accent; position: relative; @@ -13,6 +14,7 @@ padding: 4px 6px; line-height: 12px; border-radius: 5px; + overflow-wrap: break-word; } } -- cgit v1.2.3-70-g09d2 From 8954bac59b50aa3618625379a17dbefe9aceca72 Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Wed, 26 Jun 2019 12:29:07 -0400 Subject: removed console.logs --- src/client/views/MainView.tsx | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7d2aa3199..4fcc9faa2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -205,9 +205,6 @@ export class MainView extends React.Component { getScale={returnOne} />; let castRes = mainCont ? FieldValue(Cast(mainCont.presentationView, listSpec(Doc))) : undefined; - console.log("GETTING mainContent()"); - console.log(castRes instanceof Promise); - console.log(castRes); return {({ measureRef }) =>
-- cgit v1.2.3-70-g09d2 From 0d5e2537520ca1e6a6b52f4d0f03aa2bcfc6c5c6 Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Wed, 26 Jun 2019 12:30:16 -0400 Subject: cleanup --- src/client/views/collections/CollectionBaseView.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 6639879e1..7b2f216dd 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -146,9 +146,6 @@ export class CollectionBaseView extends React.Component { } }); - //initial - // - if (index !== -1) { value.splice(index, 1); @@ -189,4 +186,4 @@ export class CollectionBaseView extends React.Component { ); } -} \ No newline at end of file +} -- cgit v1.2.3-70-g09d2 From f0632e4f6b608d05ef6d9f77d93da259c58c1e8d Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Wed, 26 Jun 2019 12:33:16 -0400 Subject: long line wrap --- .../views/presentationview/PresentationList.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationList.tsx b/src/client/views/presentationview/PresentationList.tsx index e2ec343d3..7abd3e366 100644 --- a/src/client/views/presentationview/PresentationList.tsx +++ b/src/client/views/presentationview/PresentationList.tsx @@ -82,8 +82,23 @@ export default class PresentationViewList extends React.Component return (
- {children.map((doc: Doc, index: number) => { if (e) { this.props.presElementsMappings.set(doc, e); } }} key={doc[Id]} mainDocument={this.props.mainDocument} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupMappings={this.props.groupMappings} allListElements={children} presStatus={this.props.presStatus} presButtonBackUp={this.props.presButtonBackUp} presGroupBackUp={this.props.presGroupBackUp} />)} + {children.map((doc: Doc, index: number) => + { if (e) { this.props.presElementsMappings.set(doc, e); } }} + key={doc[Id]} + mainDocument={this.props.mainDocument} + document={doc} + index={index} + deleteDocument={this.props.deleteDocument} + gotoDocument={this.props.gotoDocument} + groupMappings={this.props.groupMappings} + allListElements={children} + presStatus={this.props.presStatus} + presButtonBackUp={this.props.presButtonBackUp} + presGroupBackUp={this.props.presGroupBackUp} + /> + )}
); } -} \ No newline at end of file +} -- cgit v1.2.3-70-g09d2 From 6d1f161de3c27ec07673b5e48a915961177b57b6 Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Wed, 26 Jun 2019 12:39:54 -0400 Subject: long line wrap --- src/client/views/presentationview/PresentationView.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index 50defa197..20d0e113a 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -776,8 +776,18 @@ export class PresentationView extends React.Component { {this.renderPlayPauseButton()}
- +
); } -} \ No newline at end of file +} -- 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') 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 a81677c7dffafa5134d4c5cbe893f7a886eaab63 Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 26 Jun 2019 14:48:16 -0400 Subject: can clear links on a doc --- src/client/util/LinkManager.ts | 5 +++++ src/client/views/nodes/LinkEditor.scss | 14 +++++++++----- src/client/views/nodes/LinkEditor.tsx | 1 + src/client/views/nodes/LinkMenu.scss | 4 ++++ src/client/views/nodes/LinkMenu.tsx | 10 ++++++++++ 5 files changed, 29 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 1db686751..f2f3e51dd 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -75,6 +75,11 @@ export class LinkManager { return related; } + public deleteAllLinksOnAnchor(anchor: Doc) { + let related = LinkManager.Instance.getAllRelatedLinks(anchor); + related.forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); + } + public addGroupType(groupType: string): boolean { if (LinkManager.Instance.LinkManagerDoc) { LinkManager.Instance.LinkManagerDoc[groupType] = new List([]); diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index 1424d7633..3c49c2212 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -47,8 +47,8 @@ border-radius: 3px; .linkEditor-group-row { - display: flex; - margin-bottom: 6px; + // display: flex; + margin-bottom: 3px; .linkEditor-group-row-label { margin-right: 6px; @@ -65,16 +65,16 @@ } input { - width: calc(50% - 18px); + width: calc(50% - 16px); height: 20px; } button { width: 20px; height: 20px; - margin-left: 6px; + margin-left: 3px; padding: 0; - font-size: 14px; + font-size: 10px; } } } @@ -85,6 +85,10 @@ position: relative; z-index: 999; + input { + width: 100%; + } + .linkEditor-options-wrapper { width: 100%; position: absolute; diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index 51efcc36d..22da732cf 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -278,6 +278,7 @@ export class LinkGroupEditor extends React.Component {

type:

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

metadata:

: <>} {this.renderMetadata()}
{buttons} diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index 429977326..7cc11172b 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -131,4 +131,8 @@ } } +.linkEditor-clearButton { + float: right; +} + diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 8ef899cfc..71384c368 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -7,6 +7,11 @@ import React = require("react"); import { Doc } from "../../../new_fields/Doc"; import { LinkManager } from "../../util/LinkManager"; import { LinkMenuGroup } from "./LinkMenuGroup"; +import { faTrash } from '@fortawesome/free-solid-svg-icons'; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +library.add(faTrash) interface Props { docView: DocumentView; @@ -23,6 +28,10 @@ export class LinkMenu extends React.Component { this._editingLink = undefined; } + clearAllLinks = () => { + LinkManager.Instance.deleteAllLinksOnAnchor(this.props.docView.props.Document); + } + renderAllGroups = (groups: Map>): Array => { let linkItems: Array = []; groups.forEach((group, groupType) => { @@ -43,6 +52,7 @@ export class LinkMenu extends React.Component { if (this._editingLink === undefined) { return (
+ {/* */}
{this.renderAllGroups(groups)} -- 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') 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 From fcba28b1f826da50729e3a005f5fcac7a3c4316c Mon Sep 17 00:00:00 2001 From: Fawn Date: Wed, 26 Jun 2019 17:27:48 -0400 Subject: cant link to user doc --- src/client/documents/Documents.ts | 1 + src/client/util/DragManager.ts | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ddbf8f753..7b14ae037 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -73,6 +73,7 @@ export namespace DocUtils { if (LinkManager.Instance.doesLinkExist(source, target)) return; let sv = DocumentManager.Instance.getDocumentView(source); if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return; + if (target === CurrentUserUtils.UserDocument) return; UndoManager.RunInBatch(() => { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 5c75c8fe5..ddc10d38a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -215,10 +215,8 @@ export namespace DragManager { StartDrag(eles, dragData, downX, downY, options, (dropData: { [id: string]: any }) => { // 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); -- cgit v1.2.3-70-g09d2 From 3605690fb0778ab5a5c8f56c8a3e0c65206a9cb2 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 26 Jun 2019 22:22:55 -0400 Subject: icon --- src/client/views/presentationview/PresentationElement.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 43cb9cb86..4afc0210f 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -9,6 +9,7 @@ import { Utils } from "../../../Utils"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faFile as fileSolid, faFileDownload, faLocationArrow, faArrowUp, faSearch } from '@fortawesome/free-solid-svg-icons'; +import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; @@ -17,7 +18,7 @@ library.add(faArrowUp); library.add(fileSolid); library.add(faLocationArrow); library.add(faSearch); -library.add(faFileDownload); +library.add(fileRegular); interface PresentationElementProps { mainDocument: Doc; -- cgit v1.2.3-70-g09d2