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/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 ++++++++++++++--- 7 files changed, 179 insertions(+), 21 deletions(-) create mode 100644 src/client/views/nodes/LinkManager.tsx (limited to 'src/client/views') 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