From 31451c577cfc12736feb6f9e64e72d803cef720a Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 1 Sep 2021 10:55:01 -0400 Subject: fixed double clicking on data docs in filesystem to open best alias. --- src/client/views/collections/TreeView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 86fd21677..e8f345782 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -154,8 +154,8 @@ export class TreeView extends React.Component { } else { // choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias // this.props.addDocTab(CurrentUserUtils.ActiveDashboard.isShared ? Doc.MakeAlias(this.props.document) : this.props.document, "add:right"); - // choose an appropriate alias or make one -- -- choose the first alias that (1) the user owns, (2) has no context field - if I own it and someone else does not have it open,, otherwise create an alias - this.props.addDocTab(this.props.document, "add:right"); + const bestAlias = DocListCast(this.props.document.aliases).find(doc => !doc.context); + this.props.addDocTab(bestAlias ?? Doc.MakeAlias(this.props.document), "add:right"); } } -- cgit v1.2.3-70-g09d2 From be825152070aa609817a2df7880e9cc377f7cfc1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 1 Sep 2021 12:19:38 -0400 Subject: changed ctrl-click to open alias to reuse existing alias. changed documentview to not clearout docView field when invalidated to allow webBox componentView to be persistent which allows proper settting of scrollHeight and allows webBox to grow to vertical space available in tab or lightbox. --- src/client/views/DocumentDecorations.tsx | 17 ++++++++--------- src/client/views/SidebarAnnos.tsx | 3 ++- src/client/views/collections/TreeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 7 ++++--- src/client/views/nodes/WebBox.tsx | 12 ++++++------ src/fields/documentSchemas.ts | 1 - 6 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e454be618..a570bdb34 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; import { action, computed, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { AclAdmin, AclEdit, DataSym, Doc, Field, HeightSym, WidthSym } from "../../fields/Doc"; +import { AclAdmin, AclEdit, DataSym, Doc, Field, HeightSym, WidthSym, DocListCast } from "../../fields/Doc"; import { Document } from '../../fields/documentSchemas'; import { HtmlField } from '../../fields/HtmlField'; import { InkField } from "../../fields/InkField"; @@ -159,9 +159,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b const selectedDocs = SelectionManager.Views(); if (selectedDocs.length) { if (e.ctrlKey) { // open an alias in a new tab with Ctrl Key - selectedDocs[0].props.Document._fullScreenView = Doc.MakeAlias(selectedDocs[0].props.Document); - (selectedDocs[0].props.Document._fullScreenView as Doc).context = undefined; - CollectionDockingView.AddSplit(selectedDocs[0].props.Document._fullScreenView as Doc, "right"); + const bestAlias = DocListCast(selectedDocs[0].props.Document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); + CollectionDockingView.AddSplit(bestAlias ?? Doc.MakeAlias(selectedDocs[0].props.Document), "right"); } else if (e.shiftKey) { // open centered in a new workspace with Shift Key const alias = Doc.MakeAlias(selectedDocs[0].props.Document); alias.context = undefined; @@ -169,7 +168,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b alias.y = -alias[HeightSym]() / 2; CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([alias], { title: "Tab for " + alias.title }), "right"); } else if (e.altKey) { // open same document in new tab - CollectionDockingView.ToggleSplit(Cast(selectedDocs[0].props.Document._fullScreenView, Doc, null) || selectedDocs[0].props.Document, "right"); + CollectionDockingView.ToggleSplit(selectedDocs[0].props.Document, "right"); } else { LightboxView.SetLightboxDoc(selectedDocs[0].props.Document, undefined, selectedDocs.slice(1).map(view => view.props.Document)); } @@ -391,10 +390,10 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b this._inkDragDocs.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] })) .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => { Doc.GetProto(doc).data = new InkField(inkPts.map(ipt => // (new x — oldx) + newWidth * (oldxpoint /oldWidth) - ({ - X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width, - Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height - }))); + ({ + X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width, + Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height + }))); Doc.SetNativeWidth(doc, undefined); Doc.SetNativeHeight(doc, undefined); }); diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 1f9763d18..0e3663f65 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -90,6 +90,7 @@ export class SidebarAnnos extends React.Component { } return this.props.styleProvider?.(doc, props, property); } + setHeightCallback = (height: number) => this.props.setHeight(height + this.filtersHeight()); render() { const renderTag = (tag: string) => { const active = StrListCast(this.props.rootDoc[this.filtersKey]).includes(`${tag}:${tag}:check`); @@ -126,7 +127,7 @@ export class SidebarAnnos extends React.Component { styleProvider={this.sidebarStyleProvider} docFilters={this.docFilters} scaleField={this.sidebarKey + "-scale"} - setHeight={(height) => this.props.setHeight(height + this.filtersHeight())} + setHeight={this.setHeightCallback} isAnnotationOverlay={false} select={emptyFunction} scaling={returnOne} diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index e8f345782..b9487054b 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -154,7 +154,7 @@ export class TreeView extends React.Component { } else { // choose an appropriate alias or make one. --- choose the first alias that (1) user owns, (2) has no context field ... otherwise make a new alias // this.props.addDocTab(CurrentUserUtils.ActiveDashboard.isShared ? Doc.MakeAlias(this.props.document) : this.props.document, "add:right"); - const bestAlias = DocListCast(this.props.document.aliases).find(doc => !doc.context); + const bestAlias = DocListCast(this.props.document.aliases).find(doc => !doc.context && doc.author === Doc.CurrentUserEmail); this.props.addDocTab(bestAlias ?? Doc.MakeAlias(this.props.document), "add:right"); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index fda84dd2d..6b9513b8b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -93,6 +93,7 @@ export interface DocComponentView { fieldKey?: string; annotationKey?: string; getTitle?: () => string; + getScrollHeight?: () => number; } export interface DocumentViewSharedProps { renderDepth: number; @@ -464,7 +465,6 @@ export class DocumentViewInternal extends DocComponent LightboxView.AddDocTab(this.rootDoc, "lightbox", this.props.LayoutTemplate?.()) - //this.props.addDocTab((this.rootDoc._fullScreenView as Doc) || this.rootDoc, "lightbox") , "double tap"); SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); @@ -983,6 +983,7 @@ export class DocumentViewInternal extends DocComponent; } render() { + TraceMobx(); const highlightIndex = this.props.LayoutTemplateString ? (Doc.IsHighlighted(this.props.Document) ? 6 : 0) : Doc.isBrushedHighlightedDegree(this.props.Document); // bcz: Argh!! need to identify a tree view doc better than a LayoutTemlatString const highlightColor = (Doc.UserDoc().colorScheme === ColorScheme.Dark ? ["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] : @@ -1075,7 +1076,7 @@ export class DocumentView extends React.Component { @computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); } @computed get panelHeight() { if (this.effectiveNativeHeight) { - return Math.min(this.props.PanelHeight(), Math.max(NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling); + return Math.min(this.props.PanelHeight(), Math.max(this.ComponentView?.getScrollHeight?.() ?? NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling); } return this.props.PanelHeight(); } @@ -1182,7 +1183,7 @@ export class DocumentView extends React.Component { ScreenToLocalTransform={this.screenToLocalTransform} focus={this.props.focus || emptyFunction} bringToFront={emptyFunction} - ref={action((r: DocumentViewInternal | null) => this.docView = r)} /> + ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))} /> )} ); } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index e4d4557af..719e5a796 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; import * as WebRequest from 'web-request'; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; @@ -13,9 +13,8 @@ import { ComputedField } from "../../../fields/ScriptField"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { WebField } from "../../../fields/URLField"; import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, Utils, returnEmptyString, returnEmptyFilter } from "../../../Utils"; +import { emptyFunction, getWordAtPoint, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils"; import { Docs } from "../../documents/Documents"; -import { DocumentType } from '../../documents/DocumentTypes'; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; import { Scripting } from "../../util/Scripting"; import { SnappingManager } from "../../util/SnappingManager"; @@ -59,7 +58,7 @@ export class WebBox extends ViewBoxAnnotatableComponent(); - @observable private _scrollHeight = 1500; + @observable private _scrollHeight = NumCast(this.layoutDoc.scrollHeight, 1500); @computed get _url() { return this.webField?.toString() || ""; } @computed get _urlHash() { return this._url ? WebBox.urlHash(this._url) + "" : ""; } @computed get scrollHeight() { return this._scrollHeight; } @@ -229,6 +228,8 @@ export class WebBox extends ViewBoxAnnotatableComponent this._scrollHeight; + isFirefox = () => { return "InstallTrigger" in window; // navigator.userAgent.indexOf("Chrome") !== -1; } @@ -417,8 +418,7 @@ export class WebBox extends ViewBoxAnnotatableComponent Date: Thu, 2 Sep 2021 04:45:01 -0400 Subject: Many updates - Fixed image uploads so it clones rather than makes an alias - Updated context menu - Removed tools panel from novice mode in favour of ":" menu - Added explainers to menus in novice mode - Re-added the trails button - Changed UI for text, PDF & websites so that it is more consistent --- src/client/documents/Documents.ts | 52 +++++---- src/client/util/CurrentUserUtils.ts | 93 ++++++++-------- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenuItem.tsx | 4 +- src/client/views/MainViewModal.scss | 3 +- src/client/views/PropertiesButtons.scss | 41 +++++-- src/client/views/PropertiesButtons.tsx | 53 +++++---- src/client/views/SidebarAnnos.tsx | 3 +- src/client/views/StyleProvider.tsx | 4 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionStackingView.scss | 24 +++++ .../views/collections/CollectionStackingView.tsx | 119 +++++++++++++++------ .../views/collections/CollectionTreeView.tsx | 95 ++++++++++++---- src/client/views/collections/TabDocView.tsx | 3 +- src/client/views/collections/TreeView.tsx | 5 +- .../collectionLinearView/CollectionLinearView.scss | 6 +- .../collectionSchema/CollectionSchemaHeaders.tsx | 2 +- .../collectionSchema/CollectionSchemaView.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/PDFBox.scss | 16 ++- src/client/views/nodes/PDFBox.tsx | 13 ++- src/client/views/nodes/WebBox.scss | 9 +- src/client/views/nodes/WebBox.tsx | 13 ++- src/client/views/nodes/button/FontIconBox.scss | 29 ++++- src/client/views/nodes/button/FontIconBox.tsx | 15 +-- .../nodes/formattedText/FormattedTextBox.scss | 21 +++- .../views/nodes/formattedText/FormattedTextBox.tsx | 16 ++- src/client/views/search/SearchBox.tsx | 2 +- src/client/views/topbar/TopBar.scss | 4 +- src/client/views/topbar/TopBar.tsx | 3 +- 31 files changed, 460 insertions(+), 202 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c4a713dc6..bd247bd01 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -59,6 +59,7 @@ import { WebBox } from "../views/nodes/WebBox"; import { SearchBox } from "../views/search/SearchBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; +import { IconProp } from "@fortawesome/fontawesome-svg-core"; const path = require('path'); const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); @@ -272,7 +273,12 @@ export class DocumentOptions { treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. - treeViewShowClearButton?: boolean; // whether a clear button should be displayed + + // Action Button + buttonMenu?: boolean; // whether a action button should be displayed + buttonMenuDoc?: Doc; + explainer?:string; + treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view _treeViewOpen?: boolean; // whether this document is expanded in a tree view (note: need _ and regular versions since this can be specified for both proto and layout docs) treeViewOpen?: boolean; // whether this document is expanded in a tree view @@ -1165,7 +1171,7 @@ export namespace DocUtils { export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false): void { !simpleMenu && ContextMenu.Instance.addItem({ - description: "Add Note ...", + description: "Quick Notes", subitems: DocListCast((Doc.UserDoc()["template-notes"] as Doc).data).map((note, i) => ({ description: ":" + StrCast(note.title), event: undoBatch((args: { x: number, y: number }) => { @@ -1178,12 +1184,12 @@ export namespace DocUtils { textDoc[textDoc.layoutKey] = note; docTextAdder(textDoc); }), - icon: "eye" + icon: StrCast(note.icon) as IconProp })) as ContextMenuProps[], - icon: "eye" + icon: "sticky-note" }); - ContextMenu.Instance.addItem({ - description: ":=math", event: () => { + const math:ContextMenuProps = ({ + description: ":Math", event: () => { const created = Docs.Create.EquationDocument(); if (created) { created.author = Doc.CurrentUserEmail; @@ -1194,25 +1200,27 @@ export namespace DocUtils { EquationBox.SelectOnLoad = created[Id]; docAdder?.(created); } - }, icon: "compress-arrows-alt" + }, icon: "calculator" }); + const documentList:ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ + description: ":" + StrCast(dragDoc.title), + event: undoBatch((args: { x: number, y: number }) => { + const newDoc = Doc.copyDragFactory(dragDoc); + if (newDoc) { + newDoc.author = Doc.CurrentUserEmail; + newDoc.x = x; + newDoc.y = y; + if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id]; + docAdder?.(newDoc); + } + }), + icon: Doc.toIcon(dragDoc), + })) as ContextMenuProps[]; + documentList.push(math) ContextMenu.Instance.addItem({ description: "Create document", - subitems: DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ - description: ":" + StrCast(dragDoc.title), - event: undoBatch((args: { x: number, y: number }) => { - const newDoc = Doc.copyDragFactory(dragDoc); - if (newDoc) { - newDoc.author = Doc.CurrentUserEmail; - newDoc.x = x; - newDoc.y = y; - if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id]; - docAdder?.(newDoc); - } - }), - icon: Doc.toIcon(dragDoc), - })) as ContextMenuProps[], - icon: "eye" + subitems: documentList, + icon: "file" }); }// applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index f12ac02f3..f6ec74482 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -84,7 +84,7 @@ export class CurrentUserUtils { title: "NEW MOBILE BUTTON", onClick: undefined, }, - [this.ficon({ + [this.createToolButton({ ignoreClick: true, icon: "mobile", btnType: ButtonType.ToolButton, @@ -92,7 +92,7 @@ export class CurrentUserUtils { }), this.mobileTextContainer({}, [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]); - doc["template-mobile-button"] = CurrentUserUtils.ficon({ + doc["template-mobile-button"] = CurrentUserUtils.createToolButton({ onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'), dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, title: "mobile button", icon: "mobile", btnType: ButtonType.ToolButton, }); @@ -107,7 +107,7 @@ export class CurrentUserUtils { { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true } ); slideTemplate.isTemplateDoc = makeTemplate(slideTemplate); - doc["template-button-slides"] = CurrentUserUtils.ficon({ + doc["template-button-slides"] = CurrentUserUtils.createToolButton({ onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'), dragFactory: new PrefetchProxy(slideTemplate) as any as Doc, title: "presentation slide", icon: "address-card", btnType: ButtonType.ToolButton @@ -154,7 +154,7 @@ export class CurrentUserUtils { }; linkTemplate.header = new RichTextField(JSON.stringify(rtf2), ""); - doc["template-button-link"] = CurrentUserUtils.ficon({ + doc["template-button-link"] = CurrentUserUtils.createToolButton({ onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'), dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, title: "link view", icon: "window-maximize", system: true, btnType: ButtonType.ToolButton @@ -186,7 +186,7 @@ export class CurrentUserUtils { const box = MulticolumnDocument([/*no, */ yes, name], { title: "value", _width: 120, _height: 35, system: true }); box.isTemplateDoc = makeTemplate(box, true, "switch"); - doc["template-button-switch"] = CurrentUserUtils.ficon({ + doc["template-button-switch"] = CurrentUserUtils.createToolButton({ onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'), dragFactory: new PrefetchProxy(box) as any as Doc, title: "data switch", icon: "toggle-on", system: true, btnType: ButtonType.ToolButton @@ -236,7 +236,7 @@ export class CurrentUserUtils { short.title = "A Short Description"; long.title = "Long Description"; - doc["template-button-detail"] = CurrentUserUtils.ficon({ + doc["template-button-detail"] = CurrentUserUtils.createToolButton({ onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'), dragFactory: new PrefetchProxy(detailView) as any as Doc, title: "detailView", @@ -275,7 +275,7 @@ export class CurrentUserUtils { static setupNoteTemplates(doc: Doc) { if (doc["template-note-Note"] === undefined) { const noteView = Docs.Create.TextDocument("", { - title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true, + title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true, icon: "sticky-note", _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize), }); noteView.isTemplateDoc = makeTemplate(noteView, true, "Note"); @@ -283,7 +283,7 @@ export class CurrentUserUtils { } if (doc["template-note-Idea"] === undefined) { const noteView = Docs.Create.TextDocument("", { - title: "text", backgroundColor: "pink", system: true, + title: "text", backgroundColor: "pink", system: true, icon: "lightbulb", _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize), }); noteView.isTemplateDoc = makeTemplate(noteView, true, "Idea"); @@ -291,7 +291,7 @@ export class CurrentUserUtils { } if (doc["template-note-Topic"] === undefined) { const noteView = Docs.Create.TextDocument("", { - title: "text", backgroundColor: "lightblue", system: true, + title: "text", backgroundColor: "lightblue", system: true, icon: "book-open", _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize), }); noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic"); @@ -467,7 +467,7 @@ export class CurrentUserUtils { ((doc.emptyHeader as Doc).proto as Doc)["dragFactory-count"] = 0; } if (doc.emptyComparison === undefined) { - doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true, cloneFieldFilter: new List(["system"]) }); + doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "comparison box", _width: 300, _height: 300, system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyScript === undefined) { doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script", system: true, cloneFieldFilter: new List(["system"]) }); @@ -512,7 +512,7 @@ export class CurrentUserUtils { { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc }, { toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc }, { toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true }, - { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc, noviceMode: true }, + { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc }, { toolTip: "Tap to create a videoWall", title: "Wall", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWall as Doc }, { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true }, { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc }, @@ -561,7 +561,7 @@ export class CurrentUserUtils { if (dragCreatorSet === undefined) { doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, { title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true, - _forceActive: true, _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true, + _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true })); } else { @@ -574,29 +574,31 @@ export class CurrentUserUtils { return [ { title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' }, { title: "Search", target: Cast(doc.mySearchPanel, Doc, null), icon: "search", click: 'selectMainMenu(self)' }, - { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' }, - { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' }, - { title: "Import", target: Cast(doc.myImportDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, + { title: "File Manager", target: Cast(doc.myFilesystem, Doc, null), icon: "folder-open", click: 'selectMainMenu(self)' }, + { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" }, + { title: "Uploads", target: Cast(doc.myUploadDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' }, { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc }, { title: "Trails", target: Cast(doc.myTrails, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' }, - { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' }, + { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" }, ]; } static async setupMenuPanel(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) { if (doc.menuStack === undefined) { await this.setupSharingSidebar(doc, sharingDocumentId, linkDatabaseId); // sets up the right sidebar collection for mobile upload documents and sharing - const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments }) => + const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments, hidden }) => Docs.Create.FontIconDocument({ icon, btnType: ButtonType.MenuButton, _stayInCollection: true, _hideContextMenu: true, + _chromeHidden: true, system: true, dontUndo: true, title, target, + hidden: hidden ? ComputedField.MakeFunction("IsNoviceMode()") as any : undefined, _dropAction: "alias", _removeDropProperties: new List(["dropAction", "_stayInCollection"]), _width: 60, @@ -611,8 +613,6 @@ export class CurrentUserUtils { this.searchBtn = menuBtn; } }); - // hack -- last button is assumed to be the userDoc - menuBtns[menuBtns.length - 1].hidden = ComputedField.MakeFunction("IsNoviceMode()"); menuBtns.forEach(menuBtn => { if (menuBtn.title === "Search") { @@ -684,7 +684,7 @@ export class CurrentUserUtils { onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, backgroundColor: data.backgroundColor, system: true }, - [this.ficon({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])]) + [this.createToolButton({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])]) ); } @@ -820,6 +820,7 @@ export class CurrentUserUtils { const removeDashboard = ScriptField.MakeScript('removeDashboard(self)'); (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, shareDashboard!, removeDashboard!]); (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Share Dashboard", "Remove Dashboard"]); + (doc.myDashboards as any as Doc).childContextMenuIcons = new List(["plus", "share", "times"]); // (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, toggleTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]); // (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]); } @@ -860,18 +861,21 @@ export class CurrentUserUtils { } static setupRecentlyClosedDocs(doc: Doc) { - // setup Recently Closed library item if (doc.myRecentlyClosedDocs === undefined) { - const clearDocs = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript(`getProto(self).data = new List([])`), toolTip: "Empty", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.TextButton, _width: 200, buttonText: "Empty Recently Closed", icon: "trash", system: true }); - doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([clearDocs], { - title: "My Recently Closed", _showTitle: "title", treeViewShowClearButton: true, childHideLinkButton: true, + const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`); + const clearDocsButton:Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true }); + doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], { + title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, - _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true + _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, + explainer: "Documents that you close will appear here so you can easily access them again. You can choose to clear this menu in which case you might lose these documents." + })); - const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`); (doc.myRecentlyClosedDocs as any as Doc).contextMenuScripts = new List([clearAll!]); - (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List(["Clear All"]); + (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List(["Empty recently closed"]); + (doc.myRecentlyClosedDocs as any as Doc).contextMenuIcons = new List(["trash"]); + } } @@ -916,7 +920,7 @@ export class CurrentUserUtils { static async setupSidebarButtons(doc: Doc) { CurrentUserUtils.setupSidebarContainer(doc); await CurrentUserUtils.setupToolsBtnPanel(doc); - CurrentUserUtils.setupImportSidebar(doc); + CurrentUserUtils.setupUploadSidebar(doc); CurrentUserUtils.setupDashboards(doc); CurrentUserUtils.setupPresentations(doc); CurrentUserUtils.setupFilesystem(doc); @@ -930,17 +934,17 @@ export class CurrentUserUtils { _lockedPosition: true, system: true, flexDirection: "row" })) as any as Doc - static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ - ...opts, _dropAction: "alias", _removeDropProperties: new List(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true + static createToolButton = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ + ...opts, btnType: ButtonType.ToolButton, _forceActive: true, _dropAction: "alias", _removeDropProperties: new List(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true })) as any as Doc /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupDockedButtons(doc: Doc) { if (doc["dockedBtn-undo"] === undefined) { - doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to undo", title: "undo", icon: "undo-alt", system: true }); + doc["dockedBtn-undo"] = CurrentUserUtils.createToolButton({ onClick: ScriptField.MakeScript("undo()"), _width: 30, _height: 30, dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to undo", title: "undo", icon: "undo-alt", system: true }); } if (doc["dockedBtn-redo"] === undefined) { - doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "redo", icon: "redo-alt", system: true }); + doc["dockedBtn-redo"] = CurrentUserUtils.createToolButton({ onClick: ScriptField.MakeScript("redo()"), _width: 30, _height: 30, dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "redo", icon: "redo-alt", system: true }); } if (doc.dockedBtns === undefined) { doc.dockedBtns = CurrentUserUtils.linearButtonList({ title: "docked buttons", _height: 40, flexGap: 0, linearViewFloating: true, linearViewIsExpanded: true, linearViewExpandable: true, ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]); @@ -1039,7 +1043,7 @@ export class CurrentUserUtils { // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy", hidden: 'selectedDocumentType()' }, // Only when a document is selected { title: "Text", type: "textTools", subMenu: true, expanded: 'selectedDocumentType("rtf")' }, // Always available { title: "Ink", type: "inkTools", subMenu: true, expanded: 'selectedDocumentType("ink")' }, // Always available - // { title: "Web", type: "webTools", subMenu: true, hidden: 'selectedDocumentType("web")' }, // Only when Web is selected + { title: "Web", type: "webTools", subMenu: true, hidden: 'selectedDocumentType("web")' }, // Only when Web is selected { title: "Schema", type: "schemaTools", subMenu: true, hidden: 'selectedDocumentType(undefined, "schema")' } // Only when Schema is selected ]; } @@ -1172,13 +1176,15 @@ export class CurrentUserUtils { } doc.myLinkDatabase = new PrefetchProxy(linkDocs); } + // TODO:glr NOTE: treeViewHideTitle & _showTitle may be confusing, treeViewHideTitle is for the editable title (just for tree view), _showTitle is to show the Document title for any document if (doc.mySharedDocs === undefined) { let sharedDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(sharingDocumentId + "outer"); if (!sharedDocs) { sharedDocs = Docs.Create.TreeDocument([], { title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, - _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, + _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, _chromeHidden: true, boxShadow: "0 0", + explainer: "All of the documents that you receive will appear here. They must be shared by other users. If you receive a Dashboard you can add it to your Dashboards by right clicking and clicking 'Add to Dashboards'" }, sharingDocumentId + "outer", sharingDocumentId); (sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Augment; } @@ -1189,18 +1195,21 @@ export class CurrentUserUtils { sharedDocs.childContextMenuFilters = new List([dashboardFilter!,]); sharedDocs.childContextMenuScripts = new List([addToDashboards!,]); sharedDocs.childContextMenuLabels = new List(["Add to Dashboards",]); + sharedDocs.childContextMenuIcons = new List(["user-plus",]); + } doc.mySharedDocs = new PrefetchProxy(sharedDocs); } } // Import sidebar is where shared documents are contained - static setupImportSidebar(doc: Doc) { - if (doc.myImportDocs === undefined) { - const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Upload from computer", _width: 100, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.TextButton, buttonText: "Upload from computer", icon: "upload", system: true }); - doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([newUpload], { - title: "My Uploads", _forceActive: true, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, - childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, + static setupUploadSidebar(doc: Doc) { + if (doc.myUploadDocs === undefined) { + const newUploadButton:Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true }); + doc.myUploadDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { + title: "My Uploads", _forceActive: true, buttonMenu: true, buttonMenuDoc: newUploadButton, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, + childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, + explainer: "All of the documents that are imported into Dash will go here and stay here unless they are explicitly removed." })); } } @@ -1303,7 +1312,7 @@ export class CurrentUserUtils { doc.filterDocCount = 0; this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupDocTemplates(doc); // sets up the template menu of templates - this.setupImportSidebar(doc); // sets up the import sidebar + this.setupUploadSidebar(doc); // sets up the import sidebar this.setupSearchSidebar(doc); // sets up the search sidebar this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile this.setupOverlays(doc); // documents in overlay layer @@ -1430,7 +1439,7 @@ export class CurrentUserUtils { } } } else if (input.files && input.files.length !== 0) { - const importDocs = Cast(Doc.UserDoc().myImportDocs, Doc, null); + const importDocs = Cast(Doc.UserDoc().myUploadDocs, Doc, null); const disposer = OverlayView.ShowSpinner(); DocListCastAsync(importDocs.data).then(async list => { const results = await DocUtils.uploadFilesToDocs(Array.from(input.files || []), {}); diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 41a6dc569..47ae0424b 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -130,7 +130,7 @@ } .contextMenu-inlineMenu { - border-top: solid 1px; + // border-top: solid 1px; //TODO:glr clean } .contextMenu-item:hover { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 168fcb888..c3921d846 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -116,12 +116,12 @@ export class ContextMenuItem extends React.Component {this.props.icon ? ( - + ) : null}
+ style={{ alignItems: "center", alignSelf: "center" }} > {this.props.description}
diff --git a/src/client/views/MainViewModal.scss b/src/client/views/MainViewModal.scss index 03cb5cc84..0648e31c5 100644 --- a/src/client/views/MainViewModal.scss +++ b/src/client/views/MainViewModal.scss @@ -6,6 +6,7 @@ height: 100%; .dialogue-box { + padding: 10px; position: absolute; z-index: 1000; text-align: center; @@ -13,7 +14,7 @@ align-self: center; align-content: center; background: white; - border-radius: 10px; + // border-radius: 10px; box-shadow: #00000044 5px 5px 10px; transform: translate(-50%, -50%); top: 50%; diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index 484522bc7..77686a710 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -67,10 +67,12 @@ $linkGap : 3px; } .onClickFlyout-editScript { + cursor: pointer; text-align: center; - border: 0.5px solid grey; + margin-top: 5px; + border: 0.5px solid $medium-gray; background-color: rgb(230, 230, 230); - border-radius: 9px; + border-radius: 5px; padding: 4px; } @@ -84,9 +86,32 @@ $linkGap : 3px; margin-bottom: 8px; } +.propertiesButton-dropdownList { + width: 100%; + height: fit-content; + top: 100%; + z-index: 21; + + .list-item { + cursor: pointer; + color: $black; + width: 100%; + height: 25px; + font-weight: 400; + display: flex; + justify-content: left; + align-items: center; + padding-left: 5px; + } + + .list-item:hover { + background-color: lightgrey; + } +} + .propertiesButtons-title { - background: #121721; - color: white; + background: $dark-gray; + color: $white; font-size: 6px; width: 37px; padding: 3px; @@ -111,17 +136,11 @@ $linkGap : 3px; margin-left: 4px; &:hover { - background: $medium-gray; - transform: scale(1.05); + filter:brightness(0.85); cursor: pointer; } } -.propertiesButtons-linker:hover { - cursor: pointer; - transform: scale(1.05); -} - @-moz-keyframes spin { 100% { diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index dcab9bc1e..4fde1124f 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -15,6 +15,7 @@ import { InkingStroke } from './InkingStroke'; import { DocumentView } from './nodes/DocumentView'; import './PropertiesButtons.scss'; import React = require("react"); +import { Colors } from "./global/globalEnums"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -128,11 +129,11 @@ export class PropertiesButtons extends React.Component<{}, {}> { @undoBatch @action - handleOptionChange = (e: any) => { - this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value); + handleOptionChange = (onClick: string) => { + this.selectedDoc && (this.selectedDoc.onClickBehavior = onClick); SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => { docView.noOnClick(); - switch (e.target.value) { + switch (onClick) { case "enterPortal": docView.makeIntoPortal(); break; case "toggleDetail": docView.setToggleDetail(); break; case "linkInPlace": docView.toggleFollowLink("inPlace", true, false); break; @@ -149,20 +150,34 @@ export class PropertiesButtons extends React.Component<{}, {}> { @computed get onClickFlyout() { - const makeLabel = (value: string, label: string) =>
- -
; + const buttonList = [ + ["nothing", "Select Document"], + ["enterPortal", "Enter Portal"], + ["toggleDetail", "Toggle Detail"], + ["linkInPlace", "Follow Link"], + ["linkOnRight", "Open Link on Right"] + ] + const currentSelection = this.selectedDoc.onClickBehavior; + // Get items to place into the list + + const list = buttonList.map((value) => { + const click = () => { + this.handleOptionChange(value[0]); + }; + return
+ {value[1]} +
; + }); return
-
- {makeLabel("nothing", "Select Document")} - {makeLabel("enterPortal", "Enter Portal")} - {makeLabel("toggleDetail", "Toggle Detail")} - {makeLabel("linkInPlace", "Follow Link")} - {makeLabel("linkOnRight", "Open Link on Right")} -
+
+
+ {list} +
+
{Doc.UserDoc().noviceMode ? (null) :
Edit onClick Script
}
; } @@ -190,7 +205,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const isFreeForm = this.selectedDoc?._viewType === CollectionViewType.Freeform; const isTree = this.selectedDoc?._viewType === CollectionViewType.Tree; const toggle = (ele: JSX.Element | null, style?: React.CSSProperties) =>
{ele}
; - + const isNovice = Doc.UserDoc().noviceMode; return !this.selectedDoc ? (null) :
{toggle(this.titleButton)} @@ -198,7 +213,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { {toggle(this.lockButton)} {toggle(this.dictationButton)} {toggle(this.onClickButton)} - {toggle(this.fitWidthButton)} + {toggle(this.fitWidthButton, { display: isNovice ? "none" : "" })} {toggle(this.fitContentButton, { display: !isFreeForm ? "none" : "" })} {toggle(this.autoHeightButton, { display: !isText && !isStacking && !isTree ? "none" : "" })} {toggle(this.maskButton, { display: !isInk ? "none" : "" })} @@ -207,7 +222,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { {toggle(this.snapButton, { display: isCollection ? "" : "none" })} {toggle(this.clustersButton, { display: !isFreeForm ? "none" : "" })} {toggle(this.panButton, { display: !isFreeForm ? "none" : "" })} - {toggle(this.perspectiveButton, { display: !isCollection ? "none" : "" })} + {toggle(this.perspectiveButton, { display: !isCollection || isNovice ? "none" : "" })}
; } } \ No newline at end of file diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx index 0e3663f65..01b79ffd2 100644 --- a/src/client/views/SidebarAnnos.tsx +++ b/src/client/views/SidebarAnnos.tsx @@ -106,9 +106,10 @@ export class SidebarAnnos extends React.Component { {user} ; }; + // TODO: Calculation of the topbar is hardcoded and different for text nodes - it should all be the same and all be part of SidebarAnnos return !this.props.showSidebar ? (null) :
, props: Opt, props: Opt (props?.PanelHeight() || 0) ? 5 : 10) : 0; - case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry].includes(doc?._viewType as any) || + case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) || doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0; case StyleProp.BackgroundColor: { if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 6bdeaf722..6a22acae8 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -338,7 +338,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {this.renderColors(this._col)}
+ >Hide Column
; } diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 4b123c8b6..2f002736d 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -14,6 +14,30 @@ width: 100%; } +// TODO:glr Turn this into a seperate class +.documentButtonMenu { + position: relative; + height: fit-content; + border-bottom: $standard-border; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + align-content: center; + padding: 5px 0 5px 0; + + .documentExplanation { + width: 90%; + margin: 5px; + font-size: 11px; + background-color: $light-blue; + color: $medium-blue; + padding: 10px; + border-radius: 10px; + border: solid 2px $medium-blue; + } +} + .collectionStackingView, .collectionMasonryView { height: 100%; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4fedda1bd..3c9084f64 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { CursorProperty } from "csstype"; import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { DataSym, Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../fields/Doc"; import { collectionSchema, documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; @@ -11,7 +11,7 @@ import { listSpec, makeInterface } from "../../../fields/Schema"; import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils"; +import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils, returnTrue, returnEmptyDoclist, returnEmptyFilter } from "../../../Utils"; import { DocUtils, Docs } from "../../documents/Documents"; import { DragManager, dropActionType } from "../../util/DragManager"; import { SnappingManager } from "../../util/SnappingManager"; @@ -23,12 +23,14 @@ import { EditableView } from "../EditableView"; import { LightboxView } from "../LightboxView"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from "../nodes/DocumentView"; -import { StyleProp } from "../StyleProvider"; +import { StyleProp, DefaultStyleProvider } from "../StyleProvider"; import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow"; import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; +import { FontIconBox } from "../nodes/button/FontIconBox"; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; const _global = (window /* browser */ || global /* node */) as any; type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>; @@ -514,6 +516,47 @@ export class CollectionStackingView extends CollectionSubView this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1], i === 0)); } + @computed get buttonMenu() { + const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); + // TODO:glr Allow support for multiple buttons + if (menuDoc){ + const width: number = NumCast(menuDoc._width, 30); + const height: number = NumCast(menuDoc._height, 30); + console.log(menuDoc.title, width, height); + return (
+ 35} + PanelHeight={() => 35} + renderDepth={this.props.renderDepth} + focus={emptyFunction} + styleProvider={this.props.styleProvider} + layerProvider={this.props.layerProvider} + docViewPath={returnEmptyDoclist} + whenChildContentsActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={this.props.docFilters} + docRangeFilters={this.props.docRangeFilters} + searchFilterDocs={this.props.searchFilterDocs} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> +
+ ); + } + } + @computed get nativeWidth() { return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); } @computed get nativeHeight() { return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); } @@ -529,34 +572,50 @@ export class CollectionStackingView extends CollectionSubView -
this._scroll = e.currentTarget.scrollTop)} - onDrop={this.onExternalDrop.bind(this)} - onContextMenu={this.onContextMenu} - onWheel={e => this.props.isContentActive(true) && e.stopPropagation()} > - {this.renderedSections} - {!this.showAddAGroup ? (null) : -
- -
} - {/* {this.chromeHidden || !this.props.isSelected() ? (null) : - } */} -
+ <> + {buttonMenu || noviceExplainer ?
+ {buttonMenu ? this.buttonMenu : null} + {Doc.UserDoc().isNovice && noviceExplainer ? +
+ {noviceExplainer} +
+ : null + } +
: null} +
+
this._scroll = e.currentTarget.scrollTop)} + onDrop={this.onExternalDrop.bind(this)} + onContextMenu={this.onContextMenu} + onWheel={e => this.props.isContentActive(true) && e.stopPropagation()} > + {this.renderedSections} + {!this.showAddAGroup ? (null) : +
+ +
} + {/* {this.chromeHidden || !this.props.isSelected() ? (null) : + } */} +
+
+ + ); } } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 89d42439e..4d62a1af4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -8,7 +8,7 @@ import { Document, listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils'; +import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, emptyFunction } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DocumentManager } from '../../util/DocumentManager'; @@ -26,6 +26,7 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import { TreeView } from "./TreeView"; import React = require("react"); +import { Transform } from '../../util/Transform'; const _global = (window /* browser */ || global /* node */) as any; export type collectionTreeViewProps = { @@ -221,8 +222,9 @@ export class CollectionTreeView extends CollectionSubView { const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []); - const filterScripts = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []); - return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: filterScripts[i], label })); + const customFilters = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []); + const icons = StrListCast(this.doc.childContextMenuIcons); + return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label })); } @computed get treeViewElements() { TraceMobx(); @@ -265,13 +267,48 @@ export class CollectionTreeView extends CollectionSubView - - ; + @computed get buttonMenu() { + const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); + // To create a multibutton menu add a CollectionLinearView + if (menuDoc){ + + const width: number = NumCast(menuDoc._width, 30); + const height: number = NumCast(menuDoc._height, 30); + console.log(menuDoc.title, width, height); + return (
+ 35} + PanelHeight={() => 35} + renderDepth={this.props.renderDepth + 1} + focus={emptyFunction} + styleProvider={this.props.styleProvider} + layerProvider={this.props.layerProvider} + docViewPath={returnEmptyDoclist} + whenChildContentsActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={this.props.docFilters} + docRangeFilters={this.props.docRangeFilters} + searchFilterDocs={this.props.searchFilterDocs} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> +
); + } } + + @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); } @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); } @@ -295,22 +332,34 @@ export class CollectionTreeView extends CollectionSubView this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor); const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined; + const buttonMenu = this.rootDoc.buttonMenu; + const noviceExplainer = this.rootDoc.explainer; return !(this.doc instanceof Doc) || !this.treeChildren ? (null) : -
-
e.stopPropagation()} - onDrop={this.onTreeDrop} - ref={this.createTreeDropTarget}> + <> {this.titleBar} - {this.renderClearButton} -
    - {this.treeViewElements} -
