From f19dfd26aa3232f2fe52ef5e631be208706fca11 Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Thu, 23 Jul 2020 13:09:37 -0500 Subject: menu buttons to documents --- src/client/views/collections/CollectionTreeView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 96a2e23c9..8d9c4af6e 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -64,6 +64,7 @@ export interface TreeViewProps { onCheckedClick?: () => ScriptField; onChildClick?: () => ScriptField; ignoreFields?: string[]; + alwaysOpen?: boolean; } @observer -- cgit v1.2.3-70-g09d2 From c85adfb7011d5d7a785086e8ea7d389272d80a81 Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Thu, 23 Jul 2020 19:00:37 -0500 Subject: tree view fix --- src/client/util/CurrentUserUtils.ts | 12 ++++++------ src/client/views/collections/CollectionTreeView.tsx | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d41aa4b58..cc9f6aad7 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -696,7 +696,7 @@ export class CurrentUserUtils { doc.myWorkspaces === undefined; if (doc.myWorkspaces === undefined) { doc.myWorkspaces = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, + title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, })); } const newWorkspace = ScriptField.MakeScript(`createNewWorkspace()`); @@ -707,7 +707,7 @@ export class CurrentUserUtils { CurrentUserUtils.workspaceStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces], { title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same" })) as any as Doc; @@ -718,7 +718,7 @@ export class CurrentUserUtils { if (doc.myCatalog === undefined) { doc.myCatalog = new PrefetchProxy(Docs.Create.SchemaDocument([], [], { title: "CATALOG", _height: 1000, _fitWidth: true, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false, - childDropAction: "alias", targetDropAction: "same", stayInCollection: true, + childDropAction: "alias", targetDropAction: "same", stayInCollection: true, treeViewOpen: true, })); } @@ -726,7 +726,7 @@ export class CurrentUserUtils { CurrentUserUtils.catalogStack = new PrefetchProxy(Docs.Create.TreeDocument([catalog], { title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same" })) as any as Doc; @@ -737,7 +737,7 @@ export class CurrentUserUtils { doc.myRecentlyClosed === undefined; if (doc.myRecentlyClosed === undefined) { doc.myRecentlyClosed = new PrefetchProxy(Docs.Create.TreeDocument([], { - title: "RECENTLY CLOSED", _height: 75, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: true, stayInCollection: true, + title: "RECENTLY CLOSED", _height: 75, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false, treeViewOpen: true, stayInCollection: true, })); } // this is equivalent to using PrefetchProxies to make sure the recentlyClosed doc is ready @@ -750,7 +750,7 @@ export class CurrentUserUtils { CurrentUserUtils.closedStack = new PrefetchProxy(Docs.Create.TreeDocument([recentlyClosed], { title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, + treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true, lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same" })) as any as Doc; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c36592c1b..44414fa2b 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -64,7 +64,6 @@ export interface TreeViewProps { onCheckedClick?: () => ScriptField; onChildClick?: () => ScriptField; ignoreFields?: string[]; - alwaysOpen?: boolean; } @observer @@ -91,7 +90,10 @@ class TreeView extends React.Component { get displayName() { return "TreeView(" + this.doc.title + ")"; } // this makes mobx trace() statements more descriptive get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); } @observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state - set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; } + set treeViewOpen(c: boolean) { + if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; + else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; + } @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; } @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.defaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } -- cgit v1.2.3-70-g09d2 From f3f51bb4933cada9ae83594912db10d88082be24 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 30 Jul 2020 10:53:21 -0400 Subject: made 'floatin' document API cleaner. fixed interactions with draggin blue dots off and link lines to link documents. removed Recommndations UI stuff. changed treeView to avoid "No, no, no" error warnin when tryin to render promises --- src/client/documents/DocumentTypes.ts | 1 - src/client/documents/Documents.ts | 9 - src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 1 - src/client/views/RecommendationsBox.scss | 69 ------- src/client/views/RecommendationsBox.tsx | 201 --------------------- src/client/views/TemplateMenu.tsx | 6 +- src/client/views/collections/CollectionMenu.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 33 ++-- src/client/views/nodes/LinkAnchorBox.tsx | 4 +- 13 files changed, 30 insertions(+), 307 deletions(-) delete mode 100644 src/client/views/RecommendationsBox.scss delete mode 100644 src/client/views/RecommendationsBox.tsx (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 7578b7df0..985fcce11 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -36,6 +36,5 @@ export enum DocumentType { LINKDB = "linkdb", // database of links ??? why do we have this SCRIPTDB = "scriptdb", // database of scripts - RECOMMENDATION = "recommendation", // view of a recommendation GROUPDB = "groupdb" // database of groups } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7e094089f..984d43e32 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -45,7 +45,6 @@ import { SliderBox } from "../views/nodes/SliderBox"; import { VideoBox } from "../views/nodes/VideoBox"; import { WebBox } from "../views/nodes/WebBox"; import { PresElementBox } from "../views/presentationview/PresElementBox"; -import { RecommendationsBox } from "../views/RecommendationsBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; import { Networking } from "../Network"; @@ -301,10 +300,6 @@ export namespace Docs { layout: { view: FontIconBox, dataField: defaultDataKey }, options: { _width: 40, _height: 40, borderRounding: "100%" }, }], - [DocumentType.RECOMMENDATION, { - layout: { view: RecommendationsBox, dataField: defaultDataKey }, - options: { _width: 200, _height: 200 }, - }], [DocumentType.WEBCAM, { layout: { view: DashWebRTCVideo, dataField: defaultDataKey } }], @@ -805,10 +800,6 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List(), options); } - export function RecommendationsDocument(data: Doc[], options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List(data), options); - } - export type DocConfig = { doc: Doc, initialWidth?: number, diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 190dbc8c3..51325ae1b 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -89,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); var [sptX, sptY] = transform.transformPoint(0, 0); let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight()); - if (StrCast(Doc.Layout(documentView.props.Document).layout).includes("LinkAnchorBox")) { + if (documentView.props.LayoutTemplateString?.includes("LinkAnchorBox")) { const docuBox = documentView.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); if (docuBox.length) { const rect = docuBox[0].getBoundingClientRect(); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 086085db5..c9f95a538 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -105,7 +105,6 @@ export default class KeyManager { } doDeselect && SelectionManager.DeselectAll(); DictationManager.Controls.stop(); - // RecommendationsBox.Instance.closeMenu(); GoogleAuthenticationManager.Instance.cancel(); HypothesisAuthenticationManager.Instance.cancel(); SharingManager.Instance.close(); diff --git a/src/client/views/RecommendationsBox.scss b/src/client/views/RecommendationsBox.scss deleted file mode 100644 index 7d89042a4..000000000 --- a/src/client/views/RecommendationsBox.scss +++ /dev/null @@ -1,69 +0,0 @@ -@import "globalCssVariables"; - -.rec-content *{ - display: inline-block; - margin: auto; - width: 50; - height: 150px; - border: 1px dashed grey; - padding: 10px 10px; -} - -.rec-content { - float: left; - width: inherit; - align-content: center; -} - -.rec-scroll { - overflow-y: scroll; - overflow-x: hidden; - position: absolute; - pointer-events: all; - // display: flex; - z-index: 10000; - box-shadow: gray 0.2vw 0.2vw 0.4vw; - // flex-direction: column; - background: whitesmoke; - padding-bottom: 10px; - padding-top: 20px; - // border-radius: 15px; - border: solid #BBBBBBBB 1px; - width: 100%; - text-align: center; - // max-height: 250px; - height: 100%; - text-transform: uppercase; - color: grey; - letter-spacing: 2px; -} - -.content { - padding: 10px; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} - -.image-background { - pointer-events: none; - background-color: transparent; - width: 50%; - text-align: center; - margin-left: 5px; -} - -// bcz: UGH!! Can't have global settings like this!!! -// img{ -// width: 100%; -// height: 100%; -// } - -.score { - // margin-left: 15px; - width: 50%; - height: 100%; - text-align: center; - margin-left: 10px; -} diff --git a/src/client/views/RecommendationsBox.tsx b/src/client/views/RecommendationsBox.tsx deleted file mode 100644 index 196151e32..000000000 --- a/src/client/views/RecommendationsBox.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, computed, runInAction } from "mobx"; -import Measure from "react-measure"; -import "./RecommendationsBox.scss"; -import { Doc, DocListCast, WidthSym, HeightSym } from "../../fields/Doc"; -import { DocumentIcon } from "./nodes/DocumentIcon"; -import { StrCast, NumCast } from "../../fields/Types"; -import { returnFalse, emptyFunction, returnEmptyString, returnOne, emptyPath, returnZero, returnEmptyFilter } from "../../Utils"; -import { Transform } from "../util/Transform"; -import { ObjectField } from "../../fields/ObjectField"; -import { DocumentView } from "./nodes/DocumentView"; -import { DocumentType } from '../documents/DocumentTypes'; -import { ClientRecommender } from "../ClientRecommender"; -import { DocServer } from "../DocServer"; -import { Id } from "../../fields/FieldSymbols"; -import { FieldView, FieldViewProps } from "./nodes/FieldView"; -import { DocumentManager } from "../util/DocumentManager"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; -import { DocUtils } from "../documents/Documents"; - -export interface RecProps { - documents: { preview: Doc, similarity: number }[]; - node: Doc; -} - -library.add(faBullseye, faLink); - -@observer -export class RecommendationsBox extends React.Component { - - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecommendationsBox, fieldKey); } - - // @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _width: number = 0; - @observable private _height: number = 0; - @observable.shallow private _docViews: JSX.Element[] = []; - // @observable private _documents: { preview: Doc, score: number }[] = []; - private previewDocs: Doc[] = []; - - constructor(props: FieldViewProps) { - super(props); - } - - @action - private DocumentIcon(doc: Doc) { - const layoutresult = StrCast(doc.type); - let renderDoc = doc; - //let box: number[] = []; - if (layoutresult.indexOf(DocumentType.COL) !== -1) { - renderDoc = Doc.MakeDelegate(renderDoc); - } - const returnXDimension = () => 150; - const returnYDimension = () => 150; - const scale = () => returnXDimension() / NumCast(renderDoc._nativeWidth, returnXDimension()); - //let scale = () => 1; - const newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt - newRenderDoc.height = NumCast(this.props.Document.documentIconHeight); - newRenderDoc.autoHeight = false; - const docview =
- -
; - return docview; - - } - - // @action - // closeMenu = () => { - // this._display = false; - // this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id])); - // this.previewDocs = []; - // } - - // @action - // resetDocuments = () => { - // this._documents = []; - // } - - // @action - // displayRecommendations(x: number, y: number) { - // this._pageX = x; - // this._pageY = y; - // this._display = true; - // } - - static readonly buffer = 20; - - // get pageX() { - // const x = this._pageX; - // if (x < 0) { - // return 0; - // } - // const width = this._width; - // if (x + width > window.innerWidth - RecommendationsBox.buffer) { - // return window.innerWidth - RecommendationsBox.buffer - width; - // } - // return x; - // } - - // get pageY() { - // const y = this._pageY; - // if (y < 0) { - // return 0; - // } - // const height = this._height; - // if (y + height > window.innerHeight - RecommendationsBox.buffer) { - // return window.innerHeight - RecommendationsBox.buffer - height; - // } - // return y; - // } - - // get createDocViews() { - // return DocListCast(this.props.Document.data).map(doc => { - // return ( - //
- // - // {this.DocumentIcon(doc)} - // - // {NumCast(doc.score).toFixed(4)} - //
DocumentManager.Instance.jumpToDocument(doc, false)}> - // - //
- //
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> - // - //
- //
- // ); - // }); - // } - - componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set - runInAction(() => { - if (this._docViews.length === 0) { - this._docViews = DocListCast(this.props.Document.data).map(doc => { - return ( -
- - {this.DocumentIcon(doc)} - - {NumCast(doc.score).toFixed(4)} -
DocumentManager.Instance.jumpToDocument(doc, false)}> - -
-
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "Recommender", "", undefined)}> - -
-
- ); - }); - } - }); - } - - render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered. - // if (!this._display) { - // return null; - // } - // let style = { left: this.pageX, top: this.pageY }; - //const transform = "translate(" + (NumCast(this.props.node.x) + 350) + "px, " + NumCast(this.props.node.y) + "px" - let title = StrCast((this.props.Document.sourceDoc as Doc).title); - if (title.length > 15) { - title = title.substring(0, 15) + "..."; - } - return ( -
-

Recommendations for "{title}"

- {this._docViews} -
- ); - } - // - // -} \ No newline at end of file diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 9fb8a227e..ebaf2cfcb 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -64,11 +64,7 @@ export class TemplateMenu extends React.Component { } toggleFloat = (e: React.ChangeEvent): void => { - SelectionManager.DeselectAll(); - const topDocView = this.props.docViews[0]; - const ex = e.target.getBoundingClientRect().left; - const ey = e.target.getBoundingClientRect().top; - DocumentView.FloatDoc(topDocView, ex, ey); + DocumentView.FloatDoc(this.props.docViews[0]); } toggleAudio = (e: React.ChangeEvent): void => { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index d6cb79e9c..8813861d2 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -313,7 +313,7 @@ export class CollectionViewBaseChrome extends React.Component
{this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.viewModes} - {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome} + {this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome}
-
+
*/} {this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? (null) : ; + // return ; + return null; } render() { return !this.props.docView.layoutDoc ? (null) :
- {this.props.docView.props.renderDepth !== 0 ? (null) : + {this.props.docView.props.renderDepth !== 0 || this.isText ? (null) :
} -
+ {!!!this.isText ?
-
-
: null} + {!!!this.isText ?
this.document.editing = !this.document.editing)} > {NumCast(this.document.currentFrame)} -
-
+
: null} + {!!!this.isText ?
-
+
: null} - {!this.props.isOverlay || this.document.type !== DocumentType.WEB ? (null) : + {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText ? (null) : } - {!this.props.isOverlay || this.props.docView.layoutDoc.isAnnotating ? + {(!this.props.isOverlay || this.props.docView.layoutDoc.isAnnotating) && !this.isText ? <> {this.drawButtons} {this.widthPicker} @@ -566,6 +602,7 @@ export class CollectionFreeFormViewChrome extends React.Component : (null) } + {this.isText ? : null}
; } } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 5553bbbb7..f67e049fd 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -253,7 +253,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
this.typesDropdownChange(!this._openTypes)}> - +
{this._openTypes ? allColumnTypes : justColType}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 425dc90e4..a104ac011 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -227,6 +227,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) addDocTab={this.addDocTab} bringToFront={returnFalse} ContentScaling={returnOne} + scriptContext={this.props.scriptContext} pinToPres={this.props.pinToPres} />; } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 26d2ee8a3..68c233a16 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -351,7 +351,7 @@ export class CollectionStackingViewFieldColumn extends React.Component +
(schemaCtor: (doc: Doc) => T, moreProps?: const reg = new RegExp(Utils.prepend(""), "g"); const modHtml = srcUrl ? html.replace(reg, srcUrl) : html; const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 }); - Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc)["text"] = text; + Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text; this.props.addDocument(htmlDoc); if (srcWeb) { const focusNode = (SelectionManager.SelectedDocuments()[0].ContentDiv?.getElementsByTagName("iframe")[0].contentDocument?.getSelection()?.focusNode as any); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index b8996c178..e5c4b9187 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -90,7 +90,10 @@ class TreeView extends React.Component { get displayName() { return "TreeView(" + this.doc.title + ")"; } // this makes mobx trace() statements more descriptive get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); } @observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state - set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; } + set treeViewOpen(c: boolean) { + if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; + else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; + } @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; } @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.defaultExpandedView); } @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); } @@ -101,7 +104,7 @@ class TreeView extends React.Component { const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined; return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field (layout ? DocListCast(layout[field]) : undefined) || // else if there's a layout doc, display it's fields - DocListCast(this.doc[field])) as Doc[]; // otherwise use the document's data field + DocListCast(this.doc[field])); // otherwise use the document's data field } @computed get childDocs() { return this.childDocList(this.fieldKey); } @computed get childLinks() { return this.childDocList("links"); } diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss index b630f9cf8..a5aef86de 100644 --- a/src/client/views/collections/CollectionView.scss +++ b/src/client/views/collections/CollectionView.scss @@ -24,6 +24,7 @@ border-right: unset; z-index: 2; } + .collectionTimeView-treeView { display: flex; flex-direction: column; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 7e7ea6786..62e8dc26a 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -78,6 +78,7 @@ export interface CollectionViewCustomProps { childLayoutTemplate?: () => Opt; // specify a layout Doc template to use for children of the collection childLayoutString?: string; // specify a layout string to use for children of the collection childOpacity?: () => number; + hideFilter?: true; } export interface CollectionRenderProps { @@ -309,7 +310,7 @@ export class CollectionView extends Touchable this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }); + !Doc.UserDoc().noviceMode ? optionItems.splice(0, 0, { description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }) : null; if (this.props.Document.childLayout instanceof Doc) { optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); } @@ -368,7 +369,7 @@ export class CollectionView extends Touchable this.props.PanelWidth() - this.facetWidth(); + bodyPanelWidth = () => this.props.PanelWidth(); facetWidth = () => Math.max(0, Math.min(this.props.PanelWidth() - 25, this._facetWidth)); @computed get dataDoc() { @@ -490,6 +491,7 @@ export class CollectionView extends Touchable this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0), false); } + filterBackground = () => "rgba(105, 105, 105, 0.432)"; get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } // this makes the tree view collection ignore these filters (otherwise, the filters would filter themselves) @computed get scriptField() { @@ -559,6 +561,7 @@ export class CollectionView extends Touchable
; } + childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null); childLayoutString = this.props.childLayoutString || StrCast(this.props.Document.childLayoutString); @@ -588,11 +591,11 @@ export class CollectionView extends Touchable } - {this.facetWidth() < 10 ? (null) : this.filterView} + {this.facetWidth() < 10 ? (null) : this.filterView} */}
); } } diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 8c0b8de9d..532dd6abc 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -42,14 +42,14 @@ export class SelectorContextMenu extends React.Component { async fetchDocuments() { const aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)); const containerProtoSets = await Promise.all(aliases.map(async alias => - await Promise.all((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs))); + ((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs))); const containerProtos = containerProtoSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set()); const containerSets = await Promise.all(Array.from(containerProtos.keys()).map(async container => { - return (await SearchUtil.GetAliasesOfDocument(container)); + return (SearchUtil.GetAliasesOfDocument(container)); })); const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set()); const doclayoutSets = await Promise.all(Array.from(containers.keys()).map(async (dp) => { - return (await SearchUtil.GetAliasesOfDocument(dp)); + return (SearchUtil.GetAliasesOfDocument(dp)); })); const doclayouts = Array.from(doclayoutSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set()).keys()); runInAction(() => { diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index cde795098..7e2840c2c 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -148,7 +148,7 @@ export class SchemaTable extends React.Component { } @action - changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown; + changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { @@ -208,7 +208,7 @@ export class SchemaTable extends React.Component { }}> {col.heading}
; - const sortIcon = col.desc === undefined ? "circle" : col.desc === true ? "caret-down" : "caret-up"; + const sortIcon = col.desc === undefined ? "caret-right" : col.desc === true ? "caret-down" : "caret-up"; const header =
{ {keysDropdown}
this.changeSorting(col)} - style={{ paddingRight: "6px", display: "inline" }}> + style={{ paddingRight: "6px", marginLeft: "4px", display: "inline" }}>
this.props.openHeader(col, e.clientX, e.clientY)} style={{ float: "right", paddingRight: "6px" }}> - +
; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 151acb64d..109808956 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1145,7 +1145,7 @@ export class CollectionFreeFormView extends CollectionSubView { TraceMobx(); return this.doLayoutComputation }, + this._layoutComputeReaction = reaction(() => this.doLayoutComputation, (elements) => this._layoutElements = elements || [], { fireImmediately: true, name: "doLayout" }); @@ -1240,13 +1240,15 @@ export class CollectionFreeFormView extends CollectionSubView { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" }); appearanceItems.push({ description: `${this.fitToContent ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); - appearanceItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }); + !Doc.UserDoc().noviceMode ? appearanceItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }) : null; !appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" }); const viewctrls = ContextMenu.Instance.findByDescription("UI Controls..."); const viewCtrlItems = viewctrls && "subitems" in viewctrls ? viewctrls.subitems : []; - viewCtrlItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " Snap Lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" }); - viewCtrlItems.push({ description: (this.Document.useClusters ? "Hide" : "Show") + " Clusters", event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }); + + + !Doc.UserDoc().noviceMode ? viewCtrlItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " Snap Lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" }) : null; + !Doc.UserDoc().noviceMode ? viewCtrlItems.push({ description: (this.Document.useClusters ? "Hide" : "Show") + " Clusters", event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }) : null; !viewctrls && ContextMenu.Instance.addItem({ description: "UI Controls...", subitems: viewCtrlItems, icon: "eye" }); const options = ContextMenu.Instance.findByDescription("Options..."); @@ -1291,7 +1293,7 @@ export class CollectionFreeFormView extends CollectionSubView { SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => { docs.docs.forEach(d => LinkManager.Instance.addLink(d)); - }) + }); }, 2000); // need to give solr some time to update so that this query will find any link docs we've added. } } diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx index ddc282e57..6263be261 100644 --- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx +++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx @@ -13,7 +13,6 @@ import AntimodeMenu from "../../AntimodeMenu"; import "./FormatShapePane.scss"; import { undoBatch } from "../../../util/UndoManager"; import { ColorState, SketchPicker } from 'react-color'; -import { DocumentView } from "../../../views/nodes/DocumentView" @observer export default class FormatShapePane extends AntimodeMenu { @@ -124,12 +123,12 @@ export default class FormatShapePane extends AntimodeMenu { console.log(ink); if (ink) { const newPoints: { X: number, Y: number }[] = []; - for (var j = 0; j < ink.length; j++) { + ink.forEach(i => { // (new x — oldx) + (oldxpoint * newWidt)/oldWidth - const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth; - const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight; + const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth; + const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight; newPoints.push({ X: newX, Y: newY }); - } + }); doc.data = new InkField(newPoints); } } @@ -148,12 +147,12 @@ export default class FormatShapePane extends AntimodeMenu { console.log(ink); if (ink) { const newPoints: { X: number, Y: number }[] = []; - for (var j = 0; j < ink.length; j++) { + ink.forEach(i => { // (new x — oldx) + (oldxpoint * newWidt)/oldWidth - const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth; - const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight; + const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth; + const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight; newPoints.push({ X: newX, Y: newY }); - } + }); doc.data = new InkField(newPoints); } } @@ -191,11 +190,11 @@ export default class FormatShapePane extends AntimodeMenu { if (ink) { const newPoints: { X: number, Y: number }[] = []; - for (var i = 0; i < ink.length; i++) { - const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X; - const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y; + ink.forEach(i => { + const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X; + const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y; newPoints.push({ X: newX, Y: newY }); - } + }); doc.data = new InkField(newPoints); const xs = newPoints.map(p => p.X); const ys = newPoints.map(p => p.Y); @@ -395,12 +394,12 @@ export default class FormatShapePane extends AntimodeMenu { @computed get widInput() { return this.inputBox("wid", this.shapeWid, (val: string) => this.shapeWid = val); } @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); } - @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); } @computed get YpsInput() { return this.inputBox("Yps", this.shapeYps, (val: string) => this.shapeYps = val); } @computed get controlPoints() { return this.controlPointsButton(); } @computed get lockRatio() { return this.lockRatioButton(); } @computed get rotate90() { return this.rotate90Button(); } + @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); } @computed get propertyGroupItems() { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss new file mode 100644 index 000000000..74f32275a --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -0,0 +1,620 @@ +.propertiesView { + + background-color: rgb(205, 205, 205); + height: 100%; + font-family: "Noto Sans"; + cursor: auto; + + overflow-x: visible; + overflow-y: visible; + + .propertiesView-title { + background-color: rgb(159, 159, 159); + text-align: center; + padding-top: 12px; + padding-bottom: 12px; + display: flex; + font-size: 18px; + font-weight: bold; + justify-content: center; + + .propertiesView-title-icon { + width: 20px; + height: 20px; + padding-left: 38px; + margin-top: -5px; + right: 19; + position: absolute; + + &:hover { + color: grey; + cursor: pointer; + } + + } + + } + + .propertiesView-name { + border-bottom: 1px solid black; + padding: 8.5px; + font-size: 12.5px; + + &:hover { + cursor: pointer; + } + } + + .propertiesView-settings { + border-bottom: 1px solid black; + //padding: 8.5px; + font-size: 12.5px; + font-weight: bold; + + .propertiesView-settings-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + .propertiesView-settings-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-settings-content { + margin-left: 12px; + padding-bottom: 10px; + padding-top: 8px; + } + + } + + .propertiesView-sharing { + border-bottom: 1px solid black; + //padding: 8.5px; + + .propertiesView-sharing-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + .propertiesView-sharing-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-sharing-content { + font-size: 10px; + padding: 10px; + margin-left: 5px; + } + } + + .propertiesView-appearance { + border-bottom: 1px solid black; + //padding: 8.5px; + + .propertiesView-appearance-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + .propertiesView-appearance-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-appearance-content { + font-size: 10px; + padding: 10px; + margin-left: 5px; + } + } + + .propertiesView-transform { + border-bottom: 1px solid black; + //padding: 8.5px; + + .propertiesView-transform-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + .propertiesView-transform-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-transform-content { + font-size: 10px; + padding: 10px; + margin-left: 5px; + } + } + + .notify-button { + padding: 2px; + width: 12px; + height: 12px; + background-color: black; + border-radius: 10px; + padding-left: 2px; + padding-right: 2px; + margin-top: 2px; + margin-left: 3px; + + .notify-button-icon { + width: 6px; + height: 6.5px; + margin-left: .5px; + } + + &:hover { + background-color: rgb(158, 158, 158); + cursor: pointer; + } + } + + .expansion-button-icon { + width: 11px; + height: 11px; + color: black; + margin-left: 27px; + + &:hover { + color: rgb(131, 131, 131); + cursor: pointer; + } + } + + .propertiesView-sharingTable { + + border: 1px solid black; + padding: 5px; + border-radius: 6px; + /* width: 170px; */ + margin-right: 10px; + background-color: #ececec; + max-height: 130px; + overflow-y: scroll; + + .propertiesView-sharingTable-item { + + display: flex; + padding: 3px; + align-items: center; + border-bottom: 0.5px solid grey; + + &:hover .propertiesView-sharingTable-item-name { + overflow-x: unset; + white-space: unset; + overflow-wrap: break-word; + } + + .propertiesView-sharingTable-item-name { + font-weight: bold; + width: 80px; + overflow-x: hidden; + display: inline-block; + text-overflow: ellipsis; + white-space: nowrap; + } + + .propertiesView-sharingTable-item-permission { + display: flex; + right: 34; + float: right; + position: absolute; + + .permissions-select { + z-index: 1; + border: none; + background-color: inherit; + width: 75px; + text-align: justify; // for Edge + text-align-last: end; + + &:hover { + cursor: pointer; + } + } + } + + &:last-child { + border-bottom: none; + } + } + } + + .propertiesView-fields { + border-bottom: 1px solid black; + //padding: 8.5px; + + .propertiesView-fields-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + .propertiesView-fields-title-name { + font-size: 12.5px; + font-weight: bold; + white-space: nowrap; + width: 35px; + display: flex; + } + + .propertiesView-fields-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-fields-checkbox { + float: right; + height: 20px; + margin-top: -9px; + + .propertiesView-fields-checkbox-text { + font-size: 7px; + margin-top: -10px; + margin-left: 6px; + } + } + + .propertiesView-fields-content { + font-size: 10px; + margin-left: 2px; + padding: 10px; + + &:hover { + cursor: pointer; + } + } + } + + .field { + display: flex; + font-size: 7px; + background-color: #e8e8e8; + padding-right: 3px; + border: 0.5px solid grey; + border-radius: 5px; + padding-left: 3px; + } + + .uneditable-field { + display: flex; + overflow-y: visible; + margin-bottom: 2px; + + &:hover { + cursor: auto; + } + } + + .propertiesView-layout { + + .propertiesView-layout-title { + font-weight: bold; + font-size: 12.5px; + padding: 4px; + display: flex; + color: white; + padding-left: 8px; + background-color: rgb(51, 51, 51); + + .propertiesView-layout-title-icon { + float: right; + right: 0; + position: absolute; + margin-left: 2px; + margin-right: 9px; + + &:hover { + cursor: pointer; + } + } + } + + .propertiesView-layout-content { + overflow: hidden; + padding: 10px; + } + + } +} + +.inking-button { + + display: flex; + + .inking-button-points { + background-color: #333333; + padding: 7px; + border-radius: 7px; + margin-right: 32px; + width: 32; + height: 32; + padding-top: 9px; + margin-left: 18px; + + &:hover { + background: rgb(131, 131, 131); + transform: scale(1.05); + cursor: pointer; + } + } + + .inking-button-lock { + background-color: #333333; + padding: 7px; + border-radius: 7px; + margin-right: 32px; + width: 32; + height: 32; + padding-top: 9px; + padding-left: 10px; + + &:hover { + background: rgb(131, 131, 131); + transform: scale(1.05); + cursor: pointer; + } + } + + .inking-button-rotate { + background-color: #333333; + padding: 7px; + border-radius: 7px; + width: 32; + height: 32; + padding-top: 9px; + padding-left: 10px; + + &:hover { + background: rgb(131, 131, 131); + transform: scale(1.05); + cursor: pointer; + } + } +} + +.inputBox-duo { + display: flex; +} + +.inputBox { + + margin-top: 10px; + display: flex; + height: 19px; + margin-right: 15px; + + .inputBox-title { + font-size: 12px; + padding-right: 5px; + } + + .inputBox-input { + font-size: 10px; + width: 50px; + margin-right: 1px; + border-radius: 3px; + + &:hover { + cursor: pointer; + } + } + + .inputBox-button { + + .inputBox-button-up { + background-color: #333333; + height: 9px; + padding-left: 3px; + padding-right: 3px; + padding-top: 1px; + padding-bottom: 1px; + border-radius: 1.5px; + + &:hover { + background: rgb(131, 131, 131); + transform: scale(1.05); + cursor: pointer; + } + } + + .inputBox-button-down { + background-color: #333333; + height: 9px; + padding-left: 3px; + padding-right: 3px; + padding-top: 1px; + padding-bottom: 1px; + border-radius: 1.5px; + + &:hover { + background: rgb(131, 131, 131); + transform: scale(1.05); + cursor: pointer; + } + } + + } +} + +.color-palette { + width: 160px; + height: 360; +} + +.strokeAndFill { + display: flex; + margin-top: 10px; + + .fill { + margin-right: 40px; + display: flex; + padding-bottom: 7px; + margin-left: 35px; + + .fill-title { + font-size: 12px; + margin-right: 2px; + } + + .fill-button { + padding-top: 2px; + margin-top: -1px; + } + } + + .stroke { + display: flex; + + .stroke-title { + font-size: 12px; + } + + .stroke-button { + padding-top: 2px; + margin-left: 2px; + margin-top: -1px; + } + } +} + +.widthAndDash { + + .width { + .width-top { + display: flex; + + .width-title { + font-size: 12; + margin-right: 20px; + margin-left: 35px; + text-align: center; + } + + .width-input { + margin-right: 30px; + margin-top: -10px; + } + } + + .width-range { + margin-right: 1px; + margin-bottom: 6; + } + } + + .arrows { + + display: flex; + margin-bottom: 3px; + + .arrows-head { + + display: flex; + margin-right: 35px; + + .arrows-head-title { + font-size: 10; + } + + .arrows-head-input { + margin-left: 6px; + margin-top: 2px; + } + } + + .arrows-tail { + display: flex; + + .arrows-tail-title { + font-size: 10; + } + + .arrows-tail-input { + margin-left: 6px; + margin-top: 2px; + } + } + } + + .dashed { + + display: flex; + margin-left: 74px; + margin-bottom: 6px; + + .dashed-title { + font-size: 10; + } + + .dashed-input { + margin-left: 6px; + margin-top: 2px; + } + } +} \ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx new file mode 100644 index 000000000..35c7fd425 --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -0,0 +1,858 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import "./PropertiesView.scss"; +import { observable, action, computed, runInAction } from "mobx"; +import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt } from "../../../../fields/Doc"; +import { DocumentView } from "../../nodes/DocumentView"; +import { ComputedField } from "../../../../fields/ScriptField"; +import { EditableView } from "../../EditableView"; +import { KeyValueBox } from "../../nodes/KeyValueBox"; +import { Cast, NumCast, StrCast } from "../../../../fields/Types"; +import { listSpec } from "../../../../fields/Schema"; +import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView"; +import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils"; +import { Id } from "../../../../fields/FieldSymbols"; +import { Transform } from "../../../util/Transform"; +import { PropertiesButtons } from "../../PropertiesButtons"; +import { SelectionManager } from "../../../util/SelectionManager"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { Tooltip, Checkbox, Divider } from "@material-ui/core"; +import SharingManager from "../../../util/SharingManager"; +import { DocumentType } from "../../../documents/DocumentTypes"; +import FormatShapePane from "./FormatShapePane"; +import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util"; +import { InkField } from "../../../../fields/InkField"; +import { undoBatch } from "../../../util/UndoManager"; +import { ColorState, SketchPicker } from "react-color"; +import AntimodeMenu from "../../AntimodeMenu"; +import "./FormatShapePane.scss"; +import { discovery_v1 } from "googleapis"; +import { PresBox } from "../../nodes/PresBox"; +import { DocumentManager } from "../../../util/DocumentManager"; + + +interface PropertiesViewProps { + width: number; + height: number; + renderDepth: number; + ScreenToLocalTransform: () => Transform; + onDown: (event: any) => void; +} + +@observer +export class PropertiesView extends React.Component { + + @computed get MAX_EMBED_HEIGHT() { return 200; } + + @computed get selectedDocumentView() { + if (SelectionManager.SelectedDocuments().length) { + return SelectionManager.SelectedDocuments()[0]; + } else if (PresBox.Instance) { + const presSlide = PresBox.Instance._selectedArray[0]; + const view = DocumentManager.Instance.getDocumentView(presSlide); + if (view) return view; + } else { return undefined; } + } + @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } + @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; } + + @observable layoutFields: boolean = false; + + @observable openActions: boolean = true; + @observable openSharing: boolean = true; + @observable openFields: boolean = true; + @observable openLayout: boolean = true; + @observable openAppearance: boolean = true; + @observable openTransform: boolean = true; + + @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; } + + @action + rtfWidth = () => { + if (this.selectedDoc) { + return Math.min(this.selectedDoc?.[WidthSym](), this.props.width - 20); + } else { + return 0; + } + } + @action + rtfHeight = () => { + if (this.selectedDoc) { + return this.rtfWidth() <= this.selectedDoc?.[WidthSym]() ? Math.min(this.selectedDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; + } else { + return 0; + } + } + + @action + docWidth = () => { + if (this.selectedDoc) { + const layoutDoc = this.selectedDoc; + const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); + if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20)); + return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20; + } else { + return 0; + } + } + + @action + docHeight = () => { + if (this.selectedDoc && this.dataDoc) { + const layoutDoc = this.selectedDoc; + return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => { + const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]()); + if (aspect) return this.docWidth() * aspect; + return layoutDoc._fitWidth ? (!this.dataDoc._nativeHeight ? NumCast(this.props.height) : + Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth, + NumCast(this.props.height)))) : + NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50; + })())); + } else { + return 0; + } + } + + @computed get expandedField() { + if (this.dataDoc && this.selectedDoc) { + const ids: { [key: string]: string } = {}; + const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc; + doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); + const rows: JSX.Element[] = []; + for (const key of Object.keys(ids).slice().sort()) { + const contents = doc[key]; + if (key[0] === "#") { + rows.push(
+ {key} +   +
); + } else { + let contentElement: (JSX.Element | null)[] | JSX.Element = []; + contentElement = Field.toKeyValueString(doc, key)} + SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)} + />; + rows.push(
+ {key + ":"} +   + {contentElement} +
); + } + } + rows.push(
+ ""} + SetValue={this.setKeyValue} /> +
); + return rows; + } + } + + @computed get noviceFields() { + if (this.dataDoc && this.selectedDoc) { + const ids: { [key: string]: string } = {}; + const doc = this.dataDoc; + doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); + const rows: JSX.Element[] = []; + for (const key of Object.keys(ids).slice().sort()) { + if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) { + const contents = doc[key]; + if (key[0] === "#") { + rows.push(
+ {key} +   +
); + } else { + const value = Field.toString(contents as Field); + if (key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) { + rows.push(
+ {key + ": "} +
{value}
+
); + } else { + let contentElement: (JSX.Element | null)[] | JSX.Element = []; + contentElement = Field.toKeyValueString(doc, key)} + SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)} + />; + + rows.push(
+ {key + ":"} +   + {contentElement} +
); + } + } + } + } + rows.push(
+ ""} + SetValue={this.setKeyValue} /> +
); + return rows; + } + } + + + setKeyValue = (value: string) => { + if (this.selectedDoc && this.dataDoc) { + const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc; + if (value.indexOf(":") !== -1) { + const newVal = value[0].toUpperCase() + value.substring(1, value.length); + KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); + return true; + } else if (value[0] === "#") { + const newVal = value + `:'${value}'`; + KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); + return true; + } + } + return false; + } + + @computed get layoutPreview() { + if (this.selectedDoc) { + const layoutDoc = Doc.Layout(this.selectedDoc); + const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight; + const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth; + return
+ "lightgrey"} + fitToBox={false} + FreezeDimensions={true} + NativeWidth={layoutDoc.type === + StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero} + NativeHeight={layoutDoc.type === + StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero} + PanelWidth={panelWidth} + PanelHeight={panelHeight} + focus={returnFalse} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} + docFilters={returnEmptyFilter} + ContainingCollectionDoc={undefined} + ContainingCollectionView={undefined} + addDocument={returnFalse} + moveDocument={undefined} + removeDocument={returnFalse} + parentActive={() => false} + whenActiveChanged={emptyFunction} + addDocTab={returnFalse} + pinToPres={emptyFunction} + bringToFront={returnFalse} + ContentScaling={returnOne} + dontRegisterView={true} + /> +
; + } else { + return null; + } + } + + getPermissionsSelect(user: string) { + return ; + } + + @computed get notifyIcon() { + return
Notify with message
}> +
+ +
+
; + } + + @computed get expansionIcon() { + return
{"Show more permissions"}
}> +
{ + if (this.selectedDocumentView) { + SharingManager.Instance.open(this.selectedDocumentView); + } + }}> + +
+
; + } + + sharingItem(name: string, effectiveAcl: symbol, permission?: string) { + return
+
{name}
+ {name !== "Me" ? this.notifyIcon : null} +
+ {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission} + {permission === "Owner" ? this.expansionIcon : null} +
+
; + } + + @computed get sharingTable() { + const AclMap = new Map([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit], + [AclAdmin, SharingPermissions.Admin] + ]); + + const effectiveAcl = GetEffectiveAcl(this.selectedDoc!); + const tableEntries = []; + + if (this.selectedDoc![AclSym]) { + for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) { + const name = key.substring(4).replace("_", "."); + if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!)); + } + } + + tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]))); + if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); + + return
+ {tableEntries} +
; + } + + @computed get fieldsCheckbox() { + return ; + } + + @action + toggleCheckbox = () => { + this.layoutFields = !this.layoutFields; + } + + @computed get editableTitle() { + return StrCast(this.selectedDoc?.title)} + SetValue={this.setTitle} />; + } + + @action + setTitle = (value: string) => { + if (this.dataDoc) { + this.selectedDoc && (this.selectedDoc.title = value); + KeyValueBox.SetField(this.dataDoc, "title", value, true); + return true; + } + return false; + } + + + + + + + + + + @undoBatch + @action + rotate = (angle: number) => { + const _centerPoints: { X: number, Y: number }[] = []; + if (this.selectedDoc) { + const doc = this.selectedDoc; + if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { + const ink = Cast(doc.data, InkField)?.inkData; + if (ink) { + const xs = ink.map(p => p.X); + const ys = ink.map(p => p.Y); + const left = Math.min(...xs); + const top = Math.min(...ys); + const right = Math.max(...xs); + const bottom = Math.max(...ys); + _centerPoints.push({ X: left, Y: top }); + } + } + + var index = 0; + if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) { + doc.rotation = Number(doc.rotation) + Number(angle); + const ink = Cast(doc.data, InkField)?.inkData; + if (ink) { + + const newPoints: { X: number, Y: number }[] = []; + for (var i = 0; i < ink.length; i++) { + const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X; + const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y; + newPoints.push({ X: newX, Y: newY }); + } + doc.data = new InkField(newPoints); + const xs = newPoints.map(p => p.X); + const ys = newPoints.map(p => p.Y); + const left = Math.min(...xs); + const top = Math.min(...ys); + const right = Math.max(...xs); + const bottom = Math.max(...ys); + + doc._height = (bottom - top); + doc._width = (right - left); + } + index++; + } + } + } + + @observable _controlBtn: boolean = false; + @observable _lock: boolean = false; + + @computed + get controlPointsButton() { + return
+
{"Edit points"}
}> +
this._controlBtn = !this._controlBtn)} style={{ backgroundColor: this._controlBtn ? "black" : "" }}> + +
+
+
{this._lock ? "Unlock points" : "Lock points"}
}> +
this._lock = !this._lock)} > + +
+
+
{"Rotate 90˚"}
}> +
this.rotate(Math.PI / 2))}> + +
+
+
; + } + + inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => { + return
+
{title}
+ setter(e.target.value)} /> +
+
this.upDownButtons("up", key)))} > + +
+
this.upDownButtons("down", key)))} > + +
+
+
; + } + + inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => { + return
+ {this.inputBox(key, value, setter, title1)} + {title2 === "" ? (null) : this.inputBox(key2, value2, setter2, title2)} +
; + } + + @action + upDownButtons = (dirs: string, field: string) => { + switch (field) { + case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break; + // case "rot": this.selectedInk?.forEach(i => i.rootDoc.rotation = NumCast(i.rootDoc.rotation) + (dirs === "up" ? 0.1 : -0.1)); break; + case "Xps": this.selectedDoc && (this.selectedDoc.x = NumCast(this.selectedDoc?.x) + (dirs === "up" ? 10 : -10)); break; + case "Yps": this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === "up" ? 10 : -10)); break; + case "stk": this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === "up" ? .1 : -.1)); break; + case "wid": + const oldWidth = NumCast(this.selectedDoc?._width); + const oldHeight = NumCast(this.selectedDoc?._height); + const oldX = NumCast(this.selectedDoc?.x); + const oldY = NumCast(this.selectedDoc?.y); + this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === "up" ? 10 : - 10)); + this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height))); + const doc = this.selectedDoc; + if (doc?.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) { + console.log(doc.x, doc.y, doc._height, doc._width); + const ink = Cast(doc.data, InkField)?.inkData; + console.log(ink); + if (ink) { + const newPoints: { X: number, Y: number }[] = []; + for (var j = 0; j < ink.length; j++) { + // (new x — oldx) + (oldxpoint * newWidt)/oldWidth + const newX = (NumCast(doc.x) - oldX) + (ink[j].X * NumCast(doc._width)) / oldWidth; + const newY = (NumCast(doc.y) - oldY) + (ink[j].Y * NumCast(doc._height)) / oldHeight; + newPoints.push({ X: newX, Y: newY }); + } + doc.data = new InkField(newPoints); + } + } + break; + case "hgt": + const oWidth = NumCast(this.selectedDoc?._width); + const oHeight = NumCast(this.selectedDoc?._height); + const oX = NumCast(this.selectedDoc?.x); + const oY = NumCast(this.selectedDoc?.y); + this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === "up" ? 10 : - 10)); + this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width))); + const docu = this.selectedDoc; + if (docu?.type === DocumentType.INK && docu.x && docu.y && docu._height && docu._width) { + console.log(docu.x, docu.y, docu._height, docu._width); + const ink = Cast(docu.data, InkField)?.inkData; + console.log(ink); + if (ink) { + const newPoints: { X: number, Y: number }[] = []; + for (var j = 0; j < ink.length; j++) { + // (new x — oldx) + (oldxpoint * newWidt)/oldWidth + const newX = (NumCast(docu.x) - oX) + (ink[j].X * NumCast(docu._width)) / oWidth; + const newY = (NumCast(docu.y) - oY) + (ink[j].Y * NumCast(docu._height)) / oHeight; + newPoints.push({ X: newX, Y: newY }); + } + docu.data = new InkField(newPoints); + } + } + break; + } + } + + getField(key: string) { + //if (this.selectedDoc) { + return Field.toString(this.selectedDoc[key] as Field); + // } else { + // return undefined as Opt; + // } + } + + @computed get shapeXps() { return this.getField("x"); } + @computed get shapeYps() { return this.getField("y"); } + @computed get shapeRot() { return this.getField("rotation"); } + @computed get shapeHgt() { return this.getField("_height"); } + @computed get shapeWid() { return this.getField("_width"); } + set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Number(value)); } + set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Number(value)); } + set shapeRot(value) { this.selectedDoc && (this.selectedDoc.rotation = Number(value)); } + set shapeWid(value) { + const oldWidth = NumCast(this.selectedDoc?._width); + this.selectedDoc && (this.selectedDoc._width = Number(value)); + this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) * NumCast(this.selectedDoc?._height)) / oldWidth); + } + set shapeHgt(value) { + const oldHeight = NumCast(this.selectedDoc?._height); + this.selectedDoc && (this.selectedDoc._height = Number(value)); + this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight); + } + + @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val, "H:", "wid", this.shapeWid, (val: string) => this.shapeWid = val, "W:"); } + @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); } + @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); } + + @observable private _fillBtn = false; + @observable private _lineBtn = false; + + private _lastFill = "#D0021B"; + private _lastLine = "#D0021B"; + private _lastDash: any = "2"; + + @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; } + @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; } + set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); } + set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); } + + colorButton(value: string, setter: () => {}) { + return
setter()))}> +
+ {value === "" || value === "transparent" ?

: ""} +
; + } + + @undoBatch + @action + switchStk = (color: ColorState) => { + const val = String(color.hex); + this.colorStk = val; + return true; + } + @undoBatch + @action + switchFil = (color: ColorState) => { + const val = String(color.hex); + this.colorFil = val; + return true; + } + + colorPicker(setter: (color: string) => {}, type: string) { + return ; + } + + @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); } + @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); } + + @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); } + @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); } + + @computed get strokeAndFill() { + return
+
+
+
Fill:
+
{this.fillButton}
+
+
+
Stroke:
+
{this.lineButton}
+
+
+ {this._fillBtn ? this.fillPicker : ""} + {this._lineBtn ? this.linePicker : ""} +
; + } + + @computed get solidStk() { return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === "0") ? true : false; } + @computed get dashdStk() { return this.selectedDoc?.strokeDash || ""; } + @computed get unStrokd() { return this.selectedDoc?.color ? true : false; } + @computed get widthStk() { return this.getField("strokeWidth") || "1"; } + @computed get markHead() { return this.getField("strokeStartMarker") || ""; } + @computed get markTail() { return this.getField("strokeEndMarker") || ""; } + set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; } + set dashdStk(value) { + value && (this._lastDash = value) && (this.unStrokd = false); + this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined); + } + set widthStk(value) { this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); } + set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; } + set markHead(value) { this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); } + set markTail(value) { this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); } + + + @computed get stkInput() { return this.regInput("stk", this.widthStk, (val: string) => this.widthStk = val); } + + + regInput = (key: string, value: any, setter: (val: string) => {}) => { + return
+ setter(e.target.value)} /> +
+
this.upDownButtons("up", key)))} > + +
+
this.upDownButtons("down", key)))} > + +
+
+
; + } + + @computed get widthAndDash() { + return
+
+
+
Width:
+
{this.stkInput}
+
+ this.widthStk = e.target.value))} /> +
+ +
+
+
Arrow Head:
+ this.markHead = this.markHead ? "" : "arrow"))} /> +
+
+
Arrow End:
+ this.markTail = this.markTail ? "" : "arrow"))} /> +
+
+
+
Dash:
+ +
+
; + } + + @undoBatch @action + changeDash = () => { + const dash = this.dashdStk; + if (dash === "2") { + this.dashdStk = "0"; + } else { + this.dashdStk = "2"; + } + } + + @computed get appearanceEditor() { + return
+ {this.widthAndDash} + {this.strokeAndFill} +
; + } + + @computed get transformEditor() { + return
+ {this.controlPointsButton} + {this.hgtInput} + {this.XpsInput} + {this.rotInput} +
; + } + + render() { + + if (!this.selectedDoc) { + return
+
+ No Document Selected +
; + } + + const novice = Doc.UserDoc().noviceMode; + + return
+
+ Properties +
+ +
+
+
+ {this.editableTitle} +
+
+
runInAction(() => { this.openActions = !this.openActions; })} + style={{ backgroundColor: this.openActions ? "black" : "" }}> + Actions +
+ +
+
+ {this.openActions ?
+ +
: null} +
+
+
runInAction(() => { this.openSharing = !this.openSharing; })} + style={{ backgroundColor: this.openSharing ? "black" : "" }}> + Sharing {"&"} Permissions +
+ +
+
+ {this.openSharing ?
+ {this.sharingTable} +
: null} +
+ + + + + {this.isInk ?
+
runInAction(() => { this.openAppearance = !this.openAppearance; })} + style={{ backgroundColor: this.openAppearance ? "black" : "" }}> + Appearance +
+ +
+
+ {this.openAppearance ?
+ {this.appearanceEditor} +
: null} +
: null} + + {this.isInk ?
+
runInAction(() => { this.openTransform = !this.openTransform; })} + style={{ backgroundColor: this.openTransform ? "black" : "" }}> + Transform +
+ +
+
+ {this.openTransform ?
+ {this.transformEditor} +
: null} +
: null} + + + + + +
+
runInAction(() => { this.openFields = !this.openFields; })} + style={{ backgroundColor: this.openFields ? "black" : "" }}> +
+ Fields {"&"} Tags +
+ +
+
+
+ {!novice && this.openFields ?
+ {this.fieldsCheckbox} +
Layout
+
: null} + {this.openFields ? +
+ {novice ? this.noviceFields : this.expandedField} +
: null} +
+
+
runInAction(() => { this.openLayout = !this.openLayout; })} + style={{ backgroundColor: this.openLayout ? "black" : "" }}> + Layout +
runInAction(() => { this.openLayout = !this.openLayout; })}> + +
+
+ {this.openLayout ?
{this.layoutPreview}
: null} +
+
; + } +} \ No newline at end of file diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d1c839c3b..0aabf5319 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -182,7 +182,7 @@ export class LinkMenuItem extends React.Component { switch (this.props.destinationDoc.type) { case DocumentType.IMG: destinationIcon = "image"; break; case DocumentType.COMPARISON: destinationIcon = "columns"; break; - case DocumentType.RTF: destinationIcon = "font"; break; + case DocumentType.RTF: destinationIcon = "sticky-note"; break; case DocumentType.COL: destinationIcon = "folder"; break; case DocumentType.WEB: destinationIcon = "globe-asia"; break; case DocumentType.SCREENSHOT: destinationIcon = "photo-video"; break; @@ -196,6 +196,7 @@ export class LinkMenuItem extends React.Component { case DocumentType.DOCHOLDER: destinationIcon = "expand"; break; case DocumentType.VID: destinationIcon = "video"; break; case DocumentType.INK: destinationIcon = "pen-nib"; break; + case DocumentType.PDF: destinationIcon = "file"; break; default: destinationIcon = "question"; break; } diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 6081def5d..f7e253f42 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -78,6 +78,9 @@ export class ContentFittingDocumentView extends React.Component 0.001 ? "auto" : this.props.PanelWidth(), height: Math.abs(this.centeringOffset) > 0.0001 ? "auto" : this.props.PanelHeight(), diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index e8173d103..e3f258b8d 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -18,6 +18,7 @@ import { DocHolderBox } from "./DocHolderBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { FontIconBox } from "./FontIconBox"; +import { MenuIconBox } from "./MenuIconBox"; import { FieldView, FieldViewProps } from "./FieldView"; import { FormattedTextBox } from "./formattedText/FormattedTextBox"; import { ImageBox } from "./ImageBox"; @@ -189,7 +190,7 @@ export class DocumentContentsView extends React.Component + {/* {this.props.InMenu ? this.props.StartLink ? : + : links.length} */} + {this.props.InMenu ? this.props.StartLink ? : - : links.length} + link : links.length}
{DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
(Docu } onClick = action((e: React.MouseEvent | React.PointerEvent) => { - if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && + if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && this.props.renderDepth >= 0 && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { let stopPropagate = true; let preventDefault = true; @@ -319,10 +321,11 @@ export class DocumentView extends DocComponent(Docu const func = () => this.onClickHandler.script.run({ this: this.layoutDoc, self: this.rootDoc, + scriptContext: this.props.scriptContext, thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey }, console.log); - if (this.props.Document !== Doc.UserDoc()["dockedBtn-undo"] && this.props.Document !== Doc.UserDoc()["dockedBtn-redo"]) { + if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) { UndoManager.RunInBatch(func, "on click"); } else func(); } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself @@ -584,6 +587,18 @@ export class DocumentView extends DocComponent(Docu } } + + @undoBatch + noOnClick = (): void => { + this.Document.ignoreClick = false; + this.Document.isLinkButton = false; + } + + @undoBatch + toggleDetail = (): void => { + this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`); + } + @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { if (this.props.Document === Doc.UserDoc().activeWorkspace) { @@ -660,6 +675,14 @@ export class DocumentView extends DocComponent(Docu } } + @action + onCopy = () => { + const copy = Doc.MakeCopy(this.props.Document, true); + copy.x = NumCast(this.props.Document.x) + NumCast(this.props.Document._width); + copy.y = NumCast(this.props.Document.y) + 30; + this.props.addDocument?.(copy); + } + @action onContextMenu = async (e: React.MouseEvent | Touch): Promise => { // the touch onContextMenu is button 0, the pointer onContextMenu is button 2 @@ -704,14 +727,14 @@ export class DocumentView extends DocComponent(Docu const existingOnClick = cm.findByDescription("OnClick..."); const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); - onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "window-restore" }); + onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); - onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "concierge-bell" }); - !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "concierge-bell" }); - onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "concierge-bell" }); - onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "snowflake" }); - onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" }); - !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, addDivider: true, subitems: onClicks, icon: "hand-point-right" }); + onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); + !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "link" }); + onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" }); + onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" }); + onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" }); + !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); const funcs: ContextMenuProps[] = []; if (this.layoutDoc.onDragStart) { @@ -724,6 +747,9 @@ export class DocumentView extends DocComponent(Docu const more = cm.findByDescription("More..."); const moreItems = more && "subitems" in more ? more.subitems : []; moreItems.push({ description: "Download document", icon: "download", event: async () => Doc.Zip(this.props.Document) }); + moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "users" }); + //moreItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); + moreItems.push({ description: "Create an Alias", event: () => this.onCopy(), icon: "copy" }); if (!Doc.UserDoc().noviceMode) { moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" }); moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); @@ -735,16 +761,18 @@ export class DocumentView extends DocComponent(Docu } moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); } + //GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" }); + const effectiveAcl = GetEffectiveAcl(this.props.Document); (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" }); - moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "external-link-alt" }); + !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!); const help = cm.findByDescription("Help..."); const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : []; + !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "onRight"), icon: "keyboard" }); - helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" }); cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); @@ -786,8 +814,9 @@ export class DocumentView extends DocComponent(Docu childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling()); @computed.struct get linkOffset() { return [-15, 0]; } @computed get contents() { + const pos = this.props.relative ? "relative " : "absolute"; TraceMobx(); - return (
+ return (
(Docu ChromeHeight={this.chromeHeight} isSelected={this.isSelected} select={this.select} + scriptContext={this.props.scriptContext} onClick={this.onClickFunc} layoutKey={this.finalLayoutKey} /> {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors} @@ -877,8 +907,12 @@ export class DocumentView extends DocComponent(Docu } @computed get innards() { TraceMobx(); + const pos = this.props.relative ? "relative" : undefined; if (this.props.treeViewDoc && !this.props.LayoutTemplateString?.includes("LinkAnchorBox")) { // this happens when the document is a tree view label (but not an anchor dot) - return
+ return
{StrCast(this.props.Document.title)} {this.allAnchors}
; @@ -1003,7 +1037,7 @@ export class DocumentView extends DocComponent(Docu background: finalColor, opacity: finalOpacity, fontFamily: StrCast(this.Document._fontFamily, "inherit"), - fontSize: Cast(this.Document._fontSize, "string", null) + fontSize: Cast(this.Document._fontSize, "string", null), }}> {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <> {this.innards} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5d5bc1d73..1b4151bd8 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -61,6 +61,7 @@ export interface FieldViewProps { color?: string; xMargin?: number; yMargin?: number; + scriptContext?: any; } @observer diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss index 5b85d8b0b..69c835318 100644 --- a/src/client/views/nodes/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox.scss @@ -16,7 +16,7 @@ position: absolute; text-align: center; font-size: 8px; - margin-top:4px; + //margin-top:4px; letter-spacing: normal; left: 0; overflow: hidden; diff --git a/src/client/views/nodes/MenuIconBox.scss b/src/client/views/nodes/MenuIconBox.scss new file mode 100644 index 000000000..1b72f5a8f --- /dev/null +++ b/src/client/views/nodes/MenuIconBox.scss @@ -0,0 +1,49 @@ +.menuButton { + //padding: 7px; + padding-left: 7px; + width: 100%; + width: 60px; + height: 70px; + + .menuButton-wrap { + width: 45px; + /* padding: 5px; */ + touch-action: none; + background: black; + transform-origin: top left; + /* margin-bottom: 5px; */ + margin-top: 5px; + margin-right: 25px; + border-radius: 8px; + + &:hover { + background: rgb(61, 61, 61); + cursor: pointer; + } + } + + .menuButton-label { + color: white; + margin-right: 4px; + border-radius: 8px; + width: 42px; + position: relative; + text-align: center; + font-size: 8px; + margin-top: 1px; + letter-spacing: normal; + padding: 3px; + background-color: inherit; + } + + .menuButton-icon { + width: auto; + height: 35px; + padding: 5px; + } + + svg { + width: 95% !important; + height: 95%; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/MenuIconBox.tsx b/src/client/views/nodes/MenuIconBox.tsx new file mode 100644 index 000000000..0aa7b327e --- /dev/null +++ b/src/client/views/nodes/MenuIconBox.tsx @@ -0,0 +1,33 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { createSchema, makeInterface } from '../../../fields/Schema'; +import { StrCast } from '../../../fields/Types'; +import { DocComponent } from '../DocComponent'; +import { FieldView, FieldViewProps } from './FieldView'; +import './MenuIconBox.scss'; +const MenuIconSchema = createSchema({ + icon: "string" +}); + +type MenuIconDocument = makeInterface<[typeof MenuIconSchema]>; +const MenuIconDocument = makeInterface(MenuIconSchema); +@observer +export class MenuIconBox extends DocComponent(MenuIconDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MenuIconBox, fieldKey); } + _ref: React.RefObject = React.createRef(); + + render() { + + const color = this.props.backgroundColor?.(this.props.Document) === "lightgrey" ? "black" : "white"; + const menuBTN =
+
+ +
{this.dataDoc.title}
+
+
; + + return menuBTN; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index c04c6c409..97f223c02 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -32,6 +32,7 @@ import { conformsTo } from "lodash"; import { translate } from "googleapis/build/src/apis/translate"; import { DragManager, dropActionType } from "../../util/DragManager"; import { actionAsync } from "mobx-utils"; +import { SelectionManager } from "../../util/SelectionManager"; type PresBoxSchema = makeInterface<[typeof documentSchema]>; const PresBoxDocument = makeInterface(documentSchema); @@ -260,7 +261,7 @@ export class PresBox extends ViewBoxBaseComponent const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); const srcContext = await DocCastAsync(targetDoc.context); const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); - const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined; + const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined; if (this.itemIndex >= 0) { if (targetDoc) { if (srcContext) this.layoutDoc.presCollection = srcContext; @@ -496,6 +497,8 @@ export class PresBox extends ViewBoxBaseComponent selectElement = (doc: Doc) => { // this._selectedArray = []; this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex)); + const view = DocumentManager.Instance.getDocumentView(doc); + view && SelectionManager.SelectDoc(view, false); // this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); // console.log(this._selectedArray); } @@ -504,8 +507,9 @@ export class PresBox extends ViewBoxBaseComponent @action multiSelect = (doc: Doc, ref: HTMLElement) => { this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); - const ele = ref.getElementsByClassName("stacking"); this._eleArray.push(ref); + const view = DocumentManager.Instance.getDocumentView(doc); + view && SelectionManager.SelectDoc(view, true); } //Shift click @@ -517,6 +521,8 @@ export class PresBox extends ViewBoxBaseComponent for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) { this._selectedArray.push(this.childDocs[i]); this._eleArray.push(ref); + const view = DocumentManager.Instance.getDocumentView(doc); + view && SelectionManager.SelectDoc(view, true); } } } diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index 958a37568..8ae71c035 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -190,7 +190,7 @@ export class DashFieldViewInternal extends React.Component c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, "#f1efeb")); list.map(c => c.heading).indexOf("text") === -1 && list.push(new SchemaHeaderField("text", "#f1efeb")); - alias._pivotField = this._fieldKey; + alias._pivotField = this._fieldKey.startsWith("#") ? "#" : this._fieldKey; this.props.tbox.props.addDocTab(alias, "onRight"); } } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 627c6e363..fc65f34eb 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1267,7 +1267,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.doLinkOnDeselect(); // move the richtextmenu offscreen - if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.delayHide(); + //if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.delayHide(); } _lastTimedMark: Mark | undefined = undefined; @@ -1346,7 +1346,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); } render() { TraceMobx(); - const scale = this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1); + const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground; setTimeout(() => this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props), this.props.isSelected() ? 10 : 0); // need to make sure that we update a text box that is selected after updating the one that was deselected diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 7ccbfa051..f76707a79 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -77,7 +77,8 @@ export default class RichTextMenu extends AntimodeMenu { super(props); RichTextMenu.Instance = this; this._canFade = false; - this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]); + //this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]); + this.Pinned = true; this.fontSizeOptions = [ { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize }, @@ -529,7 +530,7 @@ export default class RichTextMenu extends AntimodeMenu { indentParagraph(state: EditorState, dispatch: any) { var tr = state.tr; - let headin = false; + const heading = false; state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => { if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) { const nodeval = node.attrs.indent ? Number(node.attrs.indent) : undefined; @@ -539,7 +540,7 @@ export default class RichTextMenu extends AntimodeMenu { } return true; }); - !headin && dispatch?.(tr); + !heading && dispatch?.(tr); return true; } @@ -920,16 +921,22 @@ export default class RichTextMenu extends AntimodeMenu { render() { TraceMobx(); const row1 =
{[ - !this.collapsed ? this.getDragger() : (null), - !this.Pinned ? (null) :
{[ - this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)), - this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)), - this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)), - this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)), - this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)), - this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)), -
- ]}
, + //!this.collapsed ? this.getDragger() : (null), + // !this.Pinned ? (null) :
{[ + // this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)), + // this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)), + // this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)), + // this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)), + // this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)), + // this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)), + //
+ // ]}
, + this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)), + this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)), + this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)), + this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)), + this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)), + this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)), this.createColorButton(), this.createHighlighterButton(), this.createLinkButton(), @@ -957,16 +964,16 @@ export default class RichTextMenu extends AntimodeMenu { this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule),
,]}
-
- {/*
+ {/*
+ {
-
*/} +
} -
+
*/}
; return ( diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index 0eca6d753..1616500f6 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -79,14 +79,14 @@ export const nodes: { [index: string]: NodeSpec } = { { tag: "h5", attrs: { level: 5 } }, { tag: "h6", attrs: { level: 6 } }], toDOM(node) { - var dom = toParagraphDOM(node) as any; - var level = node.attrs.level || 1; + const dom = toParagraphDOM(node) as any; + const level = node.attrs.level || 1; dom[0] = 'h' + level; return dom; }, getAttrs(dom: any) { - var attrs = getParagraphNodeAttrs(dom) as any; - var level = Number(dom.nodeName.substring(1)) || 1; + const attrs = getParagraphNodeAttrs(dom) as any; + const level = Number(dom.nodeName.substring(1)) || 1; attrs.level = level; return attrs; } diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 43e74ff61..85fc63074 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -528,10 +528,10 @@ export namespace Doc { const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const field = ProxyField.WithoutProxy(() => doc[key]); const copyObjectField = async (field: ObjectField) => { - const list = await Cast(doc[key], listSpec(Doc)); + const list = Cast(doc[key], listSpec(Doc)); const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc); if (docs !== undefined && docs.length) { - const clones = await Promise.all(docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions, dontCreate))); + const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, rtfs, exclusions, dontCreate))); !dontCreate && assignKey(new List(clones)); } else if (doc[key] instanceof Doc) { assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions, dontCreate)); // reference documents except copy documents that are expanded teplate fields @@ -625,7 +625,7 @@ export namespace Doc { Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]); const docString = JSON.stringify({ id: doc[Id], docs }, replacer); - var zip = new JSZip(); + const zip = new JSZip(); zip.file(doc.title + ".json", docString); diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts index 60f66c878..fd9bc0c83 100644 --- a/src/server/ActionUtilities.ts +++ b/src/server/ActionUtilities.ts @@ -1,11 +1,11 @@ -import { readFile, writeFile, exists, mkdir, unlink, createWriteStream } from 'fs'; -import { ExecOptions } from 'shelljs'; import { exec } from 'child_process'; -import * as path from 'path'; -import * as rimraf from "rimraf"; -import { yellow, Color } from 'colors'; +import { Color, yellow } from 'colors'; +import { createWriteStream, exists, mkdir, readFile, unlink, writeFile } from 'fs'; import * as nodemailer from "nodemailer"; import { MailOptions } from "nodemailer/lib/json-transport"; +import * as path from 'path'; +import * as rimraf from "rimraf"; +import { ExecOptions } from 'shelljs'; import Mail = require('nodemailer/lib/mailer'); const projectRoot = path.resolve(__dirname, "../../"); diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts index e2cd88726..e657866ce 100644 --- a/src/server/ApiManagers/UtilManager.ts +++ b/src/server/ApiManagers/UtilManager.ts @@ -6,7 +6,6 @@ import { exec } from 'child_process'; // const recommender = new Recommender(); // recommender.testModel(); -import executeImport from "../../scraping/buxton/final/BuxtonImporter"; export default class UtilManager extends ApiManager { diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 2bf4c1956..890fb6f6d 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -1,23 +1,22 @@ -import { unlinkSync, createWriteStream, readFileSync, rename, writeFile, existsSync } from 'fs'; -import { Utils } from '../Utils'; -import * as path from 'path'; -import * as sharp from 'sharp'; -import request = require('request-promise'); +import { red } from 'colors'; import { ExifImage } from 'exif'; -import { Opt } from '../fields/Doc'; -import { AcceptibleMedia, Upload } from './SharedMediaTypes'; -import { filesDirectory, publicDirectory } from '.'; import { File } from 'formidable'; +import { createWriteStream, existsSync, readFileSync, rename, unlinkSync, writeFile } from 'fs'; +import * as path from 'path'; import { basename } from "path"; -import { createIfNotExists } from './ActionUtilities'; +import * as sharp from 'sharp'; +import { Stream } from 'stream'; +import { filesDirectory, publicDirectory } from '.'; +import { Opt } from '../fields/Doc'; import { ParsedPDF } from "../server/PdfTypes"; +import { Utils } from '../Utils'; +import { createIfNotExists } from './ActionUtilities'; +import { clientPathToFile, Directory, pathToDirectory, serverPathToFile } from './ApiManagers/UploadManager'; +import { resolvedServerUrl } from "./server_Initialization"; +import { AcceptibleMedia, Upload } from './SharedMediaTypes'; +import request = require('request-promise'); const parse = require('pdf-parse'); -import { Directory, serverPathToFile, clientPathToFile, pathToDirectory } from './ApiManagers/UploadManager'; -import { red } from 'colors'; -import { Stream } from 'stream'; -import { resolvedPorts } from './server_Initialization'; const requestImageSize = require("../client/util/request-image-size"); -import { resolvedServerUrl } from "./server_Initialization"; export enum SizeSuffix { Small = "_s", diff --git a/src/server/GarbageCollector.ts b/src/server/GarbageCollector.ts index 24745cbb4..a9a3b0481 100644 --- a/src/server/GarbageCollector.ts +++ b/src/server/GarbageCollector.ts @@ -1,9 +1,9 @@ -import { Database } from './database'; - -import * as path from 'path'; import * as fs from 'fs'; +import * as path from 'path'; +import { Database } from './database'; import { Search } from './Search'; + function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) { for (const key in doc) { if (!doc.hasOwnProperty(key)) { diff --git a/src/server/MemoryDatabase.ts b/src/server/MemoryDatabase.ts index 1f1d702d9..7f477327e 100644 --- a/src/server/MemoryDatabase.ts +++ b/src/server/MemoryDatabase.ts @@ -1,6 +1,7 @@ -import { IDatabase, DocumentsCollection } from './IDatabase'; -import { Transferable } from './Message'; +import { DH_CHECK_P_NOT_SAFE_PRIME } from 'constants'; import * as mongodb from 'mongodb'; +import { DocumentsCollection, IDatabase } from './IDatabase'; +import { Transferable } from './Message'; export class MemoryDatabase implements IDatabase { diff --git a/src/server/Message.ts b/src/server/Message.ts index ff0381fd3..59b24cd82 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -1,6 +1,6 @@ -import { Utils } from "../Utils"; import { Point } from "../pen-gestures/ndollar"; import { AnalysisResult, ImportResults } from "../scraping/buxton/final/BuxtonImporter"; +import { Utils } from "../Utils"; export class Message { private _name: string; diff --git a/src/server/ProcessFactory.ts b/src/server/ProcessFactory.ts index acb8b3a99..63682368f 100644 --- a/src/server/ProcessFactory.ts +++ b/src/server/ProcessFactory.ts @@ -1,8 +1,8 @@ -import { existsSync, mkdirSync } from "fs"; -import { pathFromRoot, fileDescriptorFromStream } from './ActionUtilities'; -import rimraf = require("rimraf"); import { ChildProcess, spawn, StdioOptions } from "child_process"; +import { existsSync, mkdirSync } from "fs"; import { Stream } from "stream"; +import { fileDescriptorFromStream, pathFromRoot } from './ActionUtilities'; +import rimraf = require("rimraf"); export namespace ProcessFactory { diff --git a/src/server/Recommender.ts b/src/server/Recommender.ts deleted file mode 100644 index 935ec3871..000000000 --- a/src/server/Recommender.ts +++ /dev/null @@ -1,133 +0,0 @@ -// //import { Doc } from "../fields/Doc"; -// //import { StrCast } from "../fields/Types"; -// //import { List } from "../fields/List"; -// //import { CognitiveServices } from "../client/cognitive_services/CognitiveServices"; - -// // var w2v = require('word2vec'); -// var assert = require('assert'); -// var arxivapi = require('arxiv-api-node'); -// import requestPromise = require("request-promise"); -// import * as use from '@tensorflow-models/universal-sentence-encoder'; -// import { Tensor } from "@tensorflow/tfjs-core/dist/tensor"; -// require('@tensorflow/tfjs-node'); - -// //http://gnuwin32.sourceforge.net/packages/make.htm - -// export class Recommender { - -// private _model: any; -// static Instance: Recommender; -// private dimension: number = 0; -// private choice: string = ""; // Tensorflow or Word2Vec - -// constructor() { -// Recommender.Instance = this; -// } - -// /*** -// * Loads pre-trained model from TF -// */ - -// public async loadTFModel() { -// let self = this; -// return new Promise(res => { -// use.load().then(model => { -// self.choice = "TF"; -// self._model = model; -// self.dimension = 512; -// res(model); -// }); -// } - -// ); -// } - -// /*** -// * Loads pre-trained model from word2vec -// */ - -// // private loadModel(): Promise { -// // let self = this; -// // return new Promise(res => { -// // w2v.loadModel("./node_modules/word2vec/examples/fixtures/vectors.txt", function (err: any, model: any) { -// // self.choice = "WV"; -// // self._model = model; -// // self.dimension = model.size; -// // res(model); -// // }); -// // }); -// // } - -// /*** -// * Testing -// */ - -// public async testModel() { -// if (!this._model) { -// await this.loadTFModel(); -// } -// if (this._model) { -// if (this.choice === "WV") { -// let similarity = this._model.similarity('father', 'mother'); -// } -// else if (this.choice === "TF") { -// const model = this._model as use.UniversalSentenceEncoder; -// // Embed an array of sentences. -// const sentences = [ -// 'Hello.', -// 'How are you?' -// ]; -// const embeddings = await this.vectorize(sentences); -// if (embeddings) embeddings.print(true /*verbose*/); -// // model.embed(sentences).then(embeddings => { -// // // `embeddings` is a 2D tensor consisting of the 512-dimensional embeddings for each sentence. -// // // So in this example `embeddings` has the shape [2, 512]. -// // embeddings.print(true /* verbose */); -// // }); -// } -// } -// else { -// console.log("model not found :("); -// } -// } - -// /*** -// * Uses model to convert words to vectors -// */ - -// public async vectorize(text: string[]): Promise { -// if (!this._model) { -// await this.loadTFModel(); -// } -// if (this._model) { -// if (this.choice === "WV") { -// let word_vecs = this._model.getVectors(text); -// return word_vecs; -// } -// else if (this.choice === "TF") { -// const model = this._model as use.UniversalSentenceEncoder; -// return new Promise(res => { -// model.embed(text).then(embeddings => { -// res(embeddings); -// }); -// }); - -// } -// } -// } - -// // public async trainModel() { -// // w2v.word2vec("./node_modules/word2vec/examples/eng_news-typical_2016_1M-sentences.txt", './node_modules/word2vec/examples/my_phrases.txt', { -// // cbow: 1, -// // size: 200, -// // window: 8, -// // negative: 25, -// // hs: 0, -// // sample: 1e-4, -// // threads: 20, -// // iter: 200, -// // minCount: 2 -// // }); -// // } - -// } diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index 1a2340afc..78b75d6be 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -1,8 +1,8 @@ -import RouteSubscriber from "./RouteSubscriber"; -import { DashUserModel } from "./authentication/DashUserModel"; -import { Request, Response, Express } from 'express'; -import { cyan, red, green } from 'colors'; +import { cyan, green, red } from 'colors'; +import { Express, Request, Response } from 'express'; import { AdminPriviliges } from "."; +import { DashUserModel } from "./authentication/DashUserModel"; +import RouteSubscriber from "./RouteSubscriber"; export enum Method { GET, diff --git a/src/server/Search.ts b/src/server/Search.ts index 21064e520..decd1f5b1 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -1,5 +1,5 @@ -import * as rp from 'request-promise'; import { red } from 'colors'; +import * as rp from 'request-promise'; const pathTo = (relative: string) => `http://localhost:8983/solr/dash/${relative}`; diff --git a/src/server/database.ts b/src/server/database.ts index 2372cbcf2..b7aa77f5d 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -1,11 +1,11 @@ import * as mongodb from 'mongodb'; -import { Transferable } from './Message'; +import * as mongoose from 'mongoose'; import { Opt } from '../fields/Doc'; -import { Utils, emptyFunction } from '../Utils'; +import { emptyFunction, Utils } from '../Utils'; import { GoogleApiServerUtils } from './apis/google/GoogleApiServerUtils'; -import { IDatabase, DocumentsCollection } from './IDatabase'; +import { DocumentsCollection, IDatabase } from './IDatabase'; import { MemoryDatabase } from './MemoryDatabase'; -import * as mongoose from 'mongoose'; +import { Transferable } from './Message'; import { Upload } from './SharedMediaTypes'; export namespace Database { diff --git a/src/server/downsize.ts b/src/server/downsize.ts index 5cd709fa3..382994e2d 100644 --- a/src/server/downsize.ts +++ b/src/server/downsize.ts @@ -1,5 +1,5 @@ -import * as sharp from 'sharp'; import * as fs from 'fs'; +import * as sharp from 'sharp'; const folder = "./src/server/public/files/"; const pngTypes = ["png", "PNG"]; diff --git a/src/server/index.ts b/src/server/index.ts index 9af4b00bc..9185e3c5e 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,29 +1,29 @@ require('dotenv').config(); -import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils"; +import { yellow } from "colors"; import * as mobileDetect from 'mobile-detect'; import * as path from 'path'; -import { Database } from './database'; -import { DashUploadUtils } from './DashUploadUtils'; -import RouteSubscriber from './RouteSubscriber'; -import initializeServer, { resolvedPorts } from './server_Initialization'; -import RouteManager, { Method, _success, _permission_denied, _error, _invalid, PublicHandler } from './RouteManager'; import * as qs from 'query-string'; -import UtilManager from './ApiManagers/UtilManager'; -import { SearchManager } from './ApiManagers/SearchManager'; -import UserManager from './ApiManagers/UserManager'; -import DownloadManager from './ApiManagers/DownloadManager'; -import { GoogleCredentialsLoader, SSL } from './apis/google/CredentialsLoader'; -import DeleteManager from "./ApiManagers/DeleteManager"; -import PDFManager from "./ApiManagers/PDFManager"; -import UploadManager from "./ApiManagers/UploadManager"; import { log_execution } from "./ActionUtilities"; +import DeleteManager from "./ApiManagers/DeleteManager"; +import DownloadManager from './ApiManagers/DownloadManager'; import GeneralGoogleManager from "./ApiManagers/GeneralGoogleManager"; -import HypothesisManager from "./ApiManagers/HypothesisManager"; import GooglePhotosManager from "./ApiManagers/GooglePhotosManager"; -import { Logger } from "./ProcessFactory"; -import { yellow } from "colors"; +import HypothesisManager from "./ApiManagers/HypothesisManager"; +import PDFManager from "./ApiManagers/PDFManager"; +import { SearchManager } from './ApiManagers/SearchManager'; import SessionManager from "./ApiManagers/SessionManager"; +import UploadManager from "./ApiManagers/UploadManager"; +import UserManager from './ApiManagers/UserManager'; +import UtilManager from './ApiManagers/UtilManager'; +import { GoogleCredentialsLoader, SSL } from './apis/google/CredentialsLoader'; +import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils"; import { AppliedSessionAgent } from "./DashSession/Session/agents/applied_session_agent"; +import { DashUploadUtils } from './DashUploadUtils'; +import { Database } from './database'; +import { Logger } from "./ProcessFactory"; +import RouteManager, { Method, PublicHandler } from './RouteManager'; +import RouteSubscriber from './RouteSubscriber'; +import initializeServer, { resolvedPorts } from './server_Initialization'; export const AdminPriviliges: Map = new Map(); export const onWindows = process.platform === "win32"; diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 744d4547b..e40f2b8e5 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -1,31 +1,31 @@ +import * as bodyParser from 'body-parser'; +import { blue, yellow } from 'colors'; +import * as cookieParser from 'cookie-parser'; +import * as cors from "cors"; import * as express from 'express'; -import * as expressValidator from 'express-validator'; import * as session from 'express-session'; +import * as expressValidator from 'express-validator'; +import * as fs from 'fs'; +import { Server as HttpServer } from "http"; +import { createServer, Server as HttpsServer } from "https"; import * as passport from 'passport'; -import * as bodyParser from 'body-parser'; -import * as cookieParser from 'cookie-parser'; -import expressFlash = require('express-flash'); -import flash = require('connect-flash'); -import { Database } from './database'; -import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/AuthenticationManager'; -const MongoStore = require('connect-mongo')(session); -import RouteManager from './RouteManager'; -import { WebSocket } from './websocket'; +import * as request from 'request'; import * as webpack from 'webpack'; -const config = require('../../webpack.config'); -const compiler = webpack(config); import * as wdm from 'webpack-dev-middleware'; import * as whm from 'webpack-hot-middleware'; -import * as fs from 'fs'; -import * as request from 'request'; -import RouteSubscriber from './RouteSubscriber'; import { publicDirectory } from '.'; import { logPort } from './ActionUtilities'; -import { blue, yellow } from 'colors'; -import * as cors from "cors"; -import { createServer, Server as HttpsServer } from "https"; -import { Server as HttpServer } from "http"; import { SSL } from './apis/google/CredentialsLoader'; +import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/AuthenticationManager'; +import { Database } from './database'; +import RouteManager from './RouteManager'; +import RouteSubscriber from './RouteSubscriber'; +import { WebSocket } from './websocket'; +import expressFlash = require('express-flash'); +import flash = require('connect-flash'); +const MongoStore = require('connect-mongo')(session); +const config = require('../../webpack.config'); +const compiler = webpack(config); /* RouteSetter is a wrapper around the server that prevents the server from being exposed. */ diff --git a/src/server/websocket.ts b/src/server/websocket.ts index f63a35e43..d5f89a750 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -1,21 +1,20 @@ -import * as fs from 'fs'; -import { logPort } from './ActionUtilities'; -import { Utils } from "../Utils"; -import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent, RoomMessage } from "./Message"; -import { Client } from "./Client"; -import { Socket } from "socket.io"; -import { Database } from "./database"; -import { Search } from "./Search"; -import * as sio from 'socket.io'; -import YoutubeApi from "./apis/youtube/youtubeApiSample"; -import { GoogleCredentialsLoader, SSL } from "./apis/google/CredentialsLoader"; -import { timeMap } from "./ApiManagers/UserManager"; import { green } from "colors"; +import * as express from "express"; +import { createServer, Server } from "https"; import { networkInterfaces } from "os"; +import * as sio from 'socket.io'; +import { Socket } from "socket.io"; import executeImport from "../scraping/buxton/final/BuxtonImporter"; +import { Utils } from "../Utils"; +import { logPort } from './ActionUtilities'; +import { timeMap } from "./ApiManagers/UserManager"; +import { GoogleCredentialsLoader, SSL } from "./apis/google/CredentialsLoader"; +import YoutubeApi from "./apis/youtube/youtubeApiSample"; +import { Client } from "./Client"; +import { Database } from "./database"; import { DocumentsCollection } from "./IDatabase"; -import { createServer, Server } from "https"; -import * as express from "express"; +import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent, YoutubeQueryInput, YoutubeQueryTypes } from "./Message"; +import { Search } from "./Search"; import { resolvedPorts } from './server_Initialization'; export namespace WebSocket { -- cgit v1.2.3-70-g09d2 From ac177d7b9a01075fbf1ad1c327c7625d95569afb Mon Sep 17 00:00:00 2001 From: anika-ahluwalia Date: Sun, 2 Aug 2020 18:20:59 -0500 Subject: bug fixes found with sally --- src/client/views/PropertiesButtons.scss | 13 +++++++-- src/client/views/PropertiesButtons.tsx | 29 +++++++++++++------ src/client/views/collections/CollectionMenu.scss | 19 ++++++++----- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 2 +- .../collectionFreeForm/PropertiesView.scss | 24 ++++++++++++++++ .../collectionFreeForm/PropertiesView.tsx | 33 ++++++++++------------ src/client/views/nodes/DocumentView.tsx | 8 +++--- src/client/views/nodes/FontIconBox.scss | 2 +- src/client/views/nodes/FontIconBox.tsx | 23 ++++++++------- src/client/views/nodes/LabelBox.tsx | 2 +- 11 files changed, 103 insertions(+), 54 deletions(-) (limited to 'src/client/views/collections/CollectionTreeView.tsx') diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index e099122c4..b3a317a6b 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -77,10 +77,19 @@ $linkGap : 3px; text-align: center; border-radius: 5px; pointer-events: auto; - color: $dark-color; - border: $dark-color 1px solid; + // color: $dark-color; + // border: $dark-color 1px solid; + background-color: #252b33; + color: #fcfbf7; transition: 0.2s ease all; margin-right: 5px; + padding-top: 5px; + + &:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; + } } .propertiesButtons-linker:hover { diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 59e7cc7c8..d3f056a34 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -208,7 +208,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const isPinned = targetDoc && Doc.isDocPinned(targetDoc); return !targetDoc ? (null) :
{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}
}>
DockedFrameRenderer.PinDoc(targetDoc, isPinned)}> @@ -238,6 +238,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { onAliasButtonDown = (e: React.PointerEvent): void => { setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction); } + @undoBatch onAliasButtonMoved = () => { if (this._dragRef.current) { const dragDocView = this.selectedDocumentView!; @@ -273,12 +274,17 @@ export class PropertiesButtons extends React.Component<{}, {}> {
; } + @undoBatch onCopy = () => { if (this.selectedDoc && this.selectedDocumentView) { - const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true); - copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width); - copy.y = NumCast(this.selectedDoc.y) + 30; - this.selectedDocumentView.props.addDocument?.(copy); + // const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true); + // copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width); + // copy.y = NumCast(this.selectedDoc.y) + 30; + // this.selectedDocumentView.props.addDocument?.(copy); + const alias = Doc.MakeAlias(this.selectedDoc); + alias.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width); + alias.y = NumCast(this.selectedDoc.y) + 30; + this.selectedDocumentView.props.addDocument?.(alias); } } @@ -295,7 +301,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { ; } - @action + @action @undoBatch onLock = () => { this.selectedDocumentView?.toggleLockPosition(); } @@ -337,15 +343,19 @@ export class PropertiesButtons extends React.Component<{}, {}> { return !targetDoc ? (null) :
{"Delete Document"}
}>
{ - this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document); - }}> + onPointerDown={this.deleteDocument}> {}
; } + @undoBatch + @action + deleteDocument = () => { + this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document); + } + @computed get sharingButton() { const targetDoc = this.selectedDoc; @@ -380,6 +390,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { } } + @undoBatch @action handleOptionChange = (e: any) => { const value = e.target.value; diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 9da204787..0a316317f 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -2,8 +2,8 @@ .collectionMenu-cont { - position:relative; - display:inline-flex; + position: relative; + display: inline-flex; width: 100%; opacity: 0.9; z-index: 9001; @@ -12,14 +12,15 @@ color: white; transform-origin: top left; top: 0; - width:100%; + width: 100%; .antimodeMenu-button { padding: 0; width: 30px; display: flex; + svg { - margin:auto; + margin: auto; } } @@ -108,6 +109,7 @@ margin-top: auto; margin-bottom: auto; } + .collectionViewBaseChrome-viewSpecs { margin-left: 5px; display: grid; @@ -318,12 +320,14 @@ text-align: center; display: block; } + .color-previewI { width: 80%; height: 20%; bottom: 0; position: absolute; } + .color-previewII { width: 80%; height: 80%; @@ -336,7 +340,7 @@ margin: auto; /* Make the buttons appear below each other */ } - + .btn-draw { display: inline-flex; margin: auto; @@ -374,6 +378,7 @@ display: block; margin: auto; } + border-right: solid gray 1px; } } @@ -398,14 +403,14 @@ .collectionSchemaViewChrome-toggler { width: 100px; - height: 41px; + height: 35px; background-color: black; position: relative; } .collectionSchemaViewChrome-togglerButton { width: 47px; - height: 35px; + height: 30px; background-color: $light-color-secondary; // position: absolute; transition: all 0.5s ease; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 7787a8b38..3c7471d7c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -785,7 +785,7 @@ export class CollectionTreeView extends CollectionSubView UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.doc, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit" }); - !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "hand-point-right" }); + !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" }); } outerXf = () => Utils.GetScreenTransform(this._mainEle!); onTreeDrop = (e: React.DragEvent) => this.onExternalDrop(e, {}); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index c2b55d38e..89034a0c0 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -339,7 +339,7 @@ export class CollectionView extends Touchable Doc.GetProto(this.props.Document)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)), })); - !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "hand-point-right" }); + !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" }); if (!Doc.UserDoc().noviceMode) { const more = cm.findByDescription("More..."); diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index a96716659..7df56115f 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -60,6 +60,10 @@ padding-left: 8px; background-color: rgb(51, 51, 51); + &:hover { + cursor: pointer; + } + .propertiesView-settings-title-icon { float: right; right: 0; @@ -94,6 +98,10 @@ padding-left: 8px; background-color: rgb(51, 51, 51); + &:hover { + cursor: pointer; + } + .propertiesView-sharing-title-icon { float: right; right: 0; @@ -127,6 +135,10 @@ padding-left: 8px; background-color: rgb(51, 51, 51); + &:hover { + cursor: pointer; + } + .propertiesView-appearance-title-icon { float: right; right: 0; @@ -160,6 +172,10 @@ padding-left: 8px; background-color: rgb(51, 51, 51); + &:hover { + cursor: pointer; + } + .propertiesView-transform-title-icon { float: right; right: 0; @@ -287,6 +303,10 @@ padding-left: 8px; background-color: rgb(51, 51, 51); + &:hover { + cursor: pointer; + } + .propertiesView-fields-title-name { font-size: 12.5px; font-weight: bold; @@ -362,6 +382,10 @@ padding-left: 8px; background-color: rgb(51, 51, 51); + &:hover { + cursor: pointer; + } + .propertiesView-layout-title-icon { float: right; right: 0; diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 73f0f1bdd..0168c825f 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -205,7 +205,7 @@ export class PropertiesView extends React.Component { } } - + @undoBatch setKeyValue = (value: string) => { if (this.selectedDoc && this.dataDoc) { const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc; @@ -266,9 +266,14 @@ export class PropertiesView extends React.Component { } } + @undoBatch + changePermissions = (e: any, user: string) => { + SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!); + } + getPermissionsSelect(user: string) { return this.widthStk = e.target.value))} - onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo");; }} + onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo"); }} onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }} />
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index dba92faae..2396e6973 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -21,7 +21,6 @@ import { Docs, DocUtils } from "../../documents/Documents"; import { ComputedField } from "../../../fields/ScriptField"; import { Networking } from "../../Network"; import { LinkAnchorBox } from "./LinkAnchorBox"; -import { signedCookie } from "cookie-parser"; // testing testing diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 35ed6c5a5..42a42ddf1 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -18,8 +18,6 @@ import { DocumentType } from "../../documents/DocumentTypes"; import { Zoom, Fade, Flip, Rotate, Bounce, Roll, LightSpeed } from 'react-reveal'; import { PresBox } from "./PresBox"; import { InkingStroke } from "../InkingStroke"; -import { PDFViewer } from "../pdf/PDFViewer"; -import { PDFBox } from "./PDFBox"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined; @@ -119,7 +117,6 @@ export class CollectionFreeFormDocumentView extends DocComponent(numberRange(timecode + 1).map(i => undefined) as any as number[]); const hlist = new List(numberRange(timecode + 1).map(i => undefined) as any as number[]); const olist = new List(numberRange(timecode + 1).map(t => progressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1)); - let oarray: List; - console.log(doc.title + "AF: " + doc.appearFrame); - console.log("timecode: " + timecode); - oarray = olist; + const oarray = olist; oarray.fill(0, 0, NumCast(doc.appearFrame) - 1); oarray.fill(1, NumCast(doc.appearFrame), timecode); // oarray.fill(0, 0, NumCast(doc.appearFrame) - 1); - // oarray.fill(1, NumCast(doc.appearFrame), timecode); - // console.log(oarray); + // oarray.fill(1, NumCast(doc.appearFrame), timecode);\ wlist[curTimecode] = NumCast(doc._width); hlist[curTimecode] = NumCast(doc._height); xlist[curTimecode] = NumCast(doc.x); diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 4713ce447..025669b41 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -125,7 +125,7 @@ export class DocumentLinksButton extends React.Component DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0); LinkManager.currentLink = linkDoc; if (linkDoc) { diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 1caefdc57..ccf1fb8e3 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -129,7 +129,7 @@ export class PresBox extends ViewBoxBaseComponent const nextChildDocs = DocListCast(nextTagDoc[Doc.LayoutFieldKey(presTargetDoc)]); nextChildDocs.forEach((doc, i) => { doc.opacity = 1; - }) + }); } const nextSelected = this.itemIndex + 1; this.gotoDocument(nextSelected, this.itemIndex); @@ -158,28 +158,24 @@ export class PresBox extends ViewBoxBaseComponent const vfHeight: number = this.checkList(presTargetDoc, presTargetDoc["viewfinder-height-indexed"]); // Case 1: document that is not a Golden Layout tab if (srcContext) { - console.log("CASE 1"); const srcDocView = DocumentManager.Instance.getDocumentView(srcContext); if (srcDocView) { const layoutdoc = Doc.Layout(presTargetDoc); const panelWidth: number = srcDocView.props.PanelWidth(); const panelHeight: number = srcDocView.props.PanelHeight(); - console.log("srcDocView: " + srcDocView.props.PanelWidth()); const newPanX = NumCast(presTargetDoc.x) + NumCast(layoutdoc._width) / 2; const newPanY = NumCast(presTargetDoc.y) + NumCast(layoutdoc._height) / 2; - let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight); + const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight); srcContext._panX = newPanX + (vfLeft + (vfWidth / 2)); srcContext._panY = newPanY + (vfTop + (vfHeight / 2)); srcContext._viewScale = newScale; - console.log("X: " + srcContext._panX + ", Y: " + srcContext._panY + ", Scale: " + srcContext._viewScale); } } // Case 2: document is the containing collection if (docView && !srcContext) { - console.log("CASE 2"); const panelWidth: number = docView.props.PanelWidth(); const panelHeight: number = docView.props.PanelHeight(); - let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight); + const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight); presTargetDoc._panX = vfLeft + (vfWidth / 2); presTargetDoc._panY = vfTop + (vfWidth / 2); presTargetDoc._viewScale = newScale; @@ -791,7 +787,7 @@ export class PresBox extends ViewBoxBaseComponent
Start manually
-
{ activeItem.openDocument = !activeItem.openDocument }}>Open document
+
activeItem.openDocument = !activeItem.openDocument}>Open document
Store original website
@@ -808,15 +804,15 @@ export class PresBox extends ViewBoxBaseComponent
e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
-
runInAction(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} /> -
runInAction(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}> +
{ this.layout = 'blank'; this.createNewSlide(this.layout); })} /> +
{ this.layout = 'title'; this.createNewSlide(this.layout); })}>
Title
Subtitle
-
runInAction(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}> +
{ this.layout = 'header'; this.createNewSlide(this.layout); })}>
Section header
-
runInAction(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}> +
{ this.layout = 'content'; this.createNewSlide(this.layout); })}>
Title
Text goes here
@@ -845,39 +841,39 @@ export class PresBox extends ViewBoxBaseComponent {/*
*/} { e.stopPropagation(); - runInAction(() => { (this.title = e.target.value) }); + runInAction(() => this.title = e.target.value); }}> {/*
*/}
Choose type:
-
runInAction(() => { this.addFreeform = !this.addFreeform })}>Text
-
runInAction(() => { this.addFreeform = !this.addFreeform })}>Freeform
+
this.addFreeform = !this.addFreeform)}>Text
+
this.addFreeform = !this.addFreeform)}>Freeform
Preset layouts:
-
runInAction(() => { this.layout = 'blank' })} /> -
runInAction(() => { this.layout = 'title' })}> +
this.layout = 'blank')} /> +
this.layout = 'title')}>
Title
Subtitle
-
runInAction(() => { this.layout = 'header' })}> +
this.layout = 'header')}>
Section header
-
runInAction(() => { this.layout = 'content' })}> +
this.layout = 'content')}>
Title
Text goes here
-
runInAction(() => { this.layout = 'twoColumns' })}> +
this.layout = 'twoColumns')}>
Title
Column one text
Column two text
-
runInAction(() => { this.openLayouts = !this.openLayouts })}> +
this.openLayouts = !this.openLayouts)}>
@@ -974,10 +970,10 @@ export class PresBox extends ViewBoxBaseComponent } // For toggling the options when the user wants to select play - @action togglePlay = () => { this.playTools = !this.playTools; } + @action togglePlay = () => { this.playTools = !this.playTools; }; // For toggling the options when the user wants to select play - @action togglePresent = () => { this.presentTools = !this.presentTools; } + @action togglePresent = () => { this.presentTools = !this.presentTools; }; // Case in which the document has keyframes to navigate to next key frame @undoBatch @@ -1381,9 +1377,7 @@ export class PresBox extends ViewBoxBaseComponent if (doc && tagDocView) { const scale = tagDocView.childScaling(); - console.log("childScaling: " + scale); const scale2 = tagDocView.props.ScreenToLocalTransform().Scale; - console.log("ScreenToLocal...Scale: " + scale2); let height = doc.offsetHeight; let width = doc.offsetWidth; let top = doc.offsetTop; @@ -1544,7 +1538,6 @@ export class PresBox extends ViewBoxBaseComponent @undoBatch @action prevAppearFrame = (doc: Doc, i: number): void => { - console.log("prev"); const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); const appearFrame = Cast(doc.appearFrame, "number", null); @@ -1595,7 +1588,7 @@ export class PresBox extends ViewBoxBaseComponent if (activeItem) { return ( <> -
{"Add new slide"}
}>
runInAction(() => { this.newDocumentTools = !this.newDocumentTools; })}> +
{"Add new slide"}
}>
this.newDocumentTools = !this.newDocumentTools)}>
@@ -1636,7 +1629,7 @@ export class PresBox extends ViewBoxBaseComponent } else { return ( <> -
{"Add new slide"}
}>
runInAction(() => { this.newDocumentTools = !this.newDocumentTools; })}> +
{"Add new slide"}
}>
this.newDocumentTools = !this.newDocumentTools)}>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 76d23ddfe..ab1de5529 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -577,20 +577,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const xLoc: number = (nestDepth * 20); const width: number = 390 - xLoc; const height: number = 55 - (nestDepth * 5); - for (let i = 0; i < list.length; i++) { - const mainBullets: number = Number(list[i].getAttribute("data-bulletstyle")); + Array.from(list).forEach(listItem => { + const mainBullets: number = Number(listItem.getAttribute("data-bulletstyle")); if (mainBullets === nestDepth) { - if (list[i].childElementCount > 1) { + if (listItem.childElementCount > 1) { b++; nestCount++; count = before ? count + nestCount + "." : nestCount + "."; yLoc += height; - const text = list[i].getElementsByTagName("p")[0].innerText; + const text = listItem.getElementsByTagName("p")[0].innerText; const length = text.length; - console.log(yLoc); const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); mainBulletList.push(bullet1); - const newList = this.recursiveProgressivize(nestDepth + 1, list[i].getElementsByTagName("li"), b, yLoc, count); + const newList = this.recursiveProgressivize(nestDepth + 1, listItem.getElementsByTagName("li"), b, yLoc, count); mainBulletList.push.apply(mainBulletList, newList); b += newList.length; yLoc += newList.length * (55 - ((nestDepth + 1) * 5)); @@ -599,15 +598,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp nestCount++; count = before ? count + nestCount + "." : nestCount + "."; yLoc += height; - const text = list[i].innerText; + const text = listItem.innerText; const length = text.length; - console.log(yLoc); const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b }); mainBulletList.push(bullet1); } } - } - console.log("b: " + b); + }); return mainBulletList; } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 6e268be48..5af07c15d 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -903,8 +903,9 @@ export default class RichTextMenu extends AntimodeMenu { ref_node = pos.nodeBefore; } if (pos.nodeAfter !== null && pos.nodeAfter !== undefined) { - if (!pos.nodeBefore || this.view.state.selection.$from.pos !== this.view.state.selection.$to.pos) + if (!pos.nodeBefore || this.view.state.selection.$from.pos !== this.view.state.selection.$to.pos) { ref_node = pos.nodeAfter; + } } if (!ref_node && pos.pos > 0) { let skip = false; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index e035ed0b8..11ffde9dd 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -259,7 +259,7 @@ export class PresElementBox extends ViewBoxBaseComponent doc)); // let value = this.getValue(this._heading); // value = typeof value === "string" ? `"${value}"` : value; - let dragItem: HTMLElement[] = []; + const dragItem: HTMLElement[] = []; PresBox.Instance._dragArray.map(ele => { const drag = ele; drag.style.backgroundColor = "#d5dce2"; -- cgit v1.2.3-70-g09d2