diff options
-rw-r--r-- | src/client/views/MainView.tsx | 28 | ||||
-rw-r--r-- | src/client/views/StyleProvider.scss | 10 | ||||
-rw-r--r-- | src/client/views/StyleProvider.tsx | 77 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.scss | 18 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/nodes/FilterBox.tsx | 47 |
6 files changed, 64 insertions, 121 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e54d84a6c..4eeb1fc95 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -309,32 +309,6 @@ export class MainView extends React.Component { } - /** - * add lock and hide button decorations for the "Dashboards" flyout TreeView - */ - DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) { - const toggleField = undoBatch(action((e: React.MouseEvent, doc: Doc, field: string) => { - e.stopPropagation(); - doc[field] = doc[field] ? undefined : true; - })); - switch (property.split(":")[0]) { - case StyleProp.Decorations: - return !doc || property.includes(":afterHeader") || // bcz: Todo: afterHeader should be generalized into a renderPath that is a list of the documents rendered so far which would mimic much of CSS property selectors - DocListCast((Doc.UserDoc().myDashboards as Doc).data).some(dash => dash === doc || - DocListCast(dash.data).some(tabset => tabset === doc)) ? (null) : - <> - <div className={`styleProvider-treeView-hide${doc.hidden ? "-active" : ""}`} onClick={e => toggleField(e, doc, "hidden")}> - <FontAwesomeIcon icon={doc.hidden ? "eye-slash" : "eye"} size="sm" /> - </div> - <div className={`styleProvider-treeView-lock${doc._lockedPosition ? "-active" : ""}`} onClick={e => toggleField(e, doc, "_lockedPosition")}> - <FontAwesomeIcon icon={doc._lockedPosition ? "lock" : "unlock"} size="sm" /> - </div> - </>; - } - return DefaultStyleProvider(doc, props, property); - } - - @computed get flyout() { return !this._flyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}> {this.docButtons} @@ -349,7 +323,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} docViewPath={returnEmptyDoclist} layerProvider={undefined} - styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards ? this.DashboardStyleProvider : DefaultStyleProvider} + styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards ? DashboardStyleProvider : DefaultStyleProvider} rootSelected={returnTrue} removeDocument={returnFalse} ScreenToLocalTransform={this.mainContainerXf} diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss index 94001730c..f26ed1f2d 100644 --- a/src/client/views/StyleProvider.scss +++ b/src/client/views/StyleProvider.scss @@ -16,4 +16,14 @@ } .styleProvider-lock:hover { opacity:1; +} + +.styleProvider-treeView-icon, +.styleProvider-treeView-icon-active { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.styleProvider-treeView-icon { + display: none; }
\ No newline at end of file diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index d7ee82f2c..9e61351c4 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -1,7 +1,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; -import { runInAction } from 'mobx'; +import { runInAction, action } from 'mobx'; import { Doc, Opt, StrListCast } from "../../fields/Doc"; import { List } from '../../fields/List'; import { listSpec } from '../../fields/Schema'; @@ -9,16 +10,16 @@ import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types"; import { DocumentType } from '../documents/DocumentTypes'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; import { SnappingManager } from '../util/SnappingManager'; -import { UndoManager } from '../util/UndoManager'; +import { UndoManager, undoBatch } from '../util/UndoManager'; import { CollectionViewType } from './collections/CollectionView'; +import "./collections/TreeView.scss"; import { MainView } from './MainView'; import { DocumentViewProps } from "./nodes/DocumentView"; -import "./StyleProvider.scss"; -import "./collections/TreeView.scss"; +import { FieldViewProps } from './nodes/FieldView'; import "./nodes/FilterBox.scss"; +import "./StyleProvider.scss"; import React = require("react"); import Color = require('color'); -import { FieldViewProps } from './nodes/FieldView'; export enum StyleLayers { Background = "background" @@ -98,7 +99,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps if (docColor) return docColor; const backColor = backgroundCol();// || (darkScheme() ? "black" : "white"); if (!backColor) return undefined; - const col = Color(backColor.startsWith("#") ? (backColor as string).substring(0, 7) : backColor).rgb(); + const nonAlphaColor = backColor.startsWith("#") ? (backColor as string).substring(0, 7) : + backColor.startsWith("rgba") ? backColor.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : backColor + const col = Color(nonAlphaColor).rgb(); const colsum = (col.red() + col.green() + col.blue()); if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return "black"; return "white"; @@ -110,7 +113,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry].includes(doc?._viewType as any) || doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0; case StyleProp.BackgroundColor: { - let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rbga(0,0,0,0.4)" : "")); + let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : "")); if (MainView.Instance.LastButton === doc) return darkScheme() ? "dimgrey" : "lightgrey"; switch (doc?.type) { case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break; @@ -189,60 +192,30 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps } } - -function toggleHidden(e: React.MouseEvent, doc: Doc) { - UndoManager.RunInBatch(() => runInAction(() => { - e.stopPropagation(); - doc.hidden = doc.hidden ? undefined : true; - }), "toggleHidden"); -} - -function toggleLock(e: React.MouseEvent, doc: Doc) { - UndoManager.RunInBatch(() => runInAction(() => { - e.stopPropagation(); - doc.lockedPosition = doc.lockedPosition ? undefined : true; - }), "toggleHidden"); +export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) { + return <div className={`styleProvider-treeView-icon${doc[field] ? "-active" : ""}`} + onClick={undoBatch(action((e: React.MouseEvent) => { + e.stopPropagation(); + clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true); + }))}> + <FontAwesomeIcon icon={(doc[field] ? onIcon as any : offIcon) as IconProp} size="sm" /> + </div>; } - /** * add lock and hide button decorations for the "Dashboards" flyout TreeView */ export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) { - switch (property.split(":")[0]) { - case StyleProp.Decorations: - if (doc) { - const hidden = doc.hidden; - const locked = doc.lockedPosition; - return doc._viewType === CollectionViewType.Docking || (Doc.IsSystem(doc) && Doc.UserDoc().noviceMode) ? (null) : - <> - <div className={`styleProvider-treeView-hide${hidden ? "-active" : ""}`} onClick={(e) => toggleHidden(e, doc)}> - <FontAwesomeIcon icon={hidden ? "eye-slash" : "eye"} size="sm" /> - </div> - <div className={`styleProvider-treeView-lock${locked ? "-active" : ""}`} onClick={(e) => toggleLock(e, doc)}> - <FontAwesomeIcon icon={locked ? "lock" : "unlock"} size="sm" /> - </div> - </>; - } - default: return DefaultStyleProvider(doc, props, property); + if (doc && property.split(":")[0] === StyleProp.Decorations) { + return doc._viewType === CollectionViewType.Docking ? (null) : + <> + {DashboardToggleButton(doc, "hidden", "eye-slash", "eye")} + {DashboardToggleButton(doc, "lockedPosition", "lock", "unlock")} + </>; } + return DefaultStyleProvider(doc, props, property); } -function changeFilterBool(e: any, doc: Doc) { - UndoManager.RunInBatch(() => runInAction(() => { - //e.stopPropagation(); - //doc.lockedPosition = doc.lockedPosition ? undefined : true; - }), "changeFilterBool"); -} - -function closeFilter(e: React.MouseEvent, doc: Doc) { - UndoManager.RunInBatch(() => runInAction(() => { - e.stopPropagation(); - //doc.lockedPosition = doc.lockedPosition ? undefined : true; - }), "closeFilter"); -} - - // // a preliminary semantic-"layering/grouping" mechanism for determining interactive properties of documents // currently, the provider tests whether the docuemnt's layer field matches the activeLayer field of the tab. diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 5b0c04f33..0239ae863 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -113,24 +113,18 @@ width: unset; } - .right-buttons-container { + .treeView-rightButtons { display: flex; align-items: center; margin-left: 0.25rem; opacity: 0.75; - >svg, - .styleProvider-treeView-lock, - .styleProvider-treeView-hide, - .styleProvider-treeView-lock-active, - .styleProvider-treeView-hide-active { + >svg { margin-left: 0.25rem; margin-right: 0.25rem; } - >svg, - .styleProvider-treeView-lock, - .styleProvider-treeView-hide { + >svg { display: none; } } @@ -154,11 +148,9 @@ } } - .right-buttons-container { - + .treeView-rightButtons { >svg, - .styleProvider-treeView-lock, - .styleProvider-treeView-hide { + .styleProvider-treeView-icon { display: inherit; } } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index e1fd78270..49db98743 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -626,6 +626,7 @@ export class TreeView extends React.Component<TreeViewProps> { ContainingCollectionDoc={this.props.treeView.props.Document} />; + const buttons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations + (Doc.IsSystem(this.props.containerCollection) ? ":afterHeader" : "")); return <> <div className={`docContainer${Doc.IsSystem(this.props.document) || this.props.document.isFolder ? "-system" : ""}`} ref={this._tref} title="click to edit title. Double Click or Drag to Open" style={{ @@ -636,8 +637,8 @@ export class TreeView extends React.Component<TreeViewProps> { }} > {view} </div > - <div className={"right-buttons-container"}> - {this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations + (Doc.IsSystem(this.props.containerCollection) ? ":afterHeader" : ""))} {/* hide and lock buttons */} + <div className="treeView-rightButtons"> + {buttons} {/* hide and lock buttons */} {this.headerElements} </div> </>; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 78449636a..c97de3402 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -1,8 +1,9 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { computed, observable, action, trace, reaction, runInAction } from "mobx"; +import { action, computed, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, Field, Opt, DocListCastAsync, HeightSym } from "../../../fields/Doc"; +import Select from "react-select"; +import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { List } from "../../../fields/List"; import { RichTextField } from "../../../fields/RichTextField"; @@ -12,24 +13,22 @@ import { Cast, StrCast } from "../../../fields/Types"; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; +import { CurrentUserUtils } from "../../util/CurrentUserUtils"; +import { UserOptions } from "../../util/GroupManager"; +import { Scripting } from "../../util/Scripting"; +import { SelectionManager } from "../../util/SelectionManager"; import { CollectionTreeView } from "../collections/CollectionTreeView"; +import { CollectionView } from "../collections/CollectionView"; import { ViewBoxBaseComponent } from "../DocComponent"; +import { EditableView } from "../EditableView"; import { SearchBox } from "../search/SearchBox"; +import { DashboardToggleButton, DefaultStyleProvider, StyleProp } from "../StyleProvider"; +import { DocumentViewProps } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import './FilterBox.scss'; -import { Scripting } from "../../util/Scripting"; -import { SelectionManager } from "../../util/SelectionManager"; -import { CollectionView } from "../collections/CollectionView"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -import Select from "react-select"; -import { UserOptions } from "../../util/GroupManager"; -import { DocumentViewProps } from "./DocumentView"; -import { DefaultStyleProvider, StyleProp } from "../StyleProvider"; -import { CurrentUserUtils } from "../../util/CurrentUserUtils"; -import { EditableView } from "../EditableView"; -import { undoBatch } from "../../util/UndoManager"; type FilterBoxDocument = makeInterface<[typeof documentSchema]>; const FilterBoxDocument = makeInterface(documentSchema); @@ -135,7 +134,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc } gatherFieldValues(dashboard: Doc, facetKey: string) { - const childDocs = DocListCast((dashboard.data as any)[0].data); + const childDocs = DocListCast(dashboard.data); const valueSet = new Set<string>(); let rtFields = 0; childDocs.forEach((d) => { @@ -206,7 +205,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc let nonNumbers = 0; let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE; facetValues.strings.map(val => { - const num = Number(val); + const num = val ? Number(val) : Number.NaN; if (Number.isNaN(num)) { nonNumbers++; } else { @@ -217,8 +216,8 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc let newFacet: Opt<Doc>; if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) { newFacet = Docs.Create.TextDocument("", { - _width: 100, _height: 25, system: true, _stayInCollection: true, target: targetDoc, - treeViewExpandedView: "layout", title: facetHeader, _treeViewOpen: true, _forceActive: true, ignoreClick: true + title: facetHeader, system: true, target: targetDoc, _width: 100, _height: 25, _stayInCollection: true, + treeViewExpandedView: "layout", _treeViewOpen: true, _forceActive: true, ignoreClick: true }); Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox newFacet._textBoxPadding = 4; @@ -226,7 +225,8 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" }); } else if (facetHeader !== "tags" && nonNumbers / facetValues.strings.length < .1) { newFacet = Docs.Create.SliderDocument({ - title: facetHeader, _overflow: "visible", _fitWidth: true, target: targetDoc, _height: 40, _stayInCollection: true, treeViewExpandedView: "layout", _treeViewOpen: true + title: facetHeader, system: true, target: targetDoc, _fitWidth: true, _height: 40, _stayInCollection: true, + treeViewExpandedView: "layout", _treeViewOpen: true, _forceActive: true, _overflow: "visible", }); const newFacetField = Doc.LayoutFieldKey(newFacet); const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); @@ -346,16 +346,9 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc * add lock and hide button decorations for the "Dashboards" flyout TreeView */ FilterStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) => { - switch (property.split(":")[0]) { - case StyleProp.Decorations: - return !doc || doc.treeViewHideHeaderFields ? (null) : - <> - <div className={`styleProvider-treeView-hide${doc.hidden ? "-active" : ""}`} onClick={undoBatch(e => - this.removeFilter(StrCast(doc.title)) - )}> - <FontAwesomeIcon icon={"trash"} size="sm" /> - </div> - </>; + if (property.split(":")[0] === StyleProp.Decorations) { + return !doc || doc.treeViewHideHeaderFields ? (null) : + DashboardToggleButton(doc, "hidden", "trash", "trash", () => this.removeFilter(StrCast(doc.title))); } return this.props.styleProvider?.(doc, props, property); } |