-
-
; +
+ {buttonMenu || noviceExplainer ?
+ {buttonMenu ? this.buttonMenu : null} + {Doc.UserDoc().noviceMode && noviceExplainer ? +
+ {noviceExplainer} +
+ : null + } +
: null} +
e.stopPropagation()} + onDrop={this.onTreeDrop} + ref={this.createTreeDropTarget}> +
    + {this.treeViewElements} +
+
+
+ ; } } \ No newline at end of file diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 889db1ef6..34cb6ec55 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -387,9 +387,10 @@ export class TabDocView extends React.Component { background={this.miniMapColor} document={this._document} tabView={this.tabView} /> - {this._document.hideMinimap ? "Open minimap" : "Close minimap"}}> + {this._document.hideMinimap ? "Open minimap" : "Close minimap"}}>
{ childContextMenuItems = () => { const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []); const customFilters = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []); - return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], label })); + const icons = StrListCast(this.doc.childContextMenuIcons); + return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label })); } onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); @@ -835,7 +836,7 @@ export class TreeView extends React.Component { dontRegisterView: boolean | undefined, observerHeight: (ref: any) => void, unobserveHeight: (ref: any) => void, - contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string }[]) + contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[]) ) { const viewSpecScript = Cast(conainerCollection.viewSpecScript, ScriptField); if (viewSpecScript) { diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss index f249eb1f5..8fe804466 100644 --- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss +++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss @@ -98,7 +98,11 @@ transition: transform 0.2s; align-items: center; justify-content: center; - transition: 0.15s; + transition: 0.2s; + + &:hover{ + filter: brightness(0.85); + } } >input { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx index b28c32e0e..a25f962df 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx @@ -191,7 +191,7 @@ export class CollectionSchemaColumnMenu extends React.Component {this.renderSorting()} {this.renderColors()}
- +
} diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index fed64b620..dfe99ffc8 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -338,7 +338,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {this.renderColors(this._col)}
+ >Hide Column
; } diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index f5a7e61aa..8962d29f0 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -638,12 +638,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent< ) : ( - + )} ) : ( diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7463e192f..98ae279db 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -635,7 +635,7 @@ export class DocumentViewInternal extends DocComponent { const portalLink = this.allLinks.find(d => d.anchor1 === this.props.Document); if (!portalLink) { - const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + ".portal" }); + const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + " [Portal]" }); DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to"); } this.Document.followLinkLocation = "inPlace"; @@ -679,7 +679,7 @@ export class DocumentViewInternal extends DocComponent this.props.addDocTab(templateDoc, "add:right"), icon: "eye" }); - appearanceItems.push({ + !Doc.UserDoc().noviceMode && appearanceItems.push({ description: "Add a Field", event: () => { const alias = Doc.MakeAlias(this.rootDoc); alias.layout = FormattedTextBox.LayoutString("newfield"); diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 72dec6e4c..f44355929 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -1,3 +1,5 @@ +@import "../global/globalCssVariables.scss"; + .pdfBox, .pdfBox-interactive { display: inline-block; @@ -18,12 +20,13 @@ top: 0; left: 0; + // glr: This should really be the same component as text and PDFs .pdfBox-sidebarBtn { - background: #121721; + background: $black; height: 25px; width: 25px; - right: 0; - color: white; + right: 5px; + color: $white; display: flex; position: absolute; align-items: center; @@ -31,6 +34,13 @@ border-radius: 3px; pointer-events: all; z-index: 1; // so it appears on top of the document's title, if shown + + box-shadow: $standard-box-shadow; + transition: 0.2s; + + &:hover{ + filter: brightness(0.85); + } } .pdfBox-pageNums { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 5e07229c1..3a399bfdb 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -24,6 +24,7 @@ import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); import { AnchorMenu } from '../pdf/AnchorMenu'; +import { Colors } from '../global/globalEnums'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -208,11 +209,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent this._pageControls = !this._pageControls)} /> {this._pageControls ? pageBtns : (null)} - + + ; } sidebarWidth = () => !this.SidebarShown ? 0 : diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index 19b69ff5a..417a17d96 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -10,7 +10,7 @@ background: #121721; height: 25px; width: 25px; - right: 0; + right: 5px; display: flex; position: absolute; align-items: center; @@ -18,6 +18,13 @@ border-radius: 3px; pointer-events: all; z-index: 1; // so it appears on top of the document's title, if shown + + box-shadow: $standard-box-shadow; + transition: 0.2s; + + &:hover{ + filter: brightness(0.85); + } } .pdfViewerDash-dragAnnotationBox { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 719e5a796..1f85219d6 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -33,6 +33,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { LinkDocPreview } from "./LinkDocPreview"; import "./WebBox.scss"; import React = require("react"); +import { Colors } from "../global/globalEnums"; const _global = (window /* browser */ || global /* node */) as any; const htmlToText = require("html-to-text"); @@ -590,11 +591,15 @@ export class WebBox extends ViewBoxAnnotatableComponent - + + ); } } diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss index 48fb2c8dc..a2da35fe1 100644 --- a/src/client/views/nodes/button/FontIconBox.scss +++ b/src/client/views/nodes/button/FontIconBox.scss @@ -7,6 +7,7 @@ align-items: center; font-size: 80%; border-radius: $standard-border-radius; + transition: 0.15s; .menuButton-wrap { grid-column: 1; @@ -29,6 +30,9 @@ font-family: 'ROBOTO'; text-transform: uppercase; font-weight: bold; + transition: 0.15s; + + } .fontIconBox-icon { @@ -50,7 +54,18 @@ } &.textBtn { + display: grid; + /* grid-row: auto; */ + grid-auto-flow: column; + cursor: pointer; width: 100%; + justify-content: center; + align-items: center; + justify-items: center; + + &:hover { + filter:brightness(0.85) !important; + } } &.tglBtn { @@ -127,13 +142,13 @@ } &:hover { - background-color: rgba(0, 0, 0, 0.3) !important; + background-color: rgba(0, 0, 0, 0.3); } } &.toolBtn { cursor: pointer; - width: 40px; + width: 100%; border-radius: 100%; svg { @@ -143,7 +158,7 @@ } &.menuBtn { - cursor: pointer; + cursor: pointer !important; border-radius: 0px; flex-direction: column; @@ -151,6 +166,10 @@ width: 45% !important; height: 45%; } + + &:hover{ + filter: brightness(0.85); + } } @@ -163,8 +182,8 @@ .colorButton-color { margin-top: 3px; - width: 90%; - height: 6px; + width: 80%; + height: 3px; } .menuButton-dropdownBox { diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index bccf733f0..1b27d562a 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -253,11 +253,12 @@ export class FontIconBox extends DocComponent(Fon } else if (selected) { dropdown = false; text = StrCast(selected.Document.type); + if (text === DocumentType.RTF) text = "Text"; icon = Doc.toIcon(selected.Document); } else { dropdown = false; - noneSelected = true; - text = "None selected"; + icon = "globe-asia"; + text = "User Default"; } noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking]; } else if (script === 'setFont') { @@ -302,7 +303,7 @@ export class FontIconBox extends DocComponent(Fon
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> - {dropdown || noneSelected ? (null) : } + {dropdown || noneSelected ? (null) : }
{text && text[0].toUpperCase() + text.slice(1)}
@@ -487,7 +488,7 @@ export class FontIconBox extends DocComponent(Fon
; const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) : -
+
{this.label}
; @@ -508,7 +509,7 @@ export class FontIconBox extends DocComponent(Fon switch (this.type) { case ButtonType.TextButton: button = ( -
+
{buttonText ?
@@ -558,7 +559,7 @@ export class FontIconBox extends DocComponent(Fon break; case ButtonType.MenuButton: const trailsIcon = ; + style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />; button = (
{this.icon === "pres-trail" ? trailsIcon : } @@ -605,7 +606,7 @@ Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: bo Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) { const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined; if (checkResult && selected) { - if (NumCast(selected.Document.z) === 1) return Colors.MEDIUM_BLUE; + if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE; else return "transparent"; } selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed"); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 3cedab1a4..56f5c5631 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -66,14 +66,25 @@ audiotag:hover { .formattedTextBox-sidebar-handle { position: absolute; - top: 0; + top: 5px; //top: calc(50% - 17.5px); // use this to center vertically -- make sure it looks okay for slide views - width: 10px; + width: 25px; height: 100%; - max-height: 35px; - background: lightgray; - border-radius: 20px; + max-height: 25px; + color: white; + background: $medium-gray; + border-radius: 5px; + display: flex; + justify-content: center; + align-items: center; cursor:grabbing; + box-shadow: $standard-box-shadow; + // transition: 0.2s; + + &:hover{ + filter: brightness(0.85); + } + } .formattedTextBox-sidebar, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index f45b9de7a..468edf6cc 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -63,6 +63,8 @@ import { SummaryView } from "./SummaryView"; import applyDevTools = require("prosemirror-dev-tools"); import React = require("react"); import { SidebarAnnos } from '../../SidebarAnnos'; +import { Colors } from '../../global/globalEnums'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; const translateGoogleApi = require("translate-google-api"); export interface FormattedTextBoxProps { @@ -574,11 +576,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp changeItems.push({ description: "plain", event: undoBatch(() => Doc.setNativeView(this.rootDoc)), icon: "eye" }); const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null); DocListCast(noteTypesDoc?.data).forEach(note => { + const icon: IconProp = StrCast(note.icon) as IconProp; changeItems.push({ description: StrCast(note.title), event: undoBatch(() => { Doc.setNativeView(this.rootDoc); DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note); - }), icon: "eye" + }), icon: icon }); }); !Doc.UserDoc().noviceMode && changeItems.push({ description: "FreeForm", event: () => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" }); @@ -1481,11 +1484,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get sidebarHandle() { TraceMobx(); const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length; + const color = !annotated ? Colors.WHITE : Colors.BLACK; + const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : "")); return (!annotated && !this.props.isContentActive()) ? (null) :
; + left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${"- 30px"}))`, + backgroundColor: backgroundColor, + color: color + }} > + +
; } @computed get sidebarCollection() { const renderComponent = (tag: string) => { diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 260ddfc90..e70b2bc19 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -114,7 +114,7 @@ export class SearchBox extends ViewBoxBaseComponent
-
+
window.open( + "https://brown-dash.github.io/Dash-Documentation/", "_blank")}> {"Help"}
SettingsManager.Instance.open()}> -- cgit v1.2.3-70-g09d2 From f20dfa857e1651ced1eb2303ea8a8462483fbc4c Mon Sep 17 00:00:00 2001 From: geireann Date: Sun, 12 Sep 2021 10:00:30 -0400 Subject: updates --- src/client/util/CurrentUserUtils.ts | 51 +++++++++++++++++-------------- src/client/views/MainView.tsx | 20 ++++++++++++ src/client/views/collections/TreeView.tsx | 8 ++--- src/client/views/nodes/DocumentView.tsx | 5 +-- 4 files changed, 55 insertions(+), 29 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 56807c63b..760949b57 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -575,11 +575,11 @@ export class CurrentUserUtils { return [ { title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' }, { title: "Search", target: Cast(doc.mySearchPanel, Doc, null), icon: "search", click: 'selectMainMenu(self)' }, - { title: "File Manager", target: Cast(doc.myFilesystem, Doc, null), icon: "folder-open", click: 'selectMainMenu(self)' }, + { title: "Files", target: Cast(doc.myFilesystem, Doc, null), icon: "folder-open", click: 'selectMainMenu(self)' }, { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" }, - { title: "Uploads", target: Cast(doc.myUploadDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, + { title: "Imports", target: Cast(doc.myImportDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' }, { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' }, - { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc }, + { title: "Shared with me", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc }, { title: "Trails", target: Cast(doc.myTrails, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' }, { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" }, ]; @@ -807,13 +807,15 @@ export class CurrentUserUtils { // setup dashboards library item await doc.myDashboards; if (doc.myDashboards === undefined) { + const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`); + const newDashboardButton:Doc = Docs.Create.FontIconDocument({ onClick: newDashboard, _forceActive: true, toolTip: "Create new dashboard", _stayInCollection: true, _hideContextMenu: true, title: "new dashboard", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myDashboards = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Dashboards", _showTitle: "title", _height: 400, childHideLinkButton: true, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", - treeViewTruncateTitleWidth: 150, ignoreClick: true, - _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true + treeViewTruncateTitleWidth: 150, ignoreClick: true, buttonMenu: true, buttonMenuDoc: newDashboardButton, + _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true, + explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files." })); - const newDashboard = ScriptField.MakeScript(`createNewDashboard(Doc.UserDoc())`); // const toggleTheme = ScriptField.MakeScript(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`); // const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); // const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`); @@ -821,7 +823,7 @@ export class CurrentUserUtils { const removeDashboard = ScriptField.MakeScript('removeDashboard(self)'); (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, shareDashboard!, removeDashboard!]); (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Share Dashboard", "Remove Dashboard"]); - (doc.myDashboards as any as Doc).childContextMenuIcons = new List(["plus", "share", "times"]); + (doc.myDashboards as any as Doc).childContextMenuIcons = new List(["plus", "user-friends", "times"]); // (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, toggleTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]); // (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]); } @@ -832,7 +834,7 @@ export class CurrentUserUtils { await doc.myTrails; if (doc.myTrails === undefined) { const newTrail = ScriptField.MakeScript(`createNewPresentation()`); - const newTrailButton:Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "New trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); + const newTrailButton:Doc = Docs.Create.FontIconDocument({ onClick: newTrail, _forceActive: true, toolTip: "Create new trail", _stayInCollection: true, _hideContextMenu: true, title: "New trail", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New trail", icon: "plus", system: true }); doc.myTrails = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "My Trails", _showTitle: "title", _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _fitWidth: true, _gridGap: 5, _forceActive: true, childDropAction: "alias", @@ -842,6 +844,7 @@ export class CurrentUserUtils { })); (doc.myTrails as any as Doc).contextMenuScripts = new List([newTrail!]); (doc.myTrails as any as Doc).contextMenuLabels = new List(["Create New Trail"]); + (doc.myTrails as any as Doc).childContextMenuIcons = new List(["plus"]); } return doc.myTrails as any as Doc; } @@ -851,8 +854,8 @@ export class CurrentUserUtils { if (doc.myFilesystem === undefined) { doc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); // doc.myFileRoot = Docs.Create.TreeDocument([], { title: "file root", _stayInCollection: true, system: true, isFolder: true }); - const newFolder = ScriptField.MakeFunction(`doc.makeFolder()`, { doc: doc.myFilesystem })!; - const newFolderButton:Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); + const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!; + const newFolderButton:Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "Create new folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); doc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([doc.myFileOrphans as Doc], { title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", @@ -861,8 +864,9 @@ export class CurrentUserUtils { _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." })); - (doc.myTrails as any as Doc).contextMenuScripts = new List([newFolder!]); - (doc.myTrails as any as Doc).contextMenuLabels = new List(["Create new folder"]); + (doc.myFilesystem as any as Doc).contextMenuScripts = new List([newFolder!]); + (doc.myFilesystem as any as Doc).contextMenuLabels = new List(["Create new folder"]); + (doc.myFilesystem as any as Doc).childContextMenuIcons = new List(["plus"]); } return doc.myFilesystem as any as Doc; } @@ -927,7 +931,7 @@ export class CurrentUserUtils { static async setupSidebarButtons(doc: Doc) { CurrentUserUtils.setupSidebarContainer(doc); await CurrentUserUtils.setupToolsBtnPanel(doc); - CurrentUserUtils.setupUploadSidebar(doc); + CurrentUserUtils.setupImportSidebar(doc); CurrentUserUtils.setupDashboards(doc); CurrentUserUtils.setupPresentations(doc); CurrentUserUtils.setupFilesystem(doc); @@ -1194,7 +1198,7 @@ export class CurrentUserUtils { title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 50, _gridGap: 15, _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment, _chromeHidden: true, boxShadow: "0 0", - explainer: "This is where documents or dashboards that other users have shared with you will appear." + explainer: "This is where documents or dashboards that other users have shared with you will appear. To share a document or dashboard right click and select 'Share'" }, sharingDocumentId + "outer", sharingDocumentId); (sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Augment; } @@ -1213,13 +1217,13 @@ export class CurrentUserUtils { } // Import sidebar is where shared documents are contained - static setupUploadSidebar(doc: Doc) { - if (doc.myUploadDocs === undefined) { - const newUploadButton:Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true }); - doc.myUploadDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { - title: "My Uploads", _forceActive: true, buttonMenu: true, buttonMenuDoc: newUploadButton, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, + static setupImportSidebar(doc: Doc) { + if (doc.myImportDocs === undefined) { + const newImportButton:Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Import from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Import", btnType: ButtonType.ClickButton, buttonText: "Import", icon: "upload", system: true }); + doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([], { + title: "My Imports", _forceActive: true, buttonMenu: true, buttonMenuDoc: newImportButton, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0, childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true, - explainer: "This is where documents that are uploaded into Dash will go." + explainer: "This is where documents that are Imported into Dash will go." })); } } @@ -1322,7 +1326,7 @@ export class CurrentUserUtils { doc.filterDocCount = 0; this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon this.setupDocTemplates(doc); // sets up the template menu of templates - this.setupUploadSidebar(doc); // sets up the import sidebar + this.setupImportSidebar(doc); // sets up the import sidebar this.setupSearchSidebar(doc); // sets up the search sidebar this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile this.setupOverlays(doc); // documents in overlay layer @@ -1449,7 +1453,7 @@ export class CurrentUserUtils { } } } else if (input.files && input.files.length !== 0) { - const importDocs = Cast(Doc.UserDoc().myUploadDocs, Doc, null); + const importDocs = Cast(Doc.UserDoc().myImportDocs, Doc, null); const disposer = OverlayView.ShowSpinner(); DocListCastAsync(importDocs.data).then(async list => { const results = await DocUtils.uploadFilesToDocs(Array.from(input.files || []), {}); @@ -1473,7 +1477,6 @@ export class CurrentUserUtils { } public static createNewDashboard = async (userDoc: Doc, id?: string) => { - const myTrails = await userDoc.myTrails as Doc; const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true); const dashboards = await Cast(userDoc.myDashboards, Doc) as Doc; const dashboardCount = DocListCast(dashboards.data).length + 1; @@ -1558,6 +1561,8 @@ Scripting.addGlobal(function createNewDashboard() { return CurrentUserUtils.crea "creates a new dashboard when called"); Scripting.addGlobal(function createNewPresentation() { return MainView.Instance.createNewPresentation(); }, "creates a new presentation when called"); +Scripting.addGlobal(function createNewFolder() { return MainView.Instance.createNewFolder(); }, + "creates a new folder in myFiles when called"); Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, "returns all the links to the document or its annotations", "(doc: any)"); Scripting.addGlobal(function importDocument() { return CurrentUserUtils.importDocument(); }, diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index dadf5b390..809c63a45 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -63,6 +63,7 @@ import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; +import { ScriptField } from '../../fields/ScriptField'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -239,6 +240,25 @@ export class MainView extends React.Component { Doc.AddDocToList(this.userDoc.myTrails as Doc, "data", pres); } + @action + createNewFolder = async () => { + if (!await this.userDoc.myFilesystem) { + this.userDoc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); + const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!; + const newFolderButton:Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); + this.userDoc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([this.userDoc.myFileOrphans as Doc], { + title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, + treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", + treeViewTruncateTitleWidth: 150, ignoreClick: true, + isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, + _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, + explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." + })); + } + const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true }); + Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder); + } + getPWidth = () => this._panelWidth - this.propertiesWidth(); getPHeight = () => this._panelHeight - (CollectionMenu.Instance?.Pinned ? 35 : 0); getContentsHeight = () => this._panelHeight; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 8cf34ddcc..2727a0af5 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -240,7 +240,7 @@ export class TreeView extends React.Component { } makeFolder = () => { - const folder = Docs.Create.TreeDocument([], { title: "-folder-", _stayInCollection: true, isFolder: true }); + const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true }); TreeView._editTitleOnLoad = { id: folder[Id], parent: this.props.parentTreeView }; return this.props.addDocument(folder); } @@ -512,9 +512,9 @@ export class TreeView extends React.Component { DocumentViewInternal.SelectAfterContextMenu = true; } contextMenuItems = () => { - const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }; - const openAlias = { script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }; - const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }; + const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, icon: "folder-plus", label: "New Folder" }; + const openAlias = { script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, icon: "copy", label: "Open Alias" }; + const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: "eye", label: "Focus or Open" }; return [...this.props.contextMenuItems.filter(mi => !mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result), ... (this.doc.isFolder ? [makeFolder] : Doc.IsSystem(this.doc) ? [] : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ? diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b2629200d..ebd0211e2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -49,6 +49,7 @@ import { RadialMenu } from './RadialMenu'; import { ScriptingBox } from "./ScriptingBox"; import { PresBox } from './trails/PresBox'; import React = require("react"); +import { IconProp } from "@fortawesome/fontawesome-svg-core"; const { Howl } = require('howler'); interface Window { @@ -152,7 +153,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps { NativeWidth?: () => number; NativeHeight?: () => number; LayoutTemplate?: () => Opt; - contextMenuItems?: () => { script: ScriptField, label: string }[]; + contextMenuItems?: () => { script: ScriptField, label: string, icon: string }[]; onClick?: () => ScriptField; onDoubleClick?: () => ScriptField; onPointerDown?: () => ScriptField; @@ -672,7 +673,7 @@ export class DocumentViewInternal extends DocComponent cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" })); this.props.contextMenuItems?.().forEach(item => - item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" })); + item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: item.icon as IconProp })); if (!this.props.Document.isFolder) { const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); -- cgit v1.2.3-70-g09d2 From e911344b7b93381c2dda4434480a6168291c60c0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 13 Sep 2021 14:28:37 -0400 Subject: fixed errors and warnings. --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/MainView.tsx | 5 +++-- src/client/views/collections/TreeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/button/FontIconBox.tsx | 21 +++++---------------- .../nodes/button/colorDropdown/ColorDropdown.tsx | 10 ++++------ .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- 7 files changed, 16 insertions(+), 28 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 9a5ccffa0..6a7523d5b 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -863,7 +863,7 @@ export class CurrentUserUtils { _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true, explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard." })); - (doc.myFilesystem as any as Doc).contextMenuScripts = new List([newFolder!]); + (doc.myFilesystem as any as Doc).contextMenuScripts = new List([newFolder]); (doc.myFilesystem as any as Doc).contextMenuLabels = new List(["Create new folder"]); (doc.myFilesystem as any as Doc).childContextMenuIcons = new List(["plus"]); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 68ec97523..9b1cc3499 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -64,6 +64,7 @@ import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; import { ScriptField } from '../../fields/ScriptField'; +import { ButtonType } from './nodes/button/FontIconBox'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -245,9 +246,9 @@ export class MainView extends React.Component { if (!await this.userDoc.myFilesystem) { this.userDoc.myFileOrphans = Docs.Create.TreeDocument([], { title: "Unfiled", _stayInCollection: true, system: true, isFolder: true }); const newFolder = ScriptField.MakeFunction(`createNewFolder()`, { scriptContext: "any" })!; - const newFolderButton:Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); + const newFolderButton: Doc = Docs.Create.FontIconDocument({ onClick: newFolder, _forceActive: true, toolTip: "New folder", _stayInCollection: true, _hideContextMenu: true, title: "New folder", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "New folder", icon: "folder-plus", system: true }); this.userDoc.myFilesystem = new PrefetchProxy(Docs.Create.TreeDocument([this.userDoc.myFileOrphans as Doc], { - title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, + title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100, treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias", treeViewTruncateTitleWidth: 150, ignoreClick: true, isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true, diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 2727a0af5..aa7b164b0 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -54,7 +54,7 @@ export interface TreeViewProps { indentDocument?: (editTitle: boolean) => void; outdentDocument?: (editTitle: boolean) => void; ScreenToLocalTransform: () => Transform; - contextMenuItems: { script: ScriptField, filter: ScriptField, label: string }[]; + contextMenuItems: { script: ScriptField, filter: ScriptField, icon: string, label: string }[]; dontRegisterView?: boolean; styleProvider?: StyleProviderFunc | undefined; treeViewHideHeaderFields: () => boolean; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5de4c2c4e..007dca0c4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -154,7 +154,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps { NativeWidth?: () => number; NativeHeight?: () => number; LayoutTemplate?: () => Opt; - contextMenuItems?: () => { script: ScriptField, label: string, icon: string }[]; + contextMenuItems?: () => { script: ScriptField, filter?: ScriptField, label: string, icon: string }[]; onClick?: () => ScriptField; onDoubleClick?: () => ScriptField; onPointerDown?: () => ScriptField; diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx index fb96969c5..5ae7c3628 100644 --- a/src/client/views/nodes/button/FontIconBox.tsx +++ b/src/client/views/nodes/button/FontIconBox.tsx @@ -246,7 +246,6 @@ export class FontIconBox extends DocComponent(Fon let text: string | undefined; let dropdown = true; let icon: IconProp = "caret-down"; - let noneSelected: boolean = false; if (script === 'setView') { const selected = SelectionManager.Docs().lastElement(); @@ -301,7 +300,7 @@ export class FontIconBox extends DocComponent(Fon
this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}> - {dropdown || noneSelected ? (null) : } + {dropdown ? (null) : }
{text && text[0].toUpperCase() + text.slice(1)}
@@ -334,22 +333,14 @@ export class FontIconBox extends DocComponent(Fon const scriptCheck: string = script + "(undefined, true)"; const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result; - let stroke: boolean = false; - let strokeIcon: any; - // if (script === "setStrokeColor") { - // stroke = true; - // const checkWidth = ScriptField.MakeScript("setStrokeWidth(0, true)")?.script.run().result; - // const width = 20 + (checkWidth / 100) * 70; - // const height = 20 + (checkWidth / 100) * 70; - // strokeIcon = (
); - // } + const showAlpha: boolean = script !== "setStrokeColor"; // bcz: ugh this should be changed to a field property on the button const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', "transparent"]; const colorBox = (func: (color: ColorState) => void) => ; const label = !this.label || !Doc.UserDoc()._showLabel ? (null) : @@ -375,10 +366,8 @@ export class FontIconBox extends DocComponent(Fon style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }} onClick={() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen} onPointerDown={e => e.stopPropagation()}> - {stroke ? strokeIcon : <> -
} + +
{label} {/* {dropdownCaret} */} {this.rootDoc.dropDownOpen ? diff --git a/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx b/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx index 1809f4e2e..235495250 100644 --- a/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx +++ b/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx @@ -14,8 +14,7 @@ export class ColorDropdown extends Component { const scriptCheck: string = script + "(undefined, true)"; const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result; - let stroke: boolean = false; - let strokeIcon: any; + const stroke: boolean = false; // if (script === "setStrokeColor") { // stroke = true; // const checkWidth = ScriptField.MakeScript("setStrokeWidth(0, true)")?.script.run().result; @@ -55,10 +54,9 @@ export class ColorDropdown extends Component { style={{ color: this.props.color, borderBottomLeftRadius: active ? 0 : undefined }} onClick={() => this.props.rootDoc.dropDownOpen = !this.props.rootDoc.dropDownOpen} onPointerDown={e => e.stopPropagation()}> - {stroke ? strokeIcon : <> -
} + +
{label} {/* {dropdownCaret} */} {this.props.rootDoc.dropDownOpen ? diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 4b540312e..fce95547e 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1160,7 +1160,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp selectOnLoad && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. if (this._editorView && !this._editorView.state.storedMarks?.some(mark => mark.type === schema.marks.user_mark)) { - this._editorView.state.storedMarks = [...(this._editorView!.state.storedMarks ?? []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; + this._editorView.state.storedMarks = [...(this._editorView.state.storedMarks ?? []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; } } -- cgit v1.2.3-70-g09d2 From e0240412990f102523b86e324bc973cd2ed523a1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 14 Sep 2021 22:27:17 -0400 Subject: refactored a bunch of names in MainView. Fixed scrolling in left menu flyout treeview panels. --- src/client/views/MainView.scss | 62 +--------- src/client/views/MainView.tsx | 126 +++++++++++---------- src/client/views/collections/CollectionMenu.tsx | 34 +++--- .../views/collections/CollectionTreeView.tsx | 68 +++++------ src/client/views/collections/TreeView.tsx | 2 +- src/client/views/global/globalCssVariables.scss | 8 +- .../views/global/globalCssVariables.scss.d.ts | 4 +- 7 files changed, 130 insertions(+), 174 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 817e45699..4f871f5ec 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -15,8 +15,8 @@ margin-top: 10px; } -.mainContent-div-flyout, -.mainContent-div { +.mainView-dockingContent-flyout, +.mainView-dockingContent { position: relative; width: 100%; height: 100%; @@ -99,7 +99,7 @@ } } -.mainView-mainContent { +.mainView-dashboardArea { width: 100%; height: 100%; position: absolute; @@ -208,7 +208,7 @@ } } -.mainView-menuPanel { +.mainView-leftMenuPanel { min-width: var(--menuPanelWidth); background-color: $dark-gray; border-right: $standard-border; @@ -220,60 +220,6 @@ ::-webkit-scrollbar { width: 0; } - - .mainView-menuPanel-button { - padding: 7px; - padding-left: 7px; - width: 100%; - background: $dark-gray; - - .mainView-menuPanel-button-wrap { - width: 45px; - /* padding: 5px; */ - touch-action: none; - background: $dark-gray; - transform-origin: top left; - /* margin-bottom: 5px; */ - margin-top: 5px; - margin-right: 25px; - border-radius: 8px; - - &:hover { - background: $black; - cursor: pointer; - } - } - } - - .mainView-menuPanel-button-label { - color: white; - margin-left: px; - 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; - } - - .mainView-menuPanel-button-icon { - width: auto; - height: 35px; - padding: 5px; - } -} - -.mainView-searchPanel { - width: 100%; - height: $searchpanel-height; - background-color: black; - color: white; - text-align: center; - vertical-align: middle; } .mainView-mainDiv { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b102c9a1f..5bda9f6bf 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -11,9 +11,10 @@ import * as ReactDOM from 'react-dom'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; +import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, PromiseValue, StrCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils'; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocUtils } from '../documents/Documents'; @@ -36,11 +37,12 @@ import { CollectionLinearView } from './collections/collectionLinear'; import { CollectionMenu } from './collections/CollectionMenu'; import { CollectionViewType } from './collections/CollectionView'; import "./collections/TreeView.scss"; +import { ComponentDecorations } from './ComponentDecorations'; import { ContextMenu } from './ContextMenu'; import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; import { GestureOverlay } from './GestureOverlay'; -import { MENU_PANEL_WIDTH, SEARCH_PANEL_HEIGHT } from './global/globalCssVariables.scss'; +import { DASHBOARD_SELECTOR_HEIGHT, LEFT_MENU_WIDTH } from './global/globalCssVariables.scss'; import { Colors } from './global/globalEnums'; import { KeyManager } from './GlobalKeyHandler'; import { InkStrokeProperties } from './InkStrokeProperties'; @@ -48,9 +50,11 @@ import { LightboxView } from './LightboxView'; import { LinkMenu } from './linking/LinkMenu'; import "./MainView.scss"; import { AudioBox } from './nodes/AudioBox'; +import { ButtonType } from './nodes/button/FontIconBox'; import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView } from './nodes/DocumentView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; import { LinkDocPreview } from './nodes/LinkDocPreview'; import { RadialMenu } from './nodes/RadialMenu'; @@ -62,10 +66,6 @@ import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; -import { RichTextMenu } from './nodes/formattedText/RichTextMenu'; -import { ScriptField } from '../../fields/ScriptField'; -import { ButtonType } from './nodes/button/FontIconBox'; -import { ComponentDecorations } from './ComponentDecorations'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -76,21 +76,32 @@ export class MainView extends React.Component { @observable public LastButton: Opt; @observable private _windowWidth: number = 0; @observable private _windowHeight: number = 0; - @observable private _panelWidth: number = 0; - @observable private _panelHeight: number = 0; + @observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row) + @observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons @observable private _panelContent: string = "none"; @observable private _sidebarContent: any = this.userDoc?.sidebar; - @observable private _flyoutWidth: number = 0; + @observable private _leftMenuFlyoutWidth: number = 0; - @computed private get topOffset() { return 35 + Number(SEARCH_PANEL_HEIGHT.replace("px", "")); } //TODO remove - @computed private get leftOffset() { return this.menuPanelWidth() - 2; } + @computed private get dashboardTabHeight() { return 27; } // 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js + @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); } + @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); } + @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; } + @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; } @computed private get userDoc() { return Doc.UserDoc(); } @computed private get darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); } @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; } - @computed public get mainFreeform(): Opt { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } - - menuPanelWidth = () => Number(MENU_PANEL_WIDTH.replace("px", "")); - propertiesWidth = () => Math.max(0, Math.min(this._panelWidth - 50, CurrentUserUtils.propertiesWidth || 0)); + @computed public get mainFreeform(): Opt { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } + + topMenuHeight = () => 35; + topMenuWidth = returnZero; // value is ignored ... + leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", "")); + leftMenuHeight = () => this._dashUIHeight; + leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth; + leftMenuFlyoutHeight = () => this._dashUIHeight; + propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0)); + propertiesHeight = () => this._dashUIHeight; + mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth(); + mainDocViewHeight = () => this._dashUIHeight - this.topMenuHeight(); componentDidMount() { document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!)); @@ -264,11 +275,6 @@ export class MainView extends React.Component { Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder); } - getPWidth = () => this._panelWidth - this.propertiesWidth(); - getPHeight = () => this._panelHeight - (CollectionMenu.Instance?.Pinned ? 35 : 0); - getContentsHeight = () => this._panelHeight; - getMenuPanelHeight = () => this._panelHeight + (CollectionMenu.Instance?.Pinned ? 35 : 0); - @computed get mainDocView() { return { e.stopPropagation(); e.preventDefault(); }} - // style={{ minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`, width: `calc(100% - ${this._flyoutWidth + this.propertiesWidth()}px)` }}> - // FIXME update with property panel width + return
{ e.stopPropagation(); e.preventDefault(); }} style={{ - minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`, + minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`, transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined, }}> {!this.mainContainer ? (null) : this.mainDocView} @@ -312,22 +316,21 @@ export class MainView extends React.Component { @action onPropertiesPointerDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, - action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._panelWidth - e.clientX)) ? false : false), + action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false), action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)), - action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 250) : 0), false); + action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false); } @action onFlyoutPointerDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, - action(e => (this._flyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false), - () => this._flyoutWidth < 5 && this.closeFlyout(), + action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false), + () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(), this.closeFlyout); } - flyoutWidthFunc = () => this._flyoutWidth; - sidebarScreenToLocal = () => new Transform(0, -this.topOffset, 1); - mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftOffset, 0); + sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1); + mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0); addDocTabFunc = (doc: Doc, where: string): boolean => { return where === "close" ? CollectionDockingView.CloseSplit(doc) : doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddSplit(doc, "right"); @@ -335,10 +338,10 @@ export class MainView extends React.Component { @computed get flyout() { - return !this._flyoutWidth ?
+ return !this._leftMenuFlyoutWidth ?
{this.docButtons}
: -
+
; } - @computed get menuPanel() { - return
+ @computed get leftMenuPanel() { + return
{ const title = StrCast(Doc.GetProto(button).title); - const willOpen = !this._flyoutWidth || this._panelContent !== title; + const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title; this.closeFlyout(); if (willOpen) { switch (this._panelContent = title) { @@ -422,38 +425,41 @@ export class MainView extends React.Component { } @computed get mainInnerContent() { - const width = this.propertiesWidth() + this._flyoutWidth + this.menuPanelWidth(); - const transform = this._flyoutWidth ? 'translate(-28px, 0px)' : undefined; + const width = this.propertiesWidth() + this._leftMenuFlyoutWidth + this.leftMenuWidth(); + const transform = this._leftMenuFlyoutWidth ? 'translate(-28px, 0px)' : undefined; return <> - {this.menuPanel} + {this.leftMenuPanel}
{this.flyout} -
+
- + {this.dockingContent} -
+
- {this.propertiesWidth() < 10 ? (null) : } + {this.propertiesWidth() < 10 ? (null) : }
; } - @computed get mainContent() { + @computed get mainDashboardArea() { return !this.userDoc ? (null) : -
{ - r && new _global.ResizeObserver(action(() => { this._panelWidth = r.getBoundingClientRect().width; this._panelHeight = r.getBoundingClientRect().height; })).observe(r); +
{ + r && new _global.ResizeObserver(action(() => { + this._dashUIWidth = r.getBoundingClientRect().width; + this._dashUIHeight = r.getBoundingClientRect().height; + })).observe(r); }} style={{ color: this.darkScheme ? "rgb(205,205,205)" : "black", - height: `calc(100% - ${this.topOffset - 35}px)`, + height: `calc(100% - ${this.topOfDashUI}px)`, width: "100%", }} > {this.mainInnerContent} @@ -461,7 +467,7 @@ export class MainView extends React.Component { } expandFlyout = action((button: Doc) => { - this._flyoutWidth = (this._flyoutWidth || 250); + this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250); this._sidebarContent.proto = button.target as any; this.LastButton = button; console.log(button.title); @@ -471,7 +477,7 @@ export class MainView extends React.Component { this.LastButton = undefined; this._panelContent = "none"; this._sidebarContent.proto = undefined; - this._flyoutWidth = 0; + this._leftMenuFlyoutWidth = 0; }); remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); @@ -509,8 +515,8 @@ export class MainView extends React.Component { pinToPres={emptyFunction} removeDocument={this.remButtonDoc} ScreenToLocalTransform={this.buttonBarXf} - PanelWidth={this.flyoutWidthFunc} - PanelHeight={this.getContentsHeight} + PanelWidth={this.leftMenuFlyoutWidth} + PanelHeight={this.leftMenuFlyoutHeight} renderDepth={0} focus={DocUtils.DefaultFocus} whenChildContentsActiveChanged={emptyFunction} @@ -606,14 +612,14 @@ export class MainView extends React.Component { - - {/* 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js */} + + {this.topbar} {LinkDescriptionPopup.descriptionPopup ? : null} {DocumentLinksButton.LinkEditorDocView ? : (null)} {LinkDocPreview.LinkInfo ? : (null)} - {this.mainContent} + {this.mainDashboardArea} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 6ffa6c279..8e03b2db2 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -42,8 +42,13 @@ import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { TabDocView } from "./TabDocView"; import { Colors } from "../global/globalEnums"; +interface CollectionMenuProps { + panelHeight: () => number; + panelWidth: () => number; +} + @observer -export class CollectionMenu extends AntimodeMenu { +export class CollectionMenu extends AntimodeMenu{ @observable static Instance: CollectionMenu; @observable SelectedCollection: DocumentView | undefined; @@ -93,13 +98,10 @@ export class CollectionMenu extends AntimodeMenu { return new Transform(-translateX, -translateY, 1 / scale); } - panelWidth100 = () => 100; - panelHeight35 = () => 35; - @computed get contMenuButtons() { trace(); const selDoc = Doc.UserDoc().contextMenuBtns; - return !(selDoc instanceof Doc) ? (null) :
+ return !(selDoc instanceof Doc) ? (null) :
{ pinToPres={emptyFunction} removeDocument={returnFalse} ScreenToLocalTransform={this.buttonBarXf} - PanelWidth={this.panelWidth100} - PanelHeight={this.panelHeight35} + PanelWidth={this.props.panelWidth} + PanelHeight={this.props.panelHeight} renderDepth={0} focus={emptyFunction} whenChildContentsActiveChanged={emptyFunction} @@ -176,7 +178,7 @@ export class CollectionMenu extends AntimodeMenu { } } -interface CollectionMenuProps { +interface CollectionViewMenuProps { type: CollectionViewType; fieldKey: string; docView: DocumentView; @@ -185,7 +187,7 @@ interface CollectionMenuProps { const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); @observer -export class CollectionViewBaseChrome extends React.Component { +export class CollectionViewBaseChrome extends React.Component { //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\) get document() { return this.props.docView?.props.Document; } @@ -628,14 +630,14 @@ export class CollectionViewBaseChrome extends React.Component { +export class CollectionDockingChrome extends React.Component { render() { return (null); } } @observer -export class CollectionFreeFormViewChrome extends React.Component { +export class CollectionFreeFormViewChrome extends React.Component { public static Instance: CollectionFreeFormViewChrome; constructor(props: any) { super(props); @@ -866,7 +868,7 @@ export class CollectionFreeFormViewChrome extends React.Component { +export class CollectionStackingViewChrome extends React.Component { @observable private _currentKey: string = ""; @observable private suggestions: string[] = []; @@ -987,7 +989,7 @@ export class CollectionStackingViewChrome extends React.Component { +export class CollectionSchemaViewChrome extends React.Component { // private _textwrapAllRows: boolean = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []).length > 0; get document() { return this.props.docView.props.Document; } @@ -1035,7 +1037,7 @@ export class CollectionSchemaViewChrome extends React.Component { +export class CollectionTreeViewChrome extends React.Component { get document() { return this.props.docView.props.Document; } get sortAscending() { @@ -1072,7 +1074,7 @@ export class CollectionTreeViewChrome extends React.Component { +export class Collection3DCarouselViewChrome extends React.Component { get document() { return this.props.docView.props.Document; } @computed get scrollSpeed() { return this.document._autoScrollSpeed; @@ -1113,7 +1115,7 @@ export class Collection3DCarouselViewChrome extends React.Component { +export class CollectionGridViewChrome extends React.Component { private clicked: boolean = false; private entered: boolean = false; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4d62a1af4..624a0bf4a 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -267,16 +267,17 @@ export class CollectionTreeView extends CollectionSubView 35; @computed get buttonMenu() { - const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); + const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null); // To create a multibutton menu add a CollectionLinearView - if (menuDoc){ - + if (menuDoc) { + const width: number = NumCast(menuDoc._width, 30); const height: number = NumCast(menuDoc._height, 30); console.log(menuDoc.title, width, height); return (
+ style={{ width: width, height: height }}> 35} - PanelHeight={() => 35} + PanelWidth={this.return35} + PanelHeight={this.return35} renderDepth={this.props.renderDepth + 1} focus={emptyFunction} styleProvider={this.props.styleProvider} @@ -302,13 +303,14 @@ export class CollectionTreeView extends CollectionSubView
); } } - + @observable _explainerHeight: number = 0; + @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); } @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); } @@ -336,30 +338,30 @@ export class CollectionTreeView extends CollectionSubView - {this.titleBar} -
- {buttonMenu || noviceExplainer ?
- {buttonMenu ? this.buttonMenu : null} - {Doc.UserDoc().noviceMode && noviceExplainer ? -
- {noviceExplainer} -
- : null - } -
: null} -
e.stopPropagation()} - onDrop={this.onTreeDrop} - ref={this.createTreeDropTarget}> -
    - {this.treeViewElements} -
-
-
- ; + <> + {this.titleBar} +
+ {buttonMenu || noviceExplainer ?
r && (this._explainerHeight = r.getBoundingClientRect().height))}> + {buttonMenu ? this.buttonMenu : null} + {Doc.UserDoc().noviceMode && noviceExplainer ? +
+ {noviceExplainer} +
+ : null + } +
: null} +
e.stopPropagation()} + onDrop={this.onTreeDrop} + ref={this.createTreeDropTarget}> +
    + {this.treeViewElements} +
+
+
+ ; } } \ No newline at end of file diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index aa7b164b0..4fc25752f 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -869,7 +869,7 @@ export class TreeView extends React.Component { const childLayout = Doc.Layout(pair.layout); const rowHeight = () => { const aspect = Doc.NativeAspect(childLayout); - return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym](); + return (aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]()); }; return treeViewRefs.set(child, r ? r : undefined)} document={pair.layout} diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss index caa9f4fe5..95bd44c1f 100644 --- a/src/client/views/global/globalCssVariables.scss +++ b/src/client/views/global/globalCssVariables.scss @@ -54,7 +54,7 @@ $standard-border-radius: 3px; $standard-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3); -$searchpanel-height: 32px; +$dashboardselector-height: 32px; $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc $docDecorations-zindex: 998; // then doc decorations appear over everything else $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? @@ -63,7 +63,7 @@ $SCHEMA_DIVIDER_WIDTH: 4; $MINIMIZED_ICON_SIZE: 24; $MAX_ROW_HEIGHT: 44px; $DFLT_IMAGE_NATIVE_DIM: 900px; -$MENU_PANEL_WIDTH: 60px; +$LEFT_MENU_WIDTH: 60px; $TREE_BULLET_WIDTH: 20px; :export { @@ -74,8 +74,8 @@ $TREE_BULLET_WIDTH: 20px; MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT; SEARCH_THUMBNAIL_SIZE: $search-thumnail-size; ANTIMODEMENU_HEIGHT: $antimodemenu-height; - SEARCH_PANEL_HEIGHT: $searchpanel-height; + DASHBOARD_SELECTOR_HEIGHT: $dashboardselector-height; DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM; - MENU_PANEL_WIDTH: $MENU_PANEL_WIDTH; + LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH; TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH; } \ No newline at end of file diff --git a/src/client/views/global/globalCssVariables.scss.d.ts b/src/client/views/global/globalCssVariables.scss.d.ts index 11e62e1eb..59c2b3585 100644 --- a/src/client/views/global/globalCssVariables.scss.d.ts +++ b/src/client/views/global/globalCssVariables.scss.d.ts @@ -7,9 +7,9 @@ interface IGlobalScss { MAX_ROW_HEIGHT: string; SEARCH_THUMBNAIL_SIZE: string; ANTIMODEMENU_HEIGHT: string; - SEARCH_PANEL_HEIGHT: string; + DASHBOARD_SELECTOR_HEIGHT: string; DFLT_IMAGE_NATIVE_DIM: string; - MENU_PANEL_WIDTH: string; + LEFT_MENU_WIDTH: string; TREE_BULLET_WIDTH: string; } declare const globalCssVariables: IGlobalScss; -- cgit v1.2.3-70-g09d2 From 72e6023a199fc859cc84c5d22bb12e948d4a471b Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 14 Sep 2021 23:10:06 -0400 Subject: added a deleteFolder option for empty folders in the filesystem --- src/client/views/collections/TreeView.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 4fc25752f..6bb7fb748 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -244,6 +244,9 @@ export class TreeView extends React.Component { TreeView._editTitleOnLoad = { id: folder[Id], parent: this.props.parentTreeView }; return this.props.addDocument(folder); } + deleteFolder = () => { + return this.props.removeDoc?.(this.doc); + } preTreeDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => { const dragData = de.complete.docDragData; @@ -513,9 +516,11 @@ export class TreeView extends React.Component { } contextMenuItems = () => { const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, icon: "folder-plus", label: "New Folder" }; + const deleteFolder = { script: ScriptField.MakeFunction(`scriptContext.deleteFolder()`, { scriptContext: "any" })!, icon: "folder-plus", label: "Delete Folder" }; + const folderOp = this.childDocs?.length ? makeFolder : deleteFolder; const openAlias = { script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, icon: "copy", label: "Open Alias" }; const focusDoc = { script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, icon: "eye", label: "Focus or Open" }; - return [...this.props.contextMenuItems.filter(mi => !mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result), ... (this.doc.isFolder ? [makeFolder] : + return [...this.props.contextMenuItems.filter(mi => !mi.filter ? true : mi.filter.script.run({ doc: this.doc })?.result), ... (this.doc.isFolder ? [folderOp] : Doc.IsSystem(this.doc) ? [] : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ? [openAlias, makeFolder] : -- cgit v1.2.3-70-g09d2 From e1533161b473f31544d018432abc8a9c8d4d0bfc Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 14 Sep 2021 23:16:17 -0400 Subject: fixed treeviews so that in filesys mode you can't indent a document into anything other than a folder. --- src/client/views/collections/TreeView.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 6bb7fb748..97de097e0 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -858,6 +858,7 @@ export class TreeView extends React.Component { } const dentDoc = (editTitle: boolean, newParent: Doc, addAfter: Doc | undefined, parent: TreeView | CollectionTreeView | undefined) => { + if (parent instanceof TreeView && parent.props.treeView.fileSysMode && !newParent.isFolder) return; const fieldKey = Doc.LayoutFieldKey(newParent); if (remove && fieldKey && Cast(newParent[fieldKey], listSpec(Doc)) !== undefined) { remove(child); -- cgit v1.2.3-70-g09d2 From eb50e46332c2f0b48c7cb165d55245aab317ef08 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 21 Sep 2021 19:43:32 -0400 Subject: fixed up some darkScheme css, enabled comic mode for developers, enabled opening up fields on dashboards in myDocuments --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 30 ++++++++++------ src/client/util/SelectionManager.ts | 14 ++------ src/client/util/SettingsManager.tsx | 19 +++++----- src/client/views/ContextMenu.scss | 1 - src/client/views/DocumentDecorations.scss | 28 +++++++++++---- src/client/views/DocumentDecorations.tsx | 42 +++++++++++++--------- src/client/views/MainView.scss | 12 +++---- src/client/views/MainView.tsx | 14 ++++---- src/client/views/StyleProvider.tsx | 5 +-- .../views/collections/CollectionSchemaView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 9 +++-- .../CollectionFreeFormLayoutEngines.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 ++- .../collectionSchema/CollectionSchemaView.tsx | 7 ++-- src/client/views/nodes/DocumentView.tsx | 6 ++-- src/client/views/nodes/button/FontIconBox.tsx | 2 -- .../views/nodes/formattedText/DashDocView.tsx | 3 +- src/mobile/MobileInterface.tsx | 4 +-- 19 files changed, 118 insertions(+), 89 deletions(-) (limited to 'src/client/views/collections/TreeView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index fafbc4a7d..206f65bfd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -862,7 +862,7 @@ export namespace Docs { export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { const tabs = TreeDocument(documents, { title: "On-Screen Tabs", childDontRegisterViews: true, freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", _fitWidth: true, system: true, isFolder: true }); const all = TreeDocument([], { title: "Off-Screen Tabs", childDontRegisterViews: true, freezeChildren: "add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", system: true, isFolder: true }); - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); } export function DirectoryImportDocument(options: DocumentOptions = {}) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d5dc9e2be..568a9ddbd 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -20,6 +20,7 @@ import { Networking } from "../Network"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView"; import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; +import { TreeView } from "../views/collections/TreeView"; import { Colors } from "../views/global/globalEnums"; import { MainView } from "../views/MainView"; import { ButtonType, NumButtonType } from "../views/nodes/button/FontIconBox"; @@ -38,7 +39,6 @@ import { ColorScheme } from "./SettingsManager"; import { SharingManager } from "./SharingManager"; import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; -import { TreeView } from "../views/collections/TreeView"; interface Button { title?: string; @@ -816,16 +816,19 @@ export class CurrentUserUtils { _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", treeViewType: "fileSystem", isFolder: true, system: true, explainer: "This is your collection of dashboards. A dashboard represents the tab configuration of your workspace. To manage documents as folders, go to the Files." })); - // const toggleTheme = ScriptField.MakeScript(`Doc.UserDoc().darkScheme = !Doc.UserDoc().darkScheme`); - // const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); - // const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`); + const toggleDarkTheme = ScriptField.MakeScript(`this.colorScheme = this.colorScheme ? undefined : "${ColorScheme.Dark}"`); + const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); + const snapshotDashboard = ScriptField.MakeScript(`snapshotDashboard()`); const shareDashboard = ScriptField.MakeScript(`shareDashboard(self)`); const removeDashboard = ScriptField.MakeScript('removeDashboard(self)'); - (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, shareDashboard!, removeDashboard!]); - (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Share Dashboard", "Remove Dashboard"]); - (doc.myDashboards as any as Doc).childContextMenuIcons = new List(["plus", "user-friends", "times"]); - // (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, toggleTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]); - // (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]); + const developerFilter = ScriptField.MakeFunction('!IsNoviceMode()'); + // (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, shareDashboard!, removeDashboard!]); + // (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Share Dashboard", "Remove Dashboard"]); + // (doc.myDashboards as any as Doc).childContextMenuIcons = new List(["plus", "user-friends", "times"]); + (doc.myDashboards as any as Doc).childContextMenuScripts = new List([newDashboard!, toggleDarkTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]); + (doc.myDashboards as any as Doc).childContextMenuLabels = new List(["Create New Dashboard", "Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]); + (doc.myDashboards as any as Doc).childContextMenuIcons = new List(["plus", "chalkboard", "tv", "camera", "users", "times"]); + (doc.myDashboards as any as Doc).childContextMenuFilters = new List([undefined as any, developerFilter, developerFilter, developerFilter, undefined as any, undefined as any]); } return doc.myDashboards as any as Doc; } @@ -1302,7 +1305,6 @@ export class CurrentUserUtils { }, { fireImmediately: true }); // Document properties on load doc.system = true; - doc.darkScheme = ColorScheme.Dark; doc.noviceMode = doc.noviceMode === undefined ? "true" : doc.noviceMode; doc.title = Doc.CurrentUserEmail; doc._raiseWhenDragged = true; @@ -1321,7 +1323,6 @@ export class CurrentUserUtils { doc.fontColor = StrCast(doc.fontColor, "black"); doc.fontHighlight = StrCast(doc.fontHighlight, ""); doc.defaultAclPrivate = BoolCast(doc.defaultAclPrivate, false); - doc.activeCollectionBackground = StrCast(doc.activeCollectionBackground, "white"); doc.activeCollectionNestedBackground = Cast(doc.activeCollectionNestedBackground, "string", null); doc.noviceMode = BoolCast(doc.noviceMode, true); doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); // @@ -1358,6 +1359,10 @@ export class CurrentUserUtils { // }); setTimeout(() => DocServer.UPDATE_SERVER_CACHE(), 2500); doc.fieldInfos = await Docs.setupFieldInfos(); + if (doc.activeDashboard instanceof Doc) { + // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss) + doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme; + } return doc; } @@ -1637,4 +1642,7 @@ Scripting.addGlobal(function makeTopLevelFolder() { const folder = Docs.Create.TreeDocument([], { title: "Untitled folder", _stayInCollection: true, isFolder: true }); TreeView._editTitleOnLoad = { id: folder[Id], parent: undefined }; return Doc.AddDocToList(Doc.UserDoc().myFilesystem as Doc, "data", folder); +}); +Scripting.addGlobal(function toggleComicMode() { + Doc.UserDoc().renderStyle = Doc.UserDoc().renderStyle === "comic" ? undefined : "comic"; }); \ No newline at end of file diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index bac13373c..e507ec3bf 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -2,7 +2,6 @@ import { action, observable, ObservableMap } from "mobx"; import { computedFn } from "mobx-utils"; import { Doc, Opt } from "../../fields/Doc"; import { DocumentType } from "../documents/DocumentTypes"; -import { CollectionSchemaView } from "../views/collections/collectionSchema/CollectionSchemaView"; import { CollectionViewType } from "../views/collections/CollectionView"; import { DocumentView } from "../views/nodes/DocumentView"; @@ -13,12 +12,10 @@ export namespace SelectionManager { @observable IsDragging: boolean = false; SelectedViews: ObservableMap = new ObservableMap(); @observable SelectedSchemaDocument: Doc | undefined; - @observable SelectedSchemaCollection: CollectionSchemaView | undefined; @action - SelectSchemaView(collectionView: Opt, doc: Opt) { + SelectSchemaViewDoc(doc: Opt) { manager.SelectedSchemaDocument = doc; - manager.SelectedSchemaCollection = collectionView; } @action SelectView(docView: DocumentView, ctrlPressed: boolean): void { @@ -33,7 +30,6 @@ export namespace SelectionManager { } else if (!ctrlPressed && Array.from(manager.SelectedViews.entries()).length > 1) { Array.from(manager.SelectedViews.keys()).map(dv => dv !== docView && dv.props.whenChildContentsActiveChanged(false)); manager.SelectedSchemaDocument = undefined; - manager.SelectedSchemaCollection = undefined; manager.SelectedViews.clear(); manager.SelectedViews.set(docView, docView.rootDoc); } @@ -47,7 +43,6 @@ export namespace SelectionManager { } @action DeselectAll(): void { - manager.SelectedSchemaCollection = undefined; manager.SelectedSchemaDocument = undefined; Array.from(manager.SelectedViews.keys()).map(dv => dv.props.whenChildContentsActiveChanged(false)); manager.SelectedViews.clear(); @@ -62,8 +57,8 @@ export namespace SelectionManager { export function SelectView(docView: DocumentView, ctrlPressed: boolean): void { manager.SelectView(docView, ctrlPressed); } - export function SelectSchemaView(colSchema: Opt, document: Opt): void { - manager.SelectSchemaView(colSchema, document); + export function SelectSchemaViewDoc(document: Opt): void { + manager.SelectSchemaViewDoc(document); } const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) { // wrapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed @@ -96,9 +91,6 @@ export namespace SelectionManager { export function SelectedSchemaDoc(): Doc | undefined { return manager.SelectedSchemaDocument; } - export function SelectedSchemaCollection(): CollectionSchemaView | undefined { - return manager.SelectedSchemaCollection; - } export function Docs(): Doc[] { return Array.from(manager.SelectedViews.values()).filter(doc => doc?._viewType !== CollectionViewType.Docking); } diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index bd91db779..6a26dfdc7 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -19,9 +19,9 @@ export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; export enum ColorScheme { - Dark = "Dark", - Light = "Light", - System = "Match System" + Dark = "-Dark", + Light = "-Light", + System = "-MatchSystem" } @observer @@ -38,7 +38,7 @@ export class SettingsManager extends React.Component<{}> { @observable activeTab = "Accounts"; @computed get backgroundColor() { return Doc.UserDoc().activeCollectionBackground; } - @computed get colorScheme() { return Doc.UserDoc().colorScheme; } + @computed get colorScheme() { return CurrentUserUtils.ActiveDashboard.colorScheme; } constructor(props: {}) { super(props); @@ -81,16 +81,16 @@ export class SettingsManager extends React.Component<{}> { const scheme: ColorScheme = (e.currentTarget as any).value; switch (scheme) { case ColorScheme.Light: - Doc.UserDoc().colorScheme = ColorScheme.Light; + CurrentUserUtils.ActiveDashboard.colorScheme = undefined; // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss) addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "#d3d3d3 !important" }); break; case ColorScheme.Dark: - Doc.UserDoc().colorScheme = ColorScheme.Dark; + CurrentUserUtils.ActiveDashboard.colorScheme = ColorScheme.Dark; addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "black !important" }); break; case ColorScheme.System: default: window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { - Doc.UserDoc().colorScheme = e.matches ? ColorScheme.Dark : ColorScheme.Light; + CurrentUserUtils.ActiveDashboard.colorScheme = e.matches ? ColorScheme.Dark : undefined; // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss) }); break; } @@ -119,6 +119,7 @@ export class SettingsManager extends React.Component<{}> {
; const colorSchemes = [ColorScheme.Light, ColorScheme.Dark, ColorScheme.System]; + const schemeMap = ["Light", "Dark", "Match system"]; return
@@ -132,8 +133,8 @@ export class SettingsManager extends React.Component<{}> {
Color Scheme
- + {colorSchemes.map((scheme, i) => )}
diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 47ae0424b..ea24dbf6d 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -8,7 +8,6 @@ flex-direction: column; background: whitesmoke; border-radius: 3px; - border: solid $light-gray 1px; } // .contextMenu-item:first-child { diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index a9f50f81b..d8ad47ecb 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -2,10 +2,14 @@ $linkGap: 3px; +.documentDecorations-Dark, .documentDecorations { position: absolute; z-index: 2000; } +.documentDecorations-Dark { + background: dimgray; +} .documentDecorations-container { z-index: $docDecorations-zindex; position: absolute; @@ -50,12 +54,17 @@ $linkGap: 3px; pointer-events: auto; background: $medium-gray; opacity: 0.1; - &:hover { opacity: 1; } } + .documentDecorations-resizer-Dark + { + background: $light-gray; + opacity: 0.2; + } + .documentDecorations-topLeftResizer, .documentDecorations-leftResizer, .documentDecorations-bottomLeftResizer { @@ -221,6 +230,7 @@ $linkGap: 3px; cursor: ns-resize; } + .documentDecorations-title-Dark, .documentDecorations-title { opacity: 1; grid-column-start: 2; @@ -233,14 +243,22 @@ $linkGap: 3px; height: 22px; position: absolute; - .documentDecorations-titleSpan { + .documentDecorations-titleSpan, + .documentDecorations-titleSpan-Dark { width: 100%; border-radius: 8px; - background: #ffffffcf; + background: #ffffffa0; position: absolute; display: inline-block; cursor: move; } + .documentDecorations-titleSpan-Dark { + background: hsla(0, 0%, 0%, 0.412); + } + } + .documentDecorations-title-Dark { + color: white; + background: black; } .documentDecorations-contextMenu { @@ -439,10 +457,6 @@ $linkGap: 3px; } } -.documentDecorations-darkScheme { - background: dimgray; -} - #template-list { position: absolute; top: 25px; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d785d5419..e9a54d6a5 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -8,7 +8,7 @@ import { AclAdmin, AclEdit, DataSym, Doc, DocListCast, Field, HeightSym, WidthSy import { Document } from '../../fields/documentSchemas'; import { InkField } from "../../fields/InkField"; import { ScriptField } from '../../fields/ScriptField'; -import { Cast, NumCast } from "../../fields/Types"; +import { Cast, NumCast, StrCast } from "../../fields/Types"; import { GetEffectiveAcl } from '../../fields/util'; import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../Utils"; import { Docs } from "../documents/Documents"; @@ -27,6 +27,8 @@ import { LightboxView } from './LightboxView'; import { DocumentView } from "./nodes/DocumentView"; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import React = require("react"); +import { dark } from '@material-ui/core/styles/createPalette'; +import { color } from 'd3-color'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number, PanelHeight: number, boundsLeft: number, boundsTop: number }, { value: string }> { @@ -241,7 +243,8 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P InkStrokeProperties.Instance?._lock && SelectionManager.Views().filter(dv => dv.rootDoc.type === DocumentType.INK) .forEach(dv => fixedAspect = Doc.NativeAspect(dv.rootDoc)); - if (fixedAspect && (this._resizeHdlId === "documentDecorations-bottomRightResizer" || this._resizeHdlId === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles + const resizeHdl = this._resizeHdlId.split(" ")[0]; + if (fixedAspect && (resizeHdl === "documentDecorations-bottomRightResizer" || resizeHdl === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles const project = (p: number[], a: number[], b: number[]) => { const atob = [b[0] - a[0], b[1] - a[1]]; const atop = [p[0] - a[0], p[1] - a[1]]; @@ -264,7 +267,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P this._snapY = thisPt.y; let dragBottom = false, dragRight = false, dragBotRight = false; let dX = 0, dY = 0, dW = 0, dH = 0; - switch (this._resizeHdlId) { + switch (this._resizeHdlId.split(" ")[0]) { case "": break; case "documentDecorations-topLeftResizer": dX = -1; @@ -437,11 +440,17 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
); + const colorScheme = StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); const titleArea = this._edtingTitle ? - this.titleBlur()} onChange={action(e => this._accumulatedTitle = e.target.value)} onKeyPress={this.titleEntered} /> : + this.titleBlur()} + onChange={action(e => this._accumulatedTitle = e.target.value)} + onKeyPress={this.titleEntered} /> :
- {`${this.selectionTitle}`} + {`${this.selectionTitle}`}
; let inMainMenuPanel = false; @@ -457,8 +466,9 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P bounds.b = Math.max(bounds.y, Math.max(topBounds, Math.min(window.innerHeight, bounds.b + this._resizeBorderWidth / 2 + this._linkBoxHeight) - this._resizeBorderWidth / 2 - this._linkBoxHeight)); const useRotation = seldoc.rootDoc.type === DocumentType.INK; + const resizerScheme = colorScheme ? "documentDecorations-resizer" + colorScheme : ""; - return (
+ return (
{SelectionManager.Views().length !== 1 || hideTitle ? (null) : topBtn("iconify", `window-${seldoc.finalLayoutKey.includes("icon") ? "restore" : "minimize"}`, undefined, this.onIconifyClick, `${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`)} -
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> -
-
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> -
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
+
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> +
e.preventDefault()} /> {seldoc.props.renderDepth <= 1 || !seldoc.props.ContainingCollectionView ? (null) : topBtn("selector", "arrow-alt-circle-up", undefined, this.onSelectorClick, "tap to select containing document")} diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 4f871f5ec..7fa841002 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -41,7 +41,7 @@ } .mainView-container, -.mainView-container-dark { +.mainView-container-Dark { width: 100%; height: 100%; position: absolute; @@ -65,7 +65,7 @@ } } -.mainView-container-dark { +.mainView-container-Dark { color: $light-gray; .lm_goldenlayout { @@ -91,7 +91,7 @@ .contextMenu-cont, .contextMenu-item { - background: $medium-gray; + background: $dark-gray; } .contextMenu-item:hover { @@ -144,7 +144,7 @@ } } -.mainView-innerContent, .mainView-innerContent-dark { +.mainView-innerContent, .mainView-innerContent-Dark { display: contents; flex-direction: row; position: relative; @@ -175,7 +175,7 @@ .mainView-libraryHandle { background-color: $light-gray; } -.mainView-innerContent-dark +.mainView-innerContent-Dark { .propertiesView { background-color: #252525; @@ -198,7 +198,7 @@ background: #353535; } } -.mainView-container-dark { +.mainView-container-Dark { .contextMenu-cont { background: $medium-gray; color: $white; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d854f118f..c99ba447c 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -26,7 +26,7 @@ import { HistoryUtil } from '../util/History'; import { Hypothesis } from '../util/HypothesisUtils'; import { Scripting } from '../util/Scripting'; import { SelectionManager } from '../util/SelectionManager'; -import { SettingsManager } from '../util/SettingsManager'; +import { SettingsManager, ColorScheme } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { SnappingManager } from '../util/SnappingManager'; import { Transform } from '../util/Transform'; @@ -88,7 +88,7 @@ export class MainView extends React.Component { @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; } @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; } @computed private get userDoc() { return Doc.UserDoc(); } - @computed private get darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); } + @computed private get colorScheme() { return StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); } @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; } @computed public get mainFreeform(): Opt { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } @@ -430,10 +430,10 @@ export class MainView extends React.Component { const transform = this._leftMenuFlyoutWidth ? 'translate(-28px, 0px)' : undefined; return <> {this.leftMenuPanel} -
+
{this.flyout}
- +
@@ -441,7 +441,7 @@ export class MainView extends React.Component { {this.dockingContent}
- +
{this.propertiesWidth() < 10 ? (null) : } @@ -459,7 +459,7 @@ export class MainView extends React.Component { this._dashUIHeight = r.getBoundingClientRect().height; })).observe(r); }} style={{ - color: this.darkScheme ? "rgb(205,205,205)" : "black", + color: this.colorScheme === ColorScheme.Dark ? "rgb(205,205,205)" : "black", height: `calc(100% - ${this.topOfDashUI}px)`, width: "100%", }} > @@ -601,7 +601,7 @@ export class MainView extends React.Component { } render() { - return (
((ele) => ele.scrollTop = ele.scrollLeft = 0)(document.getElementById("root")!)} ref={r => { r && new _global.ResizeObserver(action(() => { this._windowWidth = r.getBoundingClientRect().width; this._windowHeight = r.getBoundingClientRect().height; })).observe(r); diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 3c88a4830..1eb7a222e 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -22,6 +22,7 @@ import "./StyleProvider.scss"; import React = require("react"); import Color = require('color'); import { lightOrDark } from '../../Utils'; +import { ColorScheme } from '../util/SettingsManager'; export enum StyleLayers { Background = "background" @@ -49,7 +50,7 @@ export enum StyleProp { FontSize = "fontSize", // size of text font } -function darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); } +function darkScheme() { return CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark; } function toggleBackground(doc: Doc) { UndoManager.RunInBatch(() => runInAction(() => { @@ -143,7 +144,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt 0 ? Doc.UserDoc().activeCollectionNestedBackground : - Doc.UserDoc().activeCollectionBackground))); + Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE)))); break; //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 6a22acae8..3ea190a98 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -353,7 +353,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setFocused = (doc: Doc) => this._focusedTable = doc; @action setPreviewDoc = (doc: Opt) => { - SelectionManager.SelectSchemaView(this, doc); + SelectionManager.SelectSchemaViewDoc(doc); this._previewDoc = doc; } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 97de097e0..a3da0e0e4 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -481,13 +481,16 @@ export class TreeView extends React.Component { } @computed get validExpandViewTypes() { - if (this.doc.viewType === CollectionViewType.Docking) return [this.fieldKey]; + if (this.props.treeView.dashboardMode && Doc.UserDoc().noviceMode) { + return [this.doc.viewType === CollectionViewType.Docking ? this.fieldKey : "layout"]; + } const annos = () => DocListCast(this.doc[this.fieldKey + "-annotations"]).length ? "annotations" : ""; const links = () => DocListCast(this.doc.links).length ? "links" : ""; - const data = () => this.childDocs && !this.props.treeView.dashboardMode ? this.fieldKey : ""; + const data = () => this.childDocs ? this.fieldKey : ""; const aliases = () => this.props.treeView.dashboardMode ? "" : "aliases"; const fields = () => Doc.UserDoc().noviceMode ? "" : "fields"; - return [data(), "layout", ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m); + const layout = this.doc.viewType === CollectionViewType.Docking ? [] : ["layout"]; + return [data(), ...layout, ...(this.props.treeView.fileSysMode ? [aliases(), links(), annos()] : []), fields()].filter(m => m); } @action expandNextviewType = () => { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 37444a9dc..b3c57d33a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -7,6 +7,7 @@ import { Cast, NumCast, StrCast } from "../../../../fields/Types"; import { aggregateBounds } from "../../../../Utils"; import { CurrentUserUtils } from "../../../util/CurrentUserUtils"; import React = require("react"); +import { ColorScheme } from "../../../util/SettingsManager"; export interface ViewDefBounds { type: string; @@ -361,7 +362,7 @@ export function computeTimelineLayout( groupNames.push({ type: "text", text: toLabel(Math.ceil(maxTime)), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize, payload: undefined }); } - const divider = { type: "div", color: CurrentUserUtils.ActiveDashboard?.darkScheme ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined }; + const divider = { type: "div", color: CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "dimGray" : "black", x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined }; return normalizeResults(panelDim, fontHeight, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]); function layoutDocsAtTime(keyDocs: Doc[], key: number) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 94cf1c5a6..0b12f6c21 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -51,6 +51,7 @@ import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import Color = require("color"); +import { ColorScheme } from "../../../util/SettingsManager"; export const panZoomSchema = createSchema({ _panX: "number", @@ -1419,6 +1420,7 @@ export class CollectionFreeFormView extends CollectionSubView { const ctx = el?.getContext('2d'); @@ -1429,7 +1431,7 @@ export class CollectionFreeFormView extends CollectionSubView 50 ? [3, 3] : [1, 5]); ctx.clearRect(0, 0, w, h); if (ctx) { - ctx.strokeStyle = "rgba(0, 0, 0, 0.5)"; + ctx.strokeStyle = strokeStyle; ctx.beginPath(); for (let x = Cx - renderGridSpace; x <= w - Cx; x += renderGridSpace) { ctx.moveTo(x, Cy - h); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index dfe99ffc8..12493ecc1 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -337,8 +337,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { {this.renderTypes(this._col)} {this.renderColors(this._col)}
- +
; } @@ -353,7 +354,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setFocused = (doc: Doc) => this._focusedTable = doc; @action setPreviewDoc = (doc: Opt) => { - SelectionManager.SelectSchemaView(this, doc); + SelectionManager.SelectSchemaViewDoc(doc); this._previewDoc = doc; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3e15ed661..5d0b91b91 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -25,7 +25,6 @@ import { InteractionUtils } from '../../util/InteractionUtils'; import { LinkManager } from '../../util/LinkManager'; import { Scripting } from '../../util/Scripting'; import { SelectionManager } from "../../util/SelectionManager"; -import { ColorScheme } from "../../util/SettingsManager"; import { SharingManager } from '../../util/SharingManager'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from "../../util/Transform"; @@ -50,6 +49,7 @@ import { ScriptingBox } from "./ScriptingBox"; import { PresBox } from './trails/PresBox'; import React = require("react"); import { IconProp } from "@fortawesome/fontawesome-svg-core"; +import { ColorScheme } from "../../util/SettingsManager"; const { Howl } = require('howler'); interface Window { @@ -1061,9 +1061,7 @@ export class DocumentViewInternal extends DocComponent(Fon render() { const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); - const dark: boolean = Doc.UserDoc().colorScheme === ColorScheme.Dark; const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index e519de1c5..149836e93 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -12,6 +12,7 @@ import { FormattedTextBox } from "./FormattedTextBox"; import React = require("react"); import * as ReactDOM from 'react-dom'; import { observer } from "mobx-react"; +import { ColorScheme } from "../../../util/SettingsManager"; export class DashDocView { _fieldWrapper: HTMLSpanElement; // container for label and value @@ -20,7 +21,7 @@ export class DashDocView { this._fieldWrapper = document.createElement("span"); this._fieldWrapper.style.position = "relative"; this._fieldWrapper.style.textIndent = "0"; - this._fieldWrapper.style.border = "1px solid " + StrCast(tbox.layoutDoc.color, (CurrentUserUtils.ActiveDashboard.darkScheme ? "dimGray" : "lightGray")); + this._fieldWrapper.style.border = "1px solid " + StrCast(tbox.layoutDoc.color, (CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark ? "dimGray" : "lightGray")); this._fieldWrapper.style.width = node.attrs.width; this._fieldWrapper.style.height = node.attrs.height; this._fieldWrapper.style.display = node.attrs.hidden ? "none" : "inline-block"; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 404e828ea..652804126 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -17,7 +17,7 @@ import { Docs, DocumentOptions, DocUtils } from '../client/documents/Documents'; import { DocumentType } from "../client/documents/DocumentTypes"; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; import { Scripting } from '../client/util/Scripting'; -import { SettingsManager } from '../client/util/SettingsManager'; +import { SettingsManager, ColorScheme } from '../client/util/SettingsManager'; import { Transform } from '../client/util/Transform'; import { UndoManager } from "../client/util/UndoManager"; import { TabDocView } from '../client/views/collections/TabDocView'; @@ -403,7 +403,7 @@ export class MobileInterface extends React.Component { const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row"); - const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); + const toggleTheme = ScriptField.MakeScript(`self.colorScheme = self.colorScheme ? undefined: ${ColorScheme.Dark}}`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); const cloneDashboard = ScriptField.MakeScript(`cloneDashboard()`); dashboardDoc.contextMenuScripts = new List([toggleTheme!, toggleComic!, cloneDashboard!]); -- cgit v1.2.3-70-g09d2