From e7372931b9d28c141aaec9552041b5644c2f415a Mon Sep 17 00:00:00 2001 From: geireann <60007097+geireann@users.noreply.github.com> Date: Fri, 26 Jun 2020 03:37:08 +0800 Subject: Merge branch 'master' into mobile_revision_direct And changes to UI of record and image upload --- src/client/views/nodes/LinkDocPreview.tsx | 107 ++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/client/views/nodes/LinkDocPreview.tsx (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx new file mode 100644 index 000000000..126dc240a --- /dev/null +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -0,0 +1,107 @@ +import { action, computed, observable, runInAction } from 'mobx'; +import { observer } from "mobx-react"; +import wiki from "wikijs"; +import { Doc, DocCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Cast, FieldValue, NumCast } from "../../../fields/Types"; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero } from "../../../Utils"; +import { Docs } from "../../documents/Documents"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Transform } from "../../util/Transform"; +import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; +import React = require("react"); +import { DocumentView } from './DocumentView'; + +interface Props { + linkDoc?: Doc; + linkSrc?: Doc; + href?: string; + backgroundColor: (doc: Doc) => string; + addDocTab: (document: Doc, where: string) => boolean; + location: number[]; +} +@observer +export class LinkDocPreview extends React.Component { + @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>; + @observable _targetDoc: Opt; + @observable _toolTipText = ""; + + componentDidUpdate() { this.updatePreview() } + componentDidMount() { this.updatePreview() } + async updatePreview() { + const linkDoc = this.props.linkDoc; + const linkSrc = this.props.linkSrc; + if (this.props.href) { + if (this.props.href.startsWith("https://en.wikipedia.org/wiki/")) { + wiki().page(this.props.href.replace("https://en.wikipedia.org/wiki/", "")).then(page => page.summary().then(action(summary => this._toolTipText = summary.substring(0, 500)))); + } else { + runInAction(() => this._toolTipText = "external => " + this.props.href); + } + } else if (linkDoc && linkSrc) { + const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), linkSrc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc); + const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor; + runInAction(() => { + this._toolTipText = ""; + this._targetDoc = target; + if (anchor !== this._targetDoc && anchor && this._targetDoc) { + this._targetDoc._scrollY = NumCast(anchor?.y); + } + }); + } + } + pointerDown = (e: React.PointerEvent) => { + if (this.props.linkDoc && this.props.linkSrc) { + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.linkSrc, + (doc: Doc, followLinkLocation: string) => this.props.addDocTab(doc, e.ctrlKey ? "inTab" : followLinkLocation)); + } else if (this.props.href) { + this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight"); + } + } + width = () => Math.min(350, NumCast(this._targetDoc?.[WidthSym](), 350)); + height = () => Math.min(350, NumCast(this._targetDoc?.[HeightSym](), 350)); + @computed get targetDocView() { + return !this._targetDoc ? +
+
+ {this._toolTipText} +
+
: + ; + } + + render() { + return
+ {this.targetDocView} +
; + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From d662a26c9ef78581a823d14b56433950129b7ccb Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Tue, 30 Jun 2020 12:02:49 -0500 Subject: preview and movement adjustment --- src/client/views/linking/LinkMenu.tsx | 6 +- src/client/views/nodes/LinkDocPreview.tsx | 107 +++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 32 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 0fcc0f0b9..6b24f96b1 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -28,9 +28,13 @@ export class LinkMenu extends React.Component { @action onClick = (e: PointerEvent) => { - if (!Array.from(this._linkMenuRef?.getElementsByTagName((e.target as HTMLElement).tagName) || []).includes(e.target as any)) { + if (this._linkMenuRef && !Array.from(this._linkMenuRef?.getElementsByTagName((e.target as HTMLElement).tagName) || []).includes(e.target as any)) { DocumentLinksButton.EditLink = undefined; } + + // if (this._linkMenuRef && !this._linkMenuRef.contains(e.target)) { + // DocumentLinksButton.EditLink = undefined; + // } } @action componentDidMount() { diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 92b443d3b..1d2c022a7 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -10,6 +10,11 @@ import { Transform } from "../../util/Transform"; import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; import React = require("react"); import { DocumentView } from './DocumentView'; +import { sortAndDeduplicateDiagnostics } from 'typescript'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { LinkManager } from '../../util/LinkManager'; +import { DocumentLinksButton } from './DocumentLinksButton'; +import { ContextMenu } from '../ContextMenu'; interface Props { linkDoc?: Doc; @@ -24,6 +29,31 @@ export class LinkDocPreview extends React.Component { @observable public static LinkInfo: Opt<{ linkDoc?: Doc; addDocTab: (document: Doc, where: string) => boolean, linkSrc: Doc; href?: string; Location: number[] }>; @observable _targetDoc: Opt; @observable _toolTipText = ""; + _editRef = React.createRef(); + + @action + deleteLink = (): void => { + this.props.linkDoc ? LinkManager.Instance.deleteLink(this.props.linkDoc) : null; + //this.props.showLinks(); + LinkDocPreview.LinkInfo = undefined; + DocumentLinksButton.EditLink = undefined; + } + + @action + onContextMenu = (e: React.MouseEvent) => { + DocumentLinksButton.EditLink = undefined; + LinkDocPreview.LinkInfo = undefined; + e.preventDefault(); + ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" }); + ContextMenu.Instance.displayMenu(e.clientX, e.clientY); + } + + @action.bound + async followDefault() { + DocumentLinksButton.EditLink = undefined; + LinkDocPreview.LinkInfo = undefined; + this._targetDoc ? DocumentManager.Instance.FollowLink(this.props.linkDoc, this._targetDoc, doc => this.props.addDocTab(doc, "onRight"), false) : null; + } componentDidUpdate() { this.updatePreview(); } componentDidMount() { this.updatePreview(); } @@ -56,42 +86,57 @@ export class LinkDocPreview extends React.Component { this.props.addDocTab(Docs.Create.WebDocument(this.props.href, { title: this.props.href, _width: 200, _height: 400, UseCors: true }), "onRight"); } } - width = () => Math.min(350, NumCast(this._targetDoc?.[WidthSym](), 350)); - height = () => Math.min(350, NumCast(this._targetDoc?.[HeightSym](), 350)); + width = () => Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)); + height = () => Math.min(225, NumCast(this._targetDoc?.[HeightSym](), 225)); @computed get targetDocView() { return !this._targetDoc ? -
+
{this._toolTipText}
: - ; +
+
{this._targetDoc.title} +
+
+
+
+ +
+
+
+
; } render() { @@ -99,7 +144,7 @@ export class LinkDocPreview extends React.Component { style={{ position: "absolute", left: this.props.location[0], top: this.props.location[1], width: this.width(), height: this.height(), - boxShadow: "black 2px 2px 1em" + boxShadow: "black 2px 2px 1em", zIndex: 1000 }}> {this.targetDocView}
; -- cgit v1.2.3-70-g09d2 From 3cc69c7f5ae7f7a747ab72b522ea81af38dd7f20 Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Tue, 30 Jun 2020 16:45:23 -0500 Subject: slight mods to inline links --- src/client/views/nodes/LinkDocPreview.tsx | 79 +++++++++++----------- .../formattedText/FormattedTextBoxComment.tsx | 6 +- 2 files changed, 45 insertions(+), 40 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 1d2c022a7..d02896436 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -98,45 +98,46 @@ export class LinkDocPreview extends React.Component { {this._toolTipText} : -
-
{this._targetDoc.title} -
-
-
-
- -
-
-
-
; + //
+ //
{this._targetDoc.title} + //
+ //
+ //
+ //
+ // + //
+ //
+ //
+ ; + //
; } render() { diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index a4153a40c..8eeeae051 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -73,6 +73,8 @@ export class FormattedTextBoxComment { static targetDoc: Doc | undefined; static _editRef = React.createRef(); + static openDoc: any; + constructor(view: any) { if (!FormattedTextBoxComment.tooltip) { const root = document.getElementById("root"); @@ -99,6 +101,7 @@ export class FormattedTextBoxComment { if (FormattedTextBoxComment.linkDoc && !keep && textBox) { if (FormattedTextBoxComment.linkDoc.author) { if (FormattedTextBoxComment.linkDoc.type !== DocumentType.LINK) { + FormattedTextBoxComment.openDoc = textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight"); textBox.props.addDocTab(FormattedTextBoxComment.linkDoc, e.ctrlKey ? "inTab" : "onRight"); } else { DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, textBox.props.Document, @@ -119,6 +122,7 @@ export class FormattedTextBoxComment { @action public static deleteLink = (): void => { + console.log(FormattedTextBoxComment.linkDoc); FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null; //this.props.showLinks(); LinkDocPreview.LinkInfo = undefined; @@ -139,7 +143,7 @@ export class FormattedTextBoxComment { DocumentLinksButton.EditLink = undefined; LinkDocPreview.LinkInfo = undefined; FormattedTextBoxComment.targetDoc ? DocumentManager.Instance.FollowLink(FormattedTextBoxComment.linkDoc, FormattedTextBoxComment.targetDoc, - doc => MainView.addDocTabFunc(doc, "onRight"), false) : null; + doc => FormattedTextBoxComment, false) : null; } public static Hide() { -- cgit v1.2.3-70-g09d2 From 95cb352eae8188e01dbed9fce19a27481cda667c Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Thu, 9 Jul 2020 22:06:19 -0500 Subject: change doc preiew layout --- src/client/views/linking/LinkMenuItem.scss | 4 ++++ src/client/views/linking/LinkMenuItem.tsx | 5 +--- .../views/nodes/ContentFittingDocumentView.tsx | 4 ++-- src/client/views/nodes/LinkDocPreview.tsx | 27 +++++++--------------- 4 files changed, 15 insertions(+), 25 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss index a3cce8e3c..f759aef5e 100644 --- a/src/client/views/linking/LinkMenuItem.scss +++ b/src/client/views/linking/LinkMenuItem.scss @@ -12,6 +12,8 @@ padding-top: 6.5px; padding-bottom: 6.5px; + background-color: white; + .linkMenu-name { position: relative; @@ -103,6 +105,8 @@ &:hover { + background-color: rgb(201, 239, 252); + .linkMenu-item-buttons { display: flex; } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index a07266023..05ec10f71 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -213,10 +213,7 @@ export class LinkMenuItem extends React.Component {
{this.props.linkDoc.linkedText ?

- Source: {StrCast(this.props.linkDoc.linkedText)}

: null} - -

- Source: sample text

+ Source: {StrCast(this.props.linkDoc.linkedText)}

: null}
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index ba075886b..be72bf60c 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -2,7 +2,7 @@ import React = require("react"); import { computed } from "mobx"; import { observer } from "mobx-react"; import { Transform } from "nodemailer/lib/xoauth2"; -import "react-table/react-table.css"; +//import "react-table/react-table.css"; import { Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; @@ -10,7 +10,7 @@ import { TraceMobx } from "../../../fields/util"; import { emptyFunction } from "../../../Utils"; import { dropActionType } from "../../util/DragManager"; import { CollectionView } from "../collections/CollectionView"; -import '../DocumentDecorations.scss'; + import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import "./ContentFittingDocumentView.scss"; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 197dc8df4..079920f56 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -98,23 +98,11 @@ export class LinkDocPreview extends React.Component { {this._toolTipText}
: - //
- //
{this._targetDoc.title} - //
- //
- //
- //
- // - //
- //
- //
+ { ContainingCollectionDoc={undefined} ContainingCollectionView={undefined} renderDepth={0} - PanelWidth={this.width} - PanelHeight={this.height} + PanelWidth={() => this.width() - 16} //Math.min(350, NumCast(target._width, 350))} + PanelHeight={() => this.height() - 16} //Math.min(250, NumCast(target._height, 250))} focus={emptyFunction} whenActiveChanged={returnFalse} bringToFront={returnFalse} ContentScaling={returnOne} NativeWidth={returnZero} - NativeHeight={returnZero} - />; - //
; + NativeHeight={returnZero} />; } render() { @@ -145,7 +131,10 @@ export class LinkDocPreview extends React.Component { style={{ position: "absolute", left: this.props.location[0], top: this.props.location[1], width: this.width(), height: this.height(), - boxShadow: "black 2px 2px 1em", zIndex: 1000 + zIndex: 1000, + border: "8px solid white", borderRadius: "7px", + boxShadow: "3px 3px 1.5px grey", + borderBottom: "8px solid white", borderRight: "8px solid white" }}> {this.targetDocView} ; -- cgit v1.2.3-70-g09d2 From 0dafe85b7d0c826340299a7e6b51190a6eaa7004 Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Mon, 13 Jul 2020 17:56:46 -0500 Subject: fixed preview backgrounds, text size, tooltip size, adding labels, conditional end link btn, tooltips size --- src/client/views/DocumentButtonBar.tsx | 106 +++++++++++---------- src/client/views/DocumentDecorations.tsx | 12 +-- src/client/views/MainView.tsx | 4 +- .../views/collections/CollectionLinearView.tsx | 9 +- src/client/views/linking/LinkEditor.scss | 24 ++++- src/client/views/linking/LinkEditor.tsx | 27 ++++-- src/client/views/linking/LinkMenuItem.scss | 1 + src/client/views/linking/LinkMenuItem.tsx | 6 +- src/client/views/nodes/DocumentLinksButton.scss | 12 +-- src/client/views/nodes/DocumentLinksButton.tsx | 24 ++--- src/client/views/nodes/LinkDocPreview.tsx | 3 +- .../formattedText/FormattedTextBoxComment.tsx | 4 +- 12 files changed, 135 insertions(+), 97 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index a3d24b3b6..c132eb5bb 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -119,7 +119,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const targetDoc = this.view0?.props.Document; const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined; const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none"; - return !targetDoc ? (null) : + return !targetDoc ? (null) :
{`${published ? "Push" : "Publish"} to Google Docs`}
}>
(DocumentV const targetDoc = this.view0?.props.Document; const dataDoc = targetDoc && Doc.GetProto(targetDoc); const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none"; + + const title = (() => { + switch (this.openHover) { + default: + case UtilityButtonState.Default: return `${!dataDoc?.unchanged ? "Pull from" : "Fetch"} Google Docs`; + case UtilityButtonState.OpenRight: return "Open in Right Split"; + case UtilityButtonState.OpenExternally: return "Open in new Browser Tab"; + } + })(); + return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : { - switch (this.openHover) { - default: - case UtilityButtonState.Default: return `${!dataDoc.unchanged ? "Pull from" : "Fetch"} Google Docs`; - case UtilityButtonState.OpenRight: return "Open in Right Split"; - case UtilityButtonState.OpenExternally: return "Open in new Browser Tab"; - } - })()} - >
{ - if (e.altKey) { - this.openHover = UtilityButtonState.OpenExternally; - } else if (e.shiftKey) { - this.openHover = UtilityButtonState.OpenRight; - } - })} - onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)} - onClick={async e => { - const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`; - if (e.shiftKey) { - e.preventDefault(); - let googleDoc = await Cast(dataDoc.googleDoc, Doc); - if (!googleDoc) { - const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false }; - googleDoc = Docs.Create.WebDocument(googleDocUrl, options); - dataDoc.googleDoc = googleDoc; + title={
{title}
}> +
{ + if (e.altKey) { + this.openHover = UtilityButtonState.OpenExternally; + } else if (e.shiftKey) { + this.openHover = UtilityButtonState.OpenRight; + } + })} + onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)} + onClick={async e => { + const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`; + if (e.shiftKey) { + e.preventDefault(); + let googleDoc = await Cast(dataDoc.googleDoc, Doc); + if (!googleDoc) { + const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false }; + googleDoc = Docs.Create.WebDocument(googleDocUrl, options); + dataDoc.googleDoc = googleDoc; + } + CollectionDockingView.AddRightSplit(googleDoc); + } else if (e.altKey) { + e.preventDefault(); + window.open(googleDocUrl); + } else { + this.clearPullColor(); + DocumentButtonBar.hasPulledHack = false; + targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1; + dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true); } - CollectionDockingView.AddRightSplit(googleDoc); - } else if (e.altKey) { - e.preventDefault(); - window.open(googleDocUrl); - } else { - this.clearPullColor(); - DocumentButtonBar.hasPulledHack = false; - targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1; - dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true); - } - }}> + }}> { @@ -195,7 +198,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV get pinButton() { const targetDoc = this.view0?.props.Document; const isPinned = targetDoc && Doc.isDocPinned(targetDoc); - return !targetDoc ? (null) : + return !targetDoc ? (null) :
{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}
}>
DockedFrameRenderer.PinDoc(targetDoc, isPinned)}> @@ -207,14 +210,15 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV @computed get metadataButton() { const view0 = this.view0; - return !view0 ? (null) :
- this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction /> /* tfs: @bcz This might need to be the data document? */}> -
e.stopPropagation()} > - {} -
-
-
; + return !view0 ? (null) :
Show metadata panel
}> +
+ this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction /> /* tfs: @bcz This might need to be the data document? */}> +
e.stopPropagation()} > + {} +
+
+
; } @computed @@ -255,7 +259,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV Array.from(Object.values(Templates.TemplateList)).map(template => templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean))); return !view0 ? (null) : - +
Tap: Customize layout. Drag: Create alias
}>
this._aliasDown = true)} onClose={action(() => this._aliasDown = false)} content={!this._aliasDown ? (null) : v).map(v => v as DocumentView)} templates={templates} />}> @@ -276,9 +280,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
-
+ {DocumentLinksButton.StartLink ?
-
+
: null}
{this.templateButton}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d7324e1a6..2e3c63cf2 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -547,11 +547,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? ( - +
Show context menu
} placement="top">
) : ( - +
Iconify
} placement="top">
{/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} @@ -575,7 +575,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
} : <> - {minimal ? (null) :
+ {minimal ? (null) :
Show context menu
} placement="top">
}
@@ -614,11 +614,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> {maximizeIcon} {titleArea} {SelectionManager.SelectedDocuments().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) : - +
{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}
} placement="top">
{"_"}
} -
+
Open Document In Tab
} placement="top">
{SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
e.preventDefault()}>
{seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) : - +
tap to select containing document
} placement="top">
e.preventDefault()}> diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 2ed528836..a54973489 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -6,7 +6,7 @@ import { faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle, faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight, - faHeading, faRulerCombined, faFillDrip, faUnlink + faHeading, faRulerCombined, faFillDrip, faUnlink, faHandPaper } from '@fortawesome/free-solid-svg-icons'; import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -147,7 +147,7 @@ export class MainView extends React.Component { faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell, faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight, - faHeading, faRulerCombined, faFillDrip, faUnlink); + faHeading, faRulerCombined, faFillDrip, faUnlink, faHandPaper); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index dd4df20c9..319cca70f 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -124,7 +124,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { return
- +
{BoolCast(this.props.Document.linearViewIsExpanded) ? "Close menu" : "Open menu"}
} placement="top"> {menuOpener}
e.stopPropagation()} > Creating link from: {DocumentLinksButton.StartLink.title} - + +
{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" : + "Turn on description pop-up"}
} placement="top"> Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"}
- +
Exit link clicking mode
} placement="top"> Clear
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index 87afc99eb..d26b7920a 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -13,6 +13,10 @@ width: 18px; height: 18px; padding: 0; + + &:hover { + cursor: pointer; + } } .linkEditor-info { @@ -28,7 +32,13 @@ .linkEditor-linkedTo { width: calc(100% - 26px); padding-left: 5px; - padding-right: 5px + padding-right: 5px; + + .linkEditor-downArrow { + &:hover { + cursor: pointer; + } + } } } @@ -43,6 +53,10 @@ .button { color: black; + + &:hover { + cursor: pointer; + } } } @@ -83,6 +97,10 @@ padding-right: 8px; height: 80%; color: white; + + &:hover { + cursor: pointer; + } } } } @@ -92,6 +110,10 @@ padding-right: 6.5px; padding-bottom: 6px; + &:hover { + cursor: pointer; + } + .linkEditor-followingDropdown-label { color: black; } diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index a26685318..1cc981d42 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -13,6 +13,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { DocumentLinksButton } from "../nodes/DocumentLinksButton"; import { EditableView } from "../EditableView"; import { RefObject } from "react"; +import { Tooltip } from "@material-ui/core"; library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); @@ -285,15 +286,12 @@ interface LinkEditorProps { @observer export class LinkEditor extends React.Component { - @observable description = StrCast(LinkManager.currentLink?.description); @observable openDropdown: boolean = false; - @observable followBehavior = this.props.linkDoc.follow ? this.props.linkDoc.follow : "Default"; - @observable showInfo: boolean = false; - @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; } + @observable private buttonColor: string = "black"; //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; @@ -308,6 +306,10 @@ export class LinkEditor extends React.Component { setDescripValue = (value: string) => { if (LinkManager.currentLink) { LinkManager.currentLink.description = value; + this.buttonColor = "rgb(62, 133, 55)"; + setTimeout(action(() => { + this.buttonColor = "black"; + }), 750); return true; } } @@ -349,7 +351,8 @@ export class LinkEditor extends React.Component { >
Add
+ style={{ backgroundColor: this.buttonColor }} + onPointerDown={this.onDown}>Set
; } @@ -413,15 +416,19 @@ export class LinkEditor extends React.Component { return !destination ? (null) : (
- +
Return to link menu
} placement="top"> + +

Editing Link to: { destination.proto?.title ?? destination.title ?? "untitled"}

{/* */} - +
Show more link information
} placement="top"> +
+
{this.showInfo ?
{this.props.linkDoc.author ?
Author: {this.props.linkDoc.author}
: null}
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss index f70f5a23e..4e13ef8c8 100644 --- a/src/client/views/linking/LinkMenuItem.scss +++ b/src/client/views/linking/LinkMenuItem.scss @@ -67,6 +67,7 @@ color: rgb(60, 90, 156); //display: inline; text-overflow: break; + cursor: pointer; } } } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index b451f0168..ff9401696 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -253,16 +253,16 @@ export class LinkMenuItem extends React.Component { {canExpand ?
this.toggleShowMore(e)}>
: <>} - +
{showTitle}
}>
- +
Edit Link
}>
- +
Delete Link
}>
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss index 35d99d44b..97e714cd5 100644 --- a/src/client/views/nodes/DocumentLinksButton.scss +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -13,18 +13,18 @@ color: black; text-transform: uppercase; letter-spacing: 2px; - font-size: 75%; + font-size: 10px; transition: transform 0.2s; text-align: center; display: flex; justify-content: center; align-items: center; - // &:hover { - // background: deepskyblue; - // transform: scale(1.05); - // cursor: pointer; - // } + &:hover { + // background: deepskyblue; + // transform: scale(1.05); + cursor: pointer; + } } .documentLinksButton { diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 83710cfbf..96ff0157e 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -168,8 +168,8 @@ export class DocumentLinksButton extends React.Component - {/* {this.props.InMenu ? this.props.StartLink ? : - : links.length} */} - {/* {this.props.InMenu ? this.props.StartLink ? : - link : links.length} */} + {this.props.InMenu ? this.props.StartLink ? : + : links.length} - {this.props.InMenu ? this.props.StartLink ? startLink : - endLink : links.length}
{DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
: (null)}
; + return (!links.length) && !this.props.AlwaysOn ? (null) : - - {linkButton} - ; + this.props.InMenu ? +
{title}
}> + {linkButton} +
: !!!DocumentLinksButton.EditLink ? +
{title}
}> + {linkButton} +
: + linkButton; } render() { return this.linkButton; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 079920f56..1caa82380 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -123,7 +123,8 @@ export class LinkDocPreview extends React.Component { bringToFront={returnFalse} ContentScaling={returnOne} NativeWidth={returnZero} - NativeHeight={returnZero} />; + NativeHeight={returnZero} + backgroundColor={this.props.backgroundColor} />; } render() { diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index fa2548cb5..c98b5eac1 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -270,14 +270,14 @@ export class FormattedTextBoxComment {
- +
Delete Link
} placement="top">
this._deleteRef = r}>
- +
Follow Link
} placement="top">
this._followRef = r}> Date: Wed, 22 Jul 2020 11:33:28 -0400 Subject: restored download document. fixed clone() to clone to be async and handles lists properly. --- src/client/util/CurrentUserUtils.ts | 6 +++++ src/client/util/LinkManager.ts | 12 ++------- src/client/util/Scripting.ts | 10 +++----- src/client/views/GlobalKeyHandler.ts | 4 +-- src/client/views/PreviewCursor.tsx | 4 +-- .../collections/collectionFreeForm/MarqueeView.tsx | 8 +++--- src/client/views/linking/LinkEditor.tsx | 4 +-- src/client/views/linking/LinkMenuItem.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 14 ++++------ src/client/views/nodes/LinkDocPreview.tsx | 9 +------ .../formattedText/FormattedTextBoxComment.tsx | 2 ++ .../views/nodes/formattedText/RichTextMenu.tsx | 4 ++- src/fields/Doc.ts | 30 +++++++++++----------- src/server/ApiManagers/DownloadManager.ts | 12 +++------ src/server/ApiManagers/UploadManager.ts | 14 +++------- 15 files changed, 56 insertions(+), 80 deletions(-) (limited to 'src/client/views/nodes/LinkDocPreview.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 03a75381a..23b8f09de 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -22,6 +22,7 @@ import { DocumentType } from "../documents/DocumentTypes"; import { SchemaHeaderField } from "../../fields/SchemaHeaderField"; import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView"; import { LabelBox } from "../views/nodes/LabelBox"; +import { LinkManager } from "./LinkManager"; export class CurrentUserUtils { private static curr_id: string; @@ -888,3 +889,8 @@ export class CurrentUserUtils { Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.createNewWorkspace(); }, "creates a new workspace when called"); + +Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, + "returns all the links to the document or its annotations", "(doc: any)"); +Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); }, + "returns all the links directly to the document", "(doc: any)"); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 974744344..223f0e7ef 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -2,8 +2,6 @@ import { Doc, DocListCast, Opt } from "../../fields/Doc"; import { List } from "../../fields/List"; import { listSpec } from "../../fields/Schema"; import { Cast, StrCast } from "../../fields/Types"; -import { Scripting } from "./Scripting"; -import { undoBatch } from "./UndoManager"; /* * link doc: @@ -25,12 +23,12 @@ export class LinkManager { private static _instance: LinkManager; - public static currentLink: Opt; public static get Instance(): LinkManager { return this._instance || (this._instance = new this()); } + private constructor() { } @@ -53,7 +51,6 @@ export class LinkManager { return false; } - @undoBatch public deleteLink(linkDoc: Doc): boolean { if (LinkManager.Instance.LinkManagerDoc && linkDoc instanceof Doc) { Doc.RemoveDocFromList(LinkManager.Instance.LinkManagerDoc, "data", linkDoc); @@ -210,9 +207,4 @@ export class LinkManager { if (Doc.AreProtosEqual(anchor, a2)) return a1; if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc; } -} - -Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, - "returns all the links to the document or its annotations", "(doc: any)"); -Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); }, - "returns all the links directly to the document", "(doc: any)"); \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index e6cf50de3..f1e6155d2 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -10,8 +10,6 @@ export { ts }; // @ts-ignore import * as typescriptlib from '!!raw-loader!./type_decls.d'; import { Doc, Field } from '../../fields/Doc'; -import { Cast } from "../../fields/Types"; -import { listSpec } from "../../fields/Schema"; export interface ScriptSucccess { success: true; @@ -95,10 +93,10 @@ export namespace Scripting { export function removeGlobal(name: string) { if (getGlobals().includes(name)) { delete _scriptingGlobals[name]; - if (_scriptingDescriptions[name]){ + if (_scriptingDescriptions[name]) { delete _scriptingDescriptions[name]; } - if (_scriptingParams[name]){ + if (_scriptingParams[name]) { delete _scriptingParams[name]; } return true; @@ -123,11 +121,11 @@ export namespace Scripting { return _scriptingGlobals; } - export function getDescriptions(){ + export function getDescriptions() { return _scriptingDescriptions; } - export function getParameters(){ + export function getParameters() { return _scriptingParams; } } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 4dfa7aec8..b63537b5f 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -309,13 +309,13 @@ export default class KeyManager { const targetDataDoc = Doc.GetProto(first.props.Document); const fieldKey = Doc.LayoutFieldKey(first.props.Document); const docList = DocListCast(targetDataDoc[fieldKey]); - docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { + docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => { count++; if (doc instanceof Doc) { list.push(doc); } if (count === docids.length) { - const added = list.filter(d => !docList.includes(d)).map(d => clone ? Doc.MakeClone(d) : d); + const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? await Doc.MakeClone(d) : d)); if (added.length) { added.map(doc => doc.context = targetDataDoc); undoBatch(() => { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 6583589f3..2d51403d7 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -69,11 +69,11 @@ export class PreviewCursor extends React.Component<{}> { const list: Doc[] = []; let first: Doc | undefined; - docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { + docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => { count++; if (doc instanceof Doc) { i === 1 && (first = doc); - const alias = clone ? Doc.MakeClone(doc) : doc; + const alias = clone ? await Doc.MakeClone(doc) : doc; const deltaX = NumCast(doc.x) - NumCast(first!.x) - ptx; const deltaY = NumCast(doc.y) - NumCast(first!.y) - pty; alias.x = newPoint[0] + deltaX; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6db8c8992..84719b2c9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -189,8 +189,8 @@ export class MarqueeView extends React.Component { this._downX = this._lastX = e.clientX; this._downY = this._lastY = e.clientY; - if (!(e as any).marqueeHit) { - (e as any).marqueeHit = true; + if (!(e.nativeEvent as any).marqueeHit) { + (e.nativeEvent as any).marqueeHit = true; // allow marquee if right click OR alt+left click OR space bar + left click if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) { // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) { @@ -291,8 +291,8 @@ export class MarqueeView extends React.Component { //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; + @undoBatch @action deleteLink = (): void => { LinkManager.Instance.deleteLink(this.props.linkDoc); @@ -422,8 +424,6 @@ export class LinkEditor extends React.Component {

Editing Link to: { destination.proto?.title ?? destination.title ?? "untitled"}

- {/* */}
Show more link information
} placement="top">
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 0e847632b..d8ba39f09 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -17,6 +17,7 @@ import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import { Tooltip } from '@material-ui/core'; import { DocumentType } from '../../documents/DocumentTypes'; +import { undoBatch } from '../../util/UndoManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash); @@ -163,10 +164,10 @@ export class LinkMenuItem extends React.Component { } } + @undoBatch @action deleteLink = (): void => { LinkManager.Instance.deleteLink(this.props.linkDoc); - //this.props.showLinks(); LinkDocPreview.LinkInfo = undefined; DocumentLinksButton.EditLink = undefined; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0b5bd707b..12d9890c9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -794,16 +794,12 @@ export class DocumentView extends DocComponent(Docu } moreItems.push({ description: "Download document", icon: "download", event: async () => { - const response = await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), { - qs: { q: 'world', fq: 'NOT baseProto_b:true AND NOT deleted:true', start: '0', rows: '100', hl: true, 'hl.fl': '*' } - }); - console.log(response ? JSON.parse(response) : undefined); + const a = document.createElement("a"); + const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); + a.href = url; + a.download = `DocExport-${this.props.Document[Id]}.zip`; + a.click(); } - // const a = document.createElement("a"); - // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); - // a.href = url; - // a.download = `DocExport-${this.props.Document[Id]}.zip`; - // a.click(); }); moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); } diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 1caa82380..ebb916307 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -15,6 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { LinkManager } from '../../util/LinkManager'; import { DocumentLinksButton } from './DocumentLinksButton'; import { ContextMenu } from '../ContextMenu'; +import { undoBatch } from '../../util/UndoManager'; interface Props { linkDoc?: Doc; @@ -31,14 +32,6 @@ export class LinkDocPreview extends React.Component { @observable _toolTipText = ""; _editRef = React.createRef(); - @action - deleteLink = (): void => { - this.props.linkDoc ? LinkManager.Instance.deleteLink(this.props.linkDoc) : null; - //this.props.showLinks(); - LinkDocPreview.LinkInfo = undefined; - DocumentLinksButton.EditLink = undefined; - } - @action onContextMenu = (e: React.MouseEvent) => { DocumentLinksButton.EditLink = undefined; diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 3687d5513..6f3984f39 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -22,6 +22,7 @@ import { LinkManager } from "../../../util/LinkManager"; import { LinkDocPreview } from "../LinkDocPreview"; import { DocumentLinksButton } from "../DocumentLinksButton"; import { Tooltip } from "@material-ui/core"; +import { undoBatch } from "../../../util/UndoManager"; export let formattedTextBoxCommentPlugin = new Plugin({ view(editorView) { return new FormattedTextBoxComment(editorView); } @@ -143,6 +144,7 @@ export class FormattedTextBoxComment { } } + @undoBatch @action deleteLink = () => { FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 2e0b0e659..47a4911b8 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -23,7 +23,7 @@ import { updateBullets } from "./ProsemirrorExampleTransfer"; import "./RichTextMenu.scss"; import { schema } from "./schema_rts"; import { TraceMobx } from "../../../../fields/util"; -import { UndoManager } from "../../../util/UndoManager"; +import { UndoManager, undoBatch } from "../../../util/UndoManager"; import { Tooltip } from "@material-ui/core"; const { toggleMark } = require("prosemirror-commands"); @@ -831,6 +831,8 @@ export default class RichTextMenu extends AntimodeMenu { ((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRight", "", target); } + @undoBatch + @action deleteLink = () => { if (this.view) { const link = this.view.state.selection.$from.nodeAfter?.marks.find(m => m.type === this.view!.state.schema.marks.linkAnchor); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 2f3b7025e..16ade5912 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -483,25 +483,25 @@ export namespace Doc { return alias; } - - - export function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[]): Doc { + export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[]): Promise { if (Doc.IsBaseProto(doc)) return doc; if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!; const copy = new Doc(undefined, true); cloneMap.set(doc[Id], copy); if (LinkManager.Instance.getAllLinks().includes(doc) && LinkManager.Instance.getAllLinks().indexOf(copy) === -1) LinkManager.Instance.addLink(copy); - const exclude = Cast(doc.excludeFields, listSpec("string"), []); - Object.keys(doc).forEach(key => { - if (exclude.includes(key)) return; + const filter = Cast(doc.cloneFieldFilter, listSpec("string"), exclusions); + Object.keys(doc).forEach(async key => { + if (filter.includes(key)) return; const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const field = ProxyField.WithoutProxy(() => doc[key]); - const copyObjectField = (field: ObjectField) => { - const list = Cast(doc[key], listSpec(Doc)); - if (list !== undefined && !(list instanceof Promise)) { - copy[key] = new List(list.filter(d => d instanceof Doc).map(d => Doc.makeClone(d as Doc, cloneMap, rtfs))); + const copyObjectField = async (field: ObjectField) => { + const list = await Cast(doc[key], listSpec(Doc)); + const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc); + if (docs !== undefined && docs.length) { + const clones = docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions)); + copy[key] = new List(await Promise.all(clones)); } else if (doc[key] instanceof Doc) { - copy[key] = key.includes("layout[") ? undefined : Doc.makeClone(doc[key] as Doc, cloneMap, rtfs); // reference documents except copy documents that are expanded teplate fields + copy[key] = key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions); // reference documents except copy documents that are expanded teplate fields } else { copy[key] = ObjectField.MakeCopy(field); if (field instanceof RichTextField) { @@ -513,7 +513,7 @@ export namespace Doc { }; if (key === "proto") { if (doc[key] instanceof Doc) { - copy[key] = Doc.makeClone(doc[key]!, cloneMap, rtfs); + copy[key] = await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions); } } else { if (field instanceof RefField) { @@ -535,10 +535,10 @@ export namespace Doc { cloneMap.set(doc[Id], copy); return copy; } - export function MakeClone(doc: Doc): Doc { + export async function MakeClone(doc: Doc): Promise { const cloneMap = new Map(); const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = []; - const copy = Doc.makeClone(doc, cloneMap, rtfMap); + const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"]); rtfMap.map(({ copy, key, field }) => { const replacer = (match: any, attr: string, id: string, offset: any, string: any) => { const mapped = cloneMap.get(id); @@ -657,7 +657,7 @@ export namespace Doc { export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc { const copy = new Doc(copyProtoId, true); - const exclude = Cast(doc.excludeFields, listSpec("string"), []); + const exclude = Cast(doc.cloneFieldFilter, listSpec("string"), []); Object.keys(doc).forEach(key => { if (exclude.includes(key)) return; const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); diff --git a/src/server/ApiManagers/DownloadManager.ts b/src/server/ApiManagers/DownloadManager.ts index c5f3ca717..0d4472fdc 100644 --- a/src/server/ApiManagers/DownloadManager.ts +++ b/src/server/ApiManagers/DownloadManager.ts @@ -80,20 +80,14 @@ async function getDocs(id: string) { } const ids: string[] = []; for (const key in doc.fields) { - if (!doc.fields.hasOwnProperty(key)) { - continue; - } + if (!doc.fields.hasOwnProperty(key)) { continue; } const field = doc.fields[key]; - if (field === undefined || field === null) { - continue; - } + if (field === undefined || field === null) { continue; } if (field.__type === "proxy" || field.__type === "prefetch_proxy") { ids.push(field.fieldId); } else if (field.__type === "script" || field.__type === "computed") { - if (field.captures) { - ids.push(field.captures.fieldId); - } + field.captures && ids.push(field.captures.fieldId); } else if (field.__type === "list") { ids.push(...fn(field)); } else if (typeof field === "string") { diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 55ceab9fb..0b9e999ac 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -139,13 +139,9 @@ export default class UploadManager extends ApiManager { doc.id = getId(doc.id); } for (const key in doc.fields) { - if (!doc.fields.hasOwnProperty(key)) { - continue; - } + if (!doc.fields.hasOwnProperty(key)) { continue; } const field = doc.fields[key]; - if (field === undefined || field === null) { - continue; - } + if (field === undefined || field === null) { continue; } if (field.__type === "proxy" || field.__type === "prefetch_proxy") { field.fieldId = getId(field.fieldId); @@ -208,11 +204,7 @@ export default class UploadManager extends ApiManager { } catch (e) { console.log(e); } unlink(path_2, () => { }); } - if (id) { - res.send(JSON.stringify(getId(id))); - } else { - res.send(JSON.stringify("error")); - } + res.send(JSON.stringify(id ? getId(id) : "error")); } catch (e) { console.log(e); } resolve(); }); -- cgit v1.2.3-70-g09d2