From 3408a32172e4cf31c74e42609f26e1b508936b2c Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 25 Nov 2020 14:39:28 +0530 Subject: filter + bug? --- src/client/views/collections/CollectionTreeView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 85bf76e6d..439384e08 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -219,12 +219,12 @@ export class CollectionTreeView extends CollectionSubView
this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} ref={this.createTreeDropTarget}> -- cgit v1.2.3-70-g09d2 From 45dee9388ad4f5c3c70df3a5ff1852c6bd41dec0 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sun, 20 Dec 2020 01:23:44 +0530 Subject: added settings manager to esc key handler --- src/client/util/SharingManager.tsx | 44 +++++++++++----------- src/client/views/GlobalKeyHandler.ts | 2 + .../views/collections/CollectionTreeView.tsx | 4 +- 3 files changed, 26 insertions(+), 24 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 8c36a7f3c..f1fe7c22f 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -7,7 +7,7 @@ import Select from "react-select"; import * as RequestPromise from "request-promise"; import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, DocListCastAsync, Opt } from "../../fields/Doc"; import { List } from "../../fields/List"; -import { Cast, StrCast } from "../../fields/Types"; +import { Cast, NumCast, StrCast } from "../../fields/Types"; import { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from "../../fields/util"; import { Utils } from "../../Utils"; import { DocServer } from "../DocServer"; @@ -173,7 +173,7 @@ export class SharingManager extends React.Component<{}> { const acl = `acl-${normalizeEmail(user.email)}`; const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`; - const docs = SelectionManager.SelectedDocuments().length < 2 ? [target] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document); + const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); docs.forEach(doc => { doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc); @@ -309,21 +309,21 @@ export class SharingManager extends React.Component<{}> { /** * Shares the document with a user. */ - setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => { - const { user, sharingDoc } = recipient; - const target = targetDoc || this.targetDoc!; - const acl = `acl-${normalizeEmail(user.email)}`; - const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`; - - const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); - docs.forEach(doc => { - doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc); - distributeAcls(acl, permission as SharingPermissions, doc); - - if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc); - else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.aliasOf as Doc || doc)); - }); - } + // setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => { + // const { user, sharingDoc } = recipient; + // const target = targetDoc || this.targetDoc!; + // const acl = `acl-${normalizeEmail(user.email)}`; + // const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`; + + // const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); + // docs.forEach(doc => { + // doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc); + // distributeAcls(acl, permission as SharingPermissions, doc); + + // if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc); + // else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.aliasOf as Doc || doc)); + // }); + // } // private setExternalSharing = (permission: string) => { @@ -357,11 +357,11 @@ export class SharingManager extends React.Component<{}> { if (!uniform) dropdownValues.unshift("-multiple-"); if (override) dropdownValues.unshift("None"); return dropdownValues.filter(permission => permission !== SharingPermissions.View).map(permission => - ( - - ) + ( + + ) ); } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index c38842c4f..26dc0071c 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -27,6 +27,7 @@ import { SnappingManager } from "../util/SnappingManager"; import { SearchBox } from "./search/SearchBox"; import { random } from "lodash"; import { DocumentView } from "./nodes/DocumentView"; +import { SettingsManager } from "../util/SettingsManager"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -128,6 +129,7 @@ export class KeyManager { DictationManager.Controls.stop(); GoogleAuthenticationManager.Instance.cancel(); SharingManager.Instance.close(); + if (!GroupManager.Instance.isOpen) SettingsManager.Instance.close(); GroupManager.Instance.close(); CollectionFreeFormViewChrome.Instance?.clearKeep(); window.getSelection()?.empty(); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 18921e9e0..344a6c103 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -215,12 +215,12 @@ export class CollectionTreeView extends CollectionSubView
this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} ref={this.createTreeDropTarget}> -- cgit v1.2.3-70-g09d2 From 6b211be7c96a3d7f275509d094d9e96dd6dff6ba Mon Sep 17 00:00:00 2001 From: anika Date: Mon, 28 Dec 2020 22:01:58 -0600 Subject: more cleaning --- src/client/views/collections/TreeView.scss | 22 ++++++++++++++++++---- src/client/views/nodes/FilterBox.scss | 6 ++++-- src/client/views/nodes/FilterBox.tsx | 4 ++-- 3 files changed, 24 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 7a654c7cf..7a719b4a4 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -8,6 +8,7 @@ width: 100%; overflow: hidden; } + .treeView-container, .treeView-container-active { .bullet-outline { @@ -20,21 +21,26 @@ .treeView-bulletIcons { width: 15px; + .treeView-expandIcon { display: none; left: -10px; position: absolute; } + .treeView-checkIcon { - left: -10px; + left: 3px; + top: 2px; position: absolute; } + &:hover { .treeView-expandIcon { display: unset; } } } + .bullet { position: relative; width: $TREE_BULLET_WIDTH; @@ -45,9 +51,11 @@ border-radius: 4px; } } + .treeView-container-active { z-index: 100; position: relative; + .formattedTextbox-sidebar { background-color: #ffff001f !important; height: 500px !important; @@ -70,7 +78,8 @@ display: flex; overflow: hidden; } -.treeView-border{ + +.treeView-border { border-left: dashed 1px #00000042; } @@ -78,15 +87,20 @@ .treeView-header { border: transparent 1px solid; display: flex; + //align-items: center; ::-webkit-scrollbar { - display: none; + display: none; } + .formattedTextBox-cont { - .formattedTextbox-sidebar, .formattedTextbox-sidebar-inking { + + .formattedTextbox-sidebar, + .formattedTextbox-sidebar-inking { overflow: visible !important; border-left: unset; } + overflow: visible !important; } diff --git a/src/client/views/nodes/FilterBox.scss b/src/client/views/nodes/FilterBox.scss index 62f972218..6d72af679 100644 --- a/src/client/views/nodes/FilterBox.scss +++ b/src/client/views/nodes/FilterBox.scss @@ -3,7 +3,7 @@ text-align: left; .filterBox-flyout-facet { - background-color: lightgray; + background-color: white; text-align: left; display: inline-block; position: relative; @@ -106,7 +106,8 @@ .filterBox-select-box { margin-right: 2px; font-size: 30px; - border: none; + border: 0; + background: transparent; } .filterBox-selection { @@ -167,6 +168,7 @@ .filterBox-tree { display: inline-block; width: 100%; + margin-bottom: 10px; //height: calc(100% - 30px); } } \ No newline at end of file diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 95ffc6f8c..dec6f67d8 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -207,7 +207,7 @@ export class FilterBox extends ViewBoxBaseComponent)}
; - const newFlyout =
e.stopPropagation()}> + const newFlyout =
e.stopPropagation()}> {this._allFacets.map(facet =>
- +
+ add a filter
-- cgit v1.2.3-70-g09d2 From 7174328702fe6b350780728db890141f50ceec5b Mon Sep 17 00:00:00 2001 From: anika Date: Thu, 31 Dec 2020 10:29:20 -0600 Subject: last add b efore pull --- src/client/views/StyleProvider.tsx | 6 ++++++ src/client/views/collections/TreeView.tsx | 6 +++++- src/client/views/nodes/FilterBox.scss | 5 +++++ src/client/views/nodes/FilterBox.tsx | 14 +++----------- 4 files changed, 19 insertions(+), 12 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 312cfc73e..35fe30a56 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -23,6 +23,7 @@ export enum StyleLayers { } export enum StyleProp { + TreeViewIcon = "treeViewIcon", DocContents = "docContents", // when specified, the JSX returned will replace the normal rendering of the document view Opacity = "opacity", // opacity of the document view Hidden = "hidden", // whether the document view should not be isplayed @@ -64,11 +65,14 @@ export function DefaultStyleProvider(doc: Opt, props: Opt StrListCast(doc?.layers).includes(StyleLayers.Background); const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); switch (property.split(":")[0]) { + case StyleProp.TreeViewIcon: return doc && Doc.toIcon(doc); case StyleProp.DocContents: return undefined; case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey"; case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); @@ -152,6 +156,8 @@ export function DefaultStyleProvider(doc: Opt, props: Opt 0 && ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 93d3be1fc..b5e498503 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -441,7 +441,11 @@ export class TreeView extends React.Component { @computed get renderBullet() { TraceMobx(); - const iconType = Doc.toIcon(this.doc); + const iconType = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon); + + + // const footerDecoration = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decoration + ":footer"); + const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; return
e.stopPropagation()}> + const flyout =
e.stopPropagation()}> {this._allFacets.map(facet => )}
; - const newFlyout =
e.stopPropagation()}> - {this._allFacets.map(facet => )} -
- return this.props.dontRegisterView ? (null) :
{/*
*/} @@ -279,7 +271,7 @@ export class FilterBox extends ViewBoxBaseComponent
- +
+ add a filter
-- cgit v1.2.3-70-g09d2 From a70a224d40ed511e8278ce01a74fb0a8a012b075 Mon Sep 17 00:00:00 2001 From: anika Date: Thu, 31 Dec 2020 11:32:41 -0600 Subject: small merge fixes --- src/client/views/MainView.tsx | 5 ++-- src/client/views/StyleProvider.tsx | 40 ++++++++++++++++++++++++++++++ src/client/views/collections/TreeView.scss | 21 +++++++++++----- src/client/views/collections/TreeView.tsx | 5 +++- 4 files changed, 62 insertions(+), 9 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e43b8baf1..d17b72639 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -44,6 +44,7 @@ import { KeyManager } from './GlobalKeyHandler'; import { InkStrokeProperties } from './InkStrokeProperties'; import { LinkMenu } from './linking/LinkMenu'; import "./MainView.scss"; +import "./collections/TreeView.scss"; import { AudioBox } from './nodes/AudioBox'; import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView, DocumentViewProps } from './nodes/DocumentView'; @@ -58,7 +59,7 @@ import { PDFMenu } from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { SearchBox } from './search/SearchBox'; -import { DefaultStyleProvider, StyleProp } from './StyleProvider'; +import { DefaultStyleProvider, DashboardStyleProvider, StyleProp } from './StyleProvider'; import { FieldViewProps } from './nodes/FieldView'; const _global = (window /* browser */ || global /* node */) as any; @@ -342,7 +343,7 @@ export class MainView extends React.Component { PanelHeight={this.getContentsHeight} renderDepth={0} focus={emptyFunction} - styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards ? this.DashboardStyleProvider : DefaultStyleProvider} + styleProvider={this._sidebarContent.title === "My Dashboards" ? DashboardStyleProvider : DefaultStyleProvider} parentActive={returnTrue} whenActiveChanged={emptyFunction} bringToFront={emptyFunction} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index a6e3516ed..c9eedb85d 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -15,6 +15,7 @@ import { MainView } from './MainView'; import { DocumentViewProps } from "./nodes/DocumentView"; import { FieldViewProps } from './nodes/FieldView'; import "./StyleProvider.scss"; +import "./collections/TreeView.scss"; import React = require("react"); import Color = require('color'); @@ -169,6 +170,45 @@ export function DefaultStyleProvider(doc: Opt, props: Opt 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"); +} + +/** + * add lock and hide button decorations for the "Dashboards" flyout TreeView + */ +export function DashboardStyleProvider(doc: Opt, props: Opt, 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) : + <> +
toggleHidden(e, doc)}> + +
+
toggleLock(e, doc)}> + +
+ ; + } + default: return DefaultStyleProvider(doc, props, property); + + } +} + // // 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 1208fa07d..2f74a49bb 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -29,7 +29,7 @@ } .treeView-checkIcon { - left: 3px; + left: 3.5px; top: 2px; position: absolute; } @@ -118,12 +118,18 @@ margin-left: 0.25rem; opacity: 0.75; - >svg, .styleProvider-treeView-lock, .styleProvider-treeView-hide, .styleProvider-treeView-lock-active, .styleProvider-treeView-hide-active { + >svg, + .styleProvider-treeView-lock, + .styleProvider-treeView-hide, + .styleProvider-treeView-lock-active, + .styleProvider-treeView-hide-active { margin-left: 0.25rem; - margin-right: 0.25rem; + margin-right: 0.25rem; } - - >svg, .styleProvider-treeView-lock, .styleProvider-treeView-hide { + + >svg, + .styleProvider-treeView-lock, + .styleProvider-treeView-hide { display: none; } } @@ -148,7 +154,10 @@ } .right-buttons-container { - >svg, .styleProvider-treeView-lock, .styleProvider-treeView-hide { + + >svg, + .styleProvider-treeView-lock, + .styleProvider-treeView-hide { display: inherit; } } diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 2f9a2f3eb..a297ad708 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -590,7 +590,10 @@ export class TreeView extends React.Component { }} > {view}
- {this.headerElements} +
+ {this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations)} {/* hide and lock buttons */} + {this.headerElements} +
; } -- cgit v1.2.3-70-g09d2 From b98c90c3c59eb5f65a4c7aad7ff8247558a5564c Mon Sep 17 00:00:00 2001 From: anika Date: Thu, 7 Jan 2021 10:33:04 -0600 Subject: last before pull --- src/client/views/StyleProvider.tsx | 2 +- src/client/views/collections/TreeView.tsx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index c9eedb85d..607783d51 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -73,7 +73,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt props?.styleProvider?.(doc, props, StyleProp.Opacity); switch (property.split(":")[0]) { - case StyleProp.TreeViewIcon: return doc && Doc.toIcon(doc); + case StyleProp.TreeViewIcon: return doc ? Doc.toIcon(doc) : "question"; case StyleProp.DocContents: return undefined; case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey"; case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index a297ad708..6a0e05215 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -441,14 +441,17 @@ export class TreeView extends React.Component { @computed get renderBullet() { TraceMobx(); + const iconType = Doc.toIcon(this.doc); + // console.log(this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon)); <- always undefined //const iconType = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon); // const footerDecoration = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decoration + ":footer"); const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; + return
Date: Thu, 7 Jan 2021 11:23:48 -0600 Subject: shift to right --- src/client/views/PropertiesView.tsx | 45 ++++++++++++++++++++-- .../views/collections/CollectionTreeView.tsx | 5 ++- src/client/views/nodes/FilterBox.scss | 9 ++--- src/client/views/nodes/FilterBox.tsx | 4 +- 4 files changed, 51 insertions(+), 12 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 6e33b5c2f..a8b65c114 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -11,7 +11,7 @@ import { InkField } from "../../fields/InkField"; import { ComputedField } from "../../fields/ScriptField"; import { Cast, NumCast, StrCast } from "../../fields/Types"; import { denormalizeEmail, GetEffectiveAcl, SharingPermissions } from "../../fields/util"; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse } from "../../Utils"; +import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from "../../Utils"; import { DocumentType } from "../documents/DocumentTypes"; import { DocumentManager } from "../util/DocumentManager"; import { SelectionManager } from "../util/SelectionManager"; @@ -29,6 +29,7 @@ import { PropertiesButtons } from "./PropertiesButtons"; import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector"; import "./PropertiesView.scss"; import { DefaultStyleProvider } from "./StyleProvider"; +import { FilterBox } from "./nodes/FilterBox"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -67,6 +68,8 @@ export class PropertiesView extends React.Component { @observable openContexts: boolean = true; @observable openAppearance: boolean = true; @observable openTransform: boolean = true; + @observable openFilters: boolean = true; + // @observable selectedUser: string = ""; // @observable addButtonPressed: boolean = false; @observable layoutDocAcls: boolean = false; @@ -510,8 +513,6 @@ export class PropertiesView extends React.Component { } } - - @computed get controlPointsButton() { const formatInstance = InkStrokeProperties.Instance; @@ -907,6 +908,44 @@ export class PropertiesView extends React.Component {
}
+
+
this.openFilters = !this.openFilters)} + style={{ backgroundColor: this.openFilters ? "black" : "" }}> + Filters +
+ +
+
+ {!this.openFilters ? (null) : +
+ +
} +
+ {!this.isInk ? (null) :
>(Document) { +export class + CollectionTreeView extends CollectionSubView>(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _isChildActive = false; private _mainEle?: HTMLDivElement; @@ -212,7 +213,7 @@ export class CollectionTreeView extends CollectionSubView {/*
*/} -
+ {/*
Choose Filters -
+
*/}
this.changeBool(e)}> +
filters in
- {/* */} @@ -354,26 +367,6 @@ export class FilterBox extends ViewBoxBaseComponent - {/* @computed get flyoutpanel() { - return
e.stopPropagation()}> - {this._allFacets.map(facet => )} -
; - } - render() { - const facetCollection = this.props.Document; - - return this.props.dontRegisterView ? (null) :
-
e.stopPropagation()}> - -
- - Choose Facets -
-
*/}
@@ -444,7 +437,7 @@ export class FilterBox extends ViewBoxBaseComponent
- +
FILTERS
@@ -457,14 +450,6 @@ export class FilterBox extends ViewBoxBaseComponent
- {!this.showFilterDialog ? (null) : - - }
; } @@ -480,7 +465,7 @@ Scripting.addGlobal(function determineCheckedState(layoutDoc: Doc, facetHeader: } return undefined; }); -Scripting.addGlobal(function readFacetData(targetDoc: Doc, facetHeader: string) { +Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string) { const allCollectionDocs = DocListCast(CollectionDockingView.Instance?.props.Document.allDocuments); const set = new Set(); if (facetHeader === "tags") allCollectionDocs.forEach(child => Field.toString(child[facetHeader] as Field).split(":").forEach(key => set.add(key))); @@ -493,10 +478,11 @@ Scripting.addGlobal(function readFacetData(targetDoc: Doc, facetHeader: string) const doc = new Doc(); doc.system = true; doc.title = facetValue.toString(); - doc.target = targetDoc; - doc.facetHeader = facetHeader; - doc.facetValue = facetValue; - doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(self.target, self.facetHeader, self.facetValue)"); + doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(layoutDoc, facetHeader, facetValue)", {}, { layoutDoc, facetHeader, facetValue }); + // doc.target = layoutDoc; + // doc.facetHeader = facetHeader; + // doc.facetValue = facetValue; + // doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(self.target, self.facetHeader, self.facetValue)"); return doc; }); return new List(facetValueDocSet); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 75d15c409..b0d77f0de 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1049,7 +1049,7 @@ export namespace Doc { doc.layoutKey = deiconify || "layout"; } export function setDocFilterRange(target: Doc, key: string, range?: number[]) { - const container = target ?? CollectionDockingView.Instance.props.Document; + const container = target ?? FilterBox._filterScope === "Current Collection" ? SelectionManager.Views()[0].Document || CollectionDockingView.Instance.props.Document : CollectionDockingView.Instance.props.Document; const docRangeFilters = Cast(container._docRangeFilters, listSpec("string"), []); for (let i = 0; i < docRangeFilters.length; i += 3) { if (docRangeFilters[i] === key) { @@ -1065,9 +1065,11 @@ export namespace Doc { } } - // filters document in a container collection: - // all documents with the specified value for the specified key are included/excluded - // based on the modifiers :"check", "x", undefined + /** + * Filters document in a container collection: + * all documents with the specified value for the specified key are included/excluded + * based on the modifiers :"check", "x", undefined + */ export function setDocFilter(target: Opt, key: string, value: any, modifiers?: "remove" | "match" | "check" | "x" | undefined) { const container = target ?? FilterBox._filterScope === "Current Collection" ? SelectionManager.Views()[0].Document || CollectionDockingView.Instance.props.Document : CollectionDockingView.Instance.props.Document; const docFilters = Cast(container._docFilters, listSpec("string"), []); -- cgit v1.2.3-70-g09d2 From 7c6ccf0c6dce1b778163f03ae271b3c17896a560 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 17 Mar 2021 01:30:02 -0400 Subject: starting process of addingfilter attributes to new docs in collection --- src/client/documents/Documents.ts | 25 ++++++++++++------------- src/client/views/PropertiesView.scss | 4 ++-- src/client/views/collections/CollectionView.tsx | 16 ++++++++++++++++ src/client/views/nodes/FilterBox.tsx | 10 +++++----- 4 files changed, 35 insertions(+), 20 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0f1abb3ac..c13a69402 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -636,9 +636,7 @@ export namespace Docs { protoProps.system = delegateProps.system; - if (!("author" in protoProps)) { - protoProps.author = Doc.CurrentUserEmail; - } + if (!("author" in protoProps)) protoProps.author = Doc.CurrentUserEmail; if (!("creationDate" in protoProps)) { protoProps.creationDate = new DateField; @@ -1019,18 +1017,22 @@ export namespace DocUtils { return false; } - console.log(FilterBox._filterBoolean); for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== "cookies")) { const facet = filterFacets[facetKey]; - console.log(facet) + + // facets that match some value in the field of the document (e.g. some text field) const matches = Object.keys(facet).filter(value => value !== "cookies" && facet[value] === "match"); + + // facets that have a check next to them const checks = Object.keys(facet).filter(value => facet[value] === "check"); + + // facets that have an x next to them const xs = Object.keys(facet).filter(value => facet[value] === "x"); if (!xs.length && !checks.length && !matches.length) return true; const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value)); - const satisfiesMatchFacets = matches.some(value => { + const satisfiesMatchFacets = !matches.length ? true : matches.some(value => { if (facetKey.startsWith("*")) { // fields starting with a '*' are used to match families of related fields. ie, *lastModified will match text-lastModified, data-lastModified, etc const allKeys = Array.from(Object.keys(d)); allKeys.push(...Object.keys(Doc.GetProto(d))); @@ -1039,16 +1041,13 @@ export namespace DocUtils { } return Field.toString(d[facetKey] as Field).includes(value); }); - console.log(satisfiesCheckFacets, failsNotEqualFacets); + // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria if (FilterBox._filterBoolean === "OR") { - if (satisfiesCheckFacets && !failsNotEqualFacets) { - return true; - } + if (satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } + // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria else { - if (!satisfiesCheckFacets || failsNotEqualFacets) { - return false; - } + if (!satisfiesCheckFacets || failsNotEqualFacets || (matches.length && satisfiesMatchFacets)) return false; } } diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 1d52136de..7c6d507b8 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -191,8 +191,8 @@ font-size: 10px; padding: 10px; margin-left: 5px; - // max-height: 40%; - overflow-y: visible; + max-height: 40%; + overflow-y: scroll; .propertiesView-buttonContainer { float: right; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 34fd20f1a..4f37747b0 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -38,6 +38,8 @@ import { SubCollectionViewProps } from './CollectionSubView'; import { CollectionTimeView } from './CollectionTimeView'; import { CollectionTreeView } from "./CollectionTreeView"; import './CollectionView.scss'; +import { FilterBox } from '../nodes/FilterBox'; +import { listSpec } from '../../../fields/Schema'; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); @@ -116,6 +118,19 @@ export class CollectionView extends Touchable { whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); + /** + * Applies the collection/dashboard's current filter attributes to the doc being added + */ + addFilterAttributes = (doc: Doc) => { + Cast(FilterBox.targetDoc._docFilters, listSpec("string"))?.forEach(attribute => { + if (attribute.charAt(0).toUpperCase() === attribute.charAt(0)) { + const fields = attribute.split(':'); + if (fields[2] === "check") doc[DataSym][fields[0]] = fields[1]; + else if (fields[2] === "x" && doc[DataSym][fields[0]] === fields[1]) doc[DataSym][fields[0]] = undefined; + } + }); + } + @action.bound addDocument = (doc: Doc | Doc[]): boolean => { if (this.props.filterAddDocument?.(doc) === false) { @@ -157,6 +172,7 @@ export class CollectionView extends Touchable { DocUtils.LeavePushpin(doc); doc._stayInCollection = undefined; doc.context = this.props.Document; + this.addFilterAttributes(doc); // }); added.map(doc => this.props.layerProvider?.(doc, true));// assigns layer values to the newly added document... testing the utility of this (targetDataDoc[this.props.fieldKey] as List).push(...added); diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 41e274e7a..541693cdf 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -39,7 +39,7 @@ export class FilterBox extends ViewBoxBaseComponent) { super(props); - const targetDoc = this.targetDoc; + const targetDoc = FilterBox.targetDoc; if (!targetDoc) CurrentUserUtils.setupFilterDocs(targetDoc); } public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FilterBox, fieldKey); } @@ -52,7 +52,7 @@ export class FilterBox extends ViewBoxBaseComponent(); - const targetDoc = this.targetDoc; + const targetDoc = FilterBox.targetDoc; if (this._loaded && targetDoc) { // if (targetDoc) { const activeTabs = DocListCast(targetDoc.data); @@ -140,7 +140,7 @@ export class FilterBox extends ViewBoxBaseComponent { console.log("remove filter"); - const targetDoc = this.targetDoc; + const targetDoc = FilterBox.targetDoc; const filterDoc = targetDoc.currentFilter as Doc; const attributes = DocListCast(filterDoc["data"]); const found = attributes.findIndex(doc => doc.title === filterName); @@ -170,7 +170,7 @@ export class FilterBox extends ViewBoxBaseComponent doc.title === facetHeader); if (found !== -1) { // comment this bit out later once the x works in treeview -- cgit v1.2.3-70-g09d2 From 4df769e20b9588fea61b602ec67ca2208fc3d747 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 25 Mar 2021 02:25:12 -0400 Subject: filters is going to kill me the files I should look at on return to this branch are documents.ts, propertiesview, colsubview, colview, filterbox --- src/client/documents/Documents.ts | 8 ++++---- src/client/views/PropertiesView.scss | 3 +-- src/client/views/PropertiesView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 14 ++++++++++---- src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 8 ++++---- 6 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0c16d9f8f..3e29a4edf 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -990,7 +990,7 @@ export namespace DocUtils { * @param viewSpecScript * Given a list of docs and docFilters, @returns the list of Docs that match those filters */ - export function FilterDocs(docs: Doc[], docFilters: string[], docRangeFilters: string[], viewSpecScript?: ScriptField) { + export function FilterDocs(docs: Doc[], docFilters: string[], docRangeFilters: string[], viewSpecScript?: ScriptField, parentCollection?: Doc) { const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; if (!docFilters?.length && !docRangeFilters?.length) { return childDocs.filter(d => !d.cookies); // remove documents that need a cookie if there are no filters to provide one @@ -1040,16 +1040,16 @@ export namespace DocUtils { return Field.toString(d[facetKey] as Field).includes(value); }); // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria - if ((FilterBox.targetDoc.currentFilter as Doc).filterBoolean === "OR") { + if (((FilterBox._filterScope === "Current Collection" ? parentCollection || CurrentUserUtils.ActiveDashboard : CurrentUserUtils.ActiveDashboard).currentFilter as Doc)?.filterBoolean === "OR") { if (satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria else { - if (!satisfiesCheckFacets || failsNotEqualFacets || (matches.length && satisfiesMatchFacets)) return false; + if (!satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; } } - return (FilterBox.targetDoc.currentFilter as Doc).filterBoolean === "OR" ? false : true; + return ((FilterBox._filterScope === "Current Collection" ? parentCollection || CurrentUserUtils.ActiveDashboard : CurrentUserUtils.ActiveDashboard).currentFilter as Doc)?.filterBoolean === "OR" ? false : true; }) : childDocs; const rangeFilteredDocs = filteredDocs.filter(d => { for (let i = 0; i < docRangeFilters.length; i += 3) { diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 7c6d507b8..04934d50b 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -191,8 +191,7 @@ font-size: 10px; padding: 10px; margin-left: 5px; - max-height: 40%; - overflow-y: scroll; + max-height: 40%;overflow-y: scroll; .propertiesView-buttonContainer { float: right; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 1f4685bf2..1e96d62d2 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -51,7 +51,7 @@ export class PropertiesView extends React.Component { @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } @computed get filterDoc() { - return FilterBox.targetDoc; + return FilterBox._filterScope === "Current Collection" ? this.selectedDoc! : CurrentUserUtils.ActiveDashboard; } @computed get selectedDocumentView() { if (SelectionManager.Views().length) return SelectionManager.Views()[0]; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 05e9ac265..3e6deaf3a 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -82,7 +82,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: return Cast(this.dataField, listSpec(Doc)); } docFilters = () => { - return [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])]; + return [...this.props.docFilters(), ...Cast(FilterBox._filterScope === "Current Collection" ? this.props.Document._docFilters : CurrentUserUtils.ActiveDashboard._docFilters, listSpec("string"), [])]; } docRangeFilters = () => { return [...this.props.docRangeFilters(), ...Cast(this.props.Document._docRangeFilters, listSpec("string"), [])]; @@ -114,10 +114,15 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: return childDocs.filter(cd => !cd.cookies); // remove any documents that require a cookie if there are no filters to provide one } + // console.log(CurrentUserUtils.ActiveDashboard._docFilters); + if (!this.props.Document._docFilters && this.props.Document.currentFilter) { + (this.props.Document.currentFilter as Doc).filterBoolean = (this.props.ContainingCollectionDoc?.currentFilter as Doc)?.filterBoolean; + } const docsforFilter: Doc[] = []; + console.log(this.props.Document.system); childDocs.forEach((d) => { // if (DocUtils.Excluded(d, docFilters)) return; - let notFiltered = d.z || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript).length > 0)); + let notFiltered = d.z || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); const data = d[annos ? fieldKey + "-annotations" : fieldKey]; @@ -125,13 +130,13 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: let subDocs = DocListCast(data); if (subDocs.length > 0) { let newarray: Doc[] = []; - notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, docFilters, docRangeFilters, viewSpecScript).length); + notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, docFilters, docRangeFilters, viewSpecScript, this.props.Document).length); while (subDocs.length > 0 && !notFiltered) { newarray = []; subDocs.forEach((t) => { const fieldKey = Doc.LayoutFieldKey(t); const annos = !Field.toString(Doc.LayoutField(t) as Field).includes("CollectionView"); - notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!docFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], docFilters, docRangeFilters, viewSpecScript).length)); + notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!docFilters.length && !docRangeFilters.length) || DocUtils.FilterDocs([t], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length)); DocListCast(t[annos ? fieldKey + "-annotations" : fieldKey]).forEach((newdoc) => newarray.push(newdoc)); }); subDocs = newarray; @@ -481,4 +486,5 @@ import { SelectionManager } from "../../util/SelectionManager"; import { OverlayView } from "../OverlayView"; import { Hypothesis } from "../../util/HypothesisUtils"; import { GetEffectiveAcl } from "../../../fields/util"; +import { FilterBox } from "../nodes/FilterBox"; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 4f37747b0..020bb374a 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -122,7 +122,7 @@ export class CollectionView extends Touchable { * Applies the collection/dashboard's current filter attributes to the doc being added */ addFilterAttributes = (doc: Doc) => { - Cast(FilterBox.targetDoc._docFilters, listSpec("string"))?.forEach(attribute => { + Cast((FilterBox._filterScope === "Current Collection" ? this.props.Document : CurrentUserUtils.ActiveDashboard)._docFilters, listSpec("string"))?.forEach(attribute => { if (attribute.charAt(0).toUpperCase() === attribute.charAt(0)) { const fields = attribute.split(':'); if (fields[2] === "check") doc[DataSym][fields[0]] = fields[1]; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 01372c284..b9a981e77 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -81,8 +81,9 @@ export class FilterBox extends ViewBoxBaseComponent(); const targetDoc = FilterBox.targetDoc; if (this._loaded && targetDoc) { @@ -109,7 +110,7 @@ export class FilterBox extends ViewBoxBaseComponent(noviceFields); this.allDocs.forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key))); return Array.from(keys.keys()).filter(key => key[0]).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("_")) || noviceFields.includes(key) || !Doc.UserDoc().noviceMode).sort(); - // return []; } -- cgit v1.2.3-70-g09d2 From f98acc39b7bd88e1f260bab9b6e072c5401b46d3 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sun, 4 Apr 2021 14:51:22 -0400 Subject: stopped system docs from being filtered --- src/client/documents/Documents.ts | 2 +- src/client/views/collections/CollectionSubView.tsx | 3 +-- src/fields/Doc.ts | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 12d8445b4..adebb9b1c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -651,7 +651,7 @@ export namespace Docs { const viewKeys = ["x", "y", "system"]; // keys that should be addded to the view document even though they don't begin with an "_" const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_"); - dataProps.system = viewProps.system; + dataProps.system = viewProps.system ? (viewProps.system) : (viewProps.system = false); dataProps.isPrototype = true; dataProps.author = Doc.CurrentUserEmail; dataProps.creationDate = new DateField; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 79fab8b62..89df60213 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -119,10 +119,9 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: (this.props.Document.currentFilter as Doc).filterBoolean = (this.props.ContainingCollectionDoc?.currentFilter as Doc)?.filterBoolean; } const docsforFilter: Doc[] = []; - console.log(this.props.Document.system); childDocs.forEach((d) => { // if (DocUtils.Excluded(d, docFilters)) return; - let notFiltered = d.z || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); + let notFiltered = d.z || d.system || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); const data = d[annos ? fieldKey + "-annotations" : fieldKey]; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index c36bfb04b..44eb7536e 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1077,7 +1077,7 @@ export namespace Doc { // filters document in a container collection: // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined - export function setDocFilter(container: Opt, key: string, value: any, modifiers: "remove" | "match" | "check" | "x", toggle?: boolean, fieldSuffix?: string) { + export function setDocFilter(container: Opt, key: string, value: any, modifiers: "remove" | "match" | "check" | "x", toggle?: boolean, fieldSuffix?: string, append: boolean = true) { if (!container) return; const filterField = "_" + (fieldSuffix ? fieldSuffix + "-" : "") + "docFilters"; const docFilters = Cast(container[filterField], listSpec("string"), []); @@ -1146,6 +1146,7 @@ export namespace Doc { dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1; Doc.SetInPlace(ndoc, "title", ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString(), true); } + ndoc && (ndoc.system = false); return ndoc; } export function delegateDragFactory(dragFactory: Doc) { -- cgit v1.2.3-70-g09d2 From d913e2dd6f5a292cf1bc90e65280133642219949 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 5 Apr 2021 01:27:06 -0400 Subject: deleted some commented code + other small stuff --- src/client/views/PropertiesView.scss | 3 ++- src/client/views/PropertiesView.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 3 +-- src/client/views/nodes/FilterBox.scss | 4 ++++ src/client/views/nodes/FilterBox.tsx | 13 +++---------- 5 files changed, 12 insertions(+), 15 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 04934d50b..7c6d507b8 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -191,7 +191,8 @@ font-size: 10px; padding: 10px; margin-left: 5px; - max-height: 40%;overflow-y: scroll; + max-height: 40%; + overflow-y: scroll; .propertiesView-buttonContainer { float: right; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 9fc19253e..9c1b8e593 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -965,8 +965,8 @@ export class PropertiesView extends React.Component { scriptContext={this.filterDoc.currentFilter as Doc} focus={emptyFunction} styleProvider={DefaultStyleProvider} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} + isContentActive={returnTrue} + whenChildContentsActiveChanged={emptyFunction} bringToFront={emptyFunction} docFilters={returnEmptyFilter} docRangeFilters={returnEmptyFilter} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 37600fa4d..ed0ed63b3 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -37,8 +37,7 @@ export type collectionTreeViewProps = { }; @observer -export class - CollectionTreeView extends CollectionSubView>(Document) { +export class CollectionTreeView extends CollectionSubView>(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; MainEle = () => this._mainEle; diff --git a/src/client/views/nodes/FilterBox.scss b/src/client/views/nodes/FilterBox.scss index 4fe1fa2eb..107ad2e36 100644 --- a/src/client/views/nodes/FilterBox.scss +++ b/src/client/views/nodes/FilterBox.scss @@ -161,6 +161,10 @@ z-index: 1; background-color: #9F9F9F; + .filterBox-tree { + z-index: 0; + } + .filterBox-addfacet { display: inline-block; width: 200px; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 1d3f6a7cc..af95c96fb 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -2,7 +2,7 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { computed, observable, action, trace, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { DataSym, Doc, DocListCast, Field, Opt, DocListCastAsync } from "../../../fields/Doc"; +import { Doc, DocListCast, Field, Opt, DocListCastAsync } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { List } from "../../../fields/List"; import { RichTextField } from "../../../fields/RichTextField"; @@ -198,9 +198,6 @@ export class FilterBox extends ViewBoxBaseComponent { - - console.log("facetClick: " + facetHeader); - console.log(this.props.fieldKey); const targetDoc = FilterBox.targetDoc; const found = this.activeAttributes.findIndex(doc => doc.title === facetHeader); if (found !== -1) { @@ -242,8 +239,6 @@ export class FilterBox extends ViewBoxBaseComponent
filters in
-- cgit v1.2.3-70-g09d2 From 00127a4fccbd00eb3d05699a3a14f52feb7b57db Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Tue, 6 Apr 2021 00:14:21 -0400 Subject: minor cleanup + style across files --- src/client/views/DocumentDecorations.tsx | 10 +++++----- src/client/views/PropertiesView.tsx | 4 ++-- src/client/views/StyleProvider.tsx | 1 + src/client/views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 7 +++---- src/client/views/nodes/LinkDocPreview.tsx | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index ce7ff1bbd..e23374cea 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -83,7 +83,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b UndoManager.RunInBatch(() => titleFieldKey && SelectionManager.Views().forEach(d => { titleFieldKey === "title" && (d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-")); //@ts-ignore - Doc.SetInPlace(d.rootDoc, titleFieldKey, +this._accumulatedTitle == this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle, true); + Doc.SetInPlace(d.rootDoc, titleFieldKey, +this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle, true); }), "title blur"); } } @@ -376,10 +376,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/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index df4dd7788..782a0e29e 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -951,7 +951,7 @@ export class PropertiesView extends React.Component { !this.openFilters ? (null) :
{ PanelWidth={() => this.props.width} PanelHeight={this.filterDoc.currentFilter[HeightSym]} renderDepth={0} - scriptContext={this.filterDoc.currentFilter as Doc} + scriptContext={this.filterDoc.currentFilter} focus={emptyFunction} styleProvider={DefaultStyleProvider} isContentActive={returnTrue} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index d1e2fefcb..3853d5888 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -18,6 +18,7 @@ import "./collections/TreeView.scss"; import "./nodes/FilterBox.scss"; import React = require("react"); import Color = require('color'); +import { FieldViewProps } from './nodes/FieldView'; export enum StyleLayers { Background = "background" diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a9e73583d..959864a60 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -59,7 +59,7 @@ export class CollectionTreeView extends CollectionSubView this.rootDoc.autoHeight, auto => auto && this.computeHeight(), - { fireImmediately: true }) + { fireImmediately: true }); } refList: Set = new Set(); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 2c3a6c0d7..5df33afe0 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -174,7 +174,7 @@ export class TreeView extends React.Component { componentWillUnmount() { this._selDisposer?.(); - this._treeEle && this.props.unobserveHeight(this._treeEle) + this._treeEle && this.props.unobserveHeight(this._treeEle); document.removeEventListener("pointermove", this.onDragMove, true); document.removeEventListener("pointermove", this.onDragUp, true); } diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index ae5b79aec..30d7ed187 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -82,9 +82,8 @@ export class FilterBox extends ViewBoxBaseComponent { const targetDoc = FilterBox.targetDoc; const filterDoc = targetDoc.currentFilter as Doc; - const attributes = DocListCast(filterDoc["data"]); + const attributes = DocListCast(filterDoc.data); const found = attributes.findIndex(doc => doc.title === filterName); if (found !== -1) { - (filterDoc["data"] as List).splice(found, 1); + (filterDoc.data as List).splice(found, 1); const docFilter = Cast(targetDoc._docFilters, listSpec("string")); if (docFilter) { let index: number; diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 45e3c8382..b73fb10df 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -26,7 +26,7 @@ interface LinkDocPreviewProps { @observer export class LinkDocPreview extends React.Component { @action public static Clear() { LinkDocPreview.LinkInfo = undefined; } - @action public static SetLinkInfo(info?: LinkDocPreviewProps) { LinkDocPreview.LinkInfo != info && (LinkDocPreview.LinkInfo = info); } + @action public static SetLinkInfo(info?: LinkDocPreviewProps) { LinkDocPreview.LinkInfo !== info && (LinkDocPreview.LinkInfo = info); } _infoRef = React.createRef(); @observable public static LinkInfo: Opt; -- cgit v1.2.3-70-g09d2 From e675858cfab46300a543b1013c7f88c8233ed7ad Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 6 Apr 2021 11:09:26 -0400 Subject: added ability to remove filters using inline context menu --- .../views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 12 +++++--- src/client/views/nodes/DocumentView.tsx | 5 ++-- src/client/views/nodes/FilterBox.tsx | 34 ++++++++-------------- 4 files changed, 24 insertions(+), 29 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 959864a60..55fe84835 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -101,7 +101,7 @@ export class CollectionTreeView extends CollectionSubView !docs.includes(v)); - SelectionManager.DeselectAll(); + if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views().some(dv => Doc.AreProtosEqual(dv.rootDoc, doc)))) SelectionManager.DeselectAll(); if (result.length !== value.length) { const ind = targetDataDoc[this.props.fieldKey].indexOf(doc); const prev = ind && targetDataDoc[this.props.fieldKey][ind - 1]; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 5df33afe0..8a5425992 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -21,7 +21,7 @@ import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { EditableView } from "../EditableView"; import { TREE_BULLET_WIDTH } from '../globalCssVariables.scss'; -import { DocumentView, DocumentViewProps, StyleProviderFunc } from '../nodes/DocumentView'; +import { DocumentView, DocumentViewProps, StyleProviderFunc, DocumentViewInternal } from '../nodes/DocumentView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { KeyValueBox } from '../nodes/KeyValueBox'; @@ -483,17 +483,21 @@ export class TreeView extends React.Component { } @computed get headerElements() { - return this.props.treeViewHideHeaderFields() || Doc.IsSystem(this.doc) ? (null) + return this.props.treeViewHideHeaderFields() ? (null) : <> { this.showContextMenu(e); e.stopPropagation(); }} /> - {this.doc.treeViewExpandedViewLock ? (null) : + {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? (null) : {this.treeViewExpandedView} } ; } - showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); + showContextMenu = (e: React.MouseEvent) => { + DocumentViewInternal.SelectOnContextsMenu = false; + simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); + DocumentViewInternal.SelectOnContextsMenu = true; + } contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : this.doc.isFolder ? [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : 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 1c4008a55..703e78470 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -658,7 +658,7 @@ export class DocumentViewInternal extends DocComponent - cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" })); + 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" })); @@ -746,8 +746,9 @@ export class DocumentViewInternal extends DocComponent SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + DocumentViewInternal.SelectOnContextsMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. } + public static SelectOnContextsMenu = true; rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; panelHeight = () => this.props.PanelHeight() - this.headerMargin; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 30d7ed187..0a010c105 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -167,7 +167,7 @@ export class FilterBox extends ViewBoxBaseComponent (doc instanceof Doc ? [doc] : doc).map(doc => this.removeFilter(StrCast(doc.title))).length ? true : false; public removeFilter = (filterName: string) => { const targetDoc = FilterBox.targetDoc; const filterDoc = targetDoc.currentFilter as Doc; @@ -190,8 +190,8 @@ export class FilterBox extends ViewBoxBaseComponent doc.title === facetHeader); if (found !== -1) { - // comment this bit out later once the x works in treeview - (this.dataDoc[this.props.fieldKey] as List).splice(found, 1); - const docFilter = Cast(targetDoc._docFilters, listSpec("string")); - if (docFilter) { - let index: number; - while ((index = docFilter.findIndex(item => item.split(":")[0] === facetHeader)) !== -1) { - docFilter.splice(index, 1); - } - } - const docRangeFilters = Cast(targetDoc._docRangeFilters, listSpec("string")); - if (docRangeFilters) { - let index: number; - while ((index = docRangeFilters.findIndex(item => item.split(":")[0] === facetHeader)) !== -1) { - docRangeFilters.splice(index, 3); - } - } + this.removeFilter(facetHeader); } else { const allCollectionDocs = DocListCast((targetDoc.data as any)[0].data); const facetValues = this.gatherFieldValues(targetDoc, facetHeader); @@ -232,7 +217,7 @@ export class FilterBox extends ViewBoxBaseComponent; if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) { - newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, system: true, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, _forceActive: true, ignoreClick: true }); + newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, system: true, _stayInCollection: true, treeViewExpandedView: "layout", title: facetHeader, 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; const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`; @@ -261,7 +246,11 @@ export class FilterBox extends ViewBoxBaseComponent([remove!]); + newFacet.contextMenuLabels = new List(["Remove"]); + Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet); } } @@ -450,7 +439,7 @@ export class FilterBox extends ViewBoxBaseComponent
@@ -519,6 +508,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string) const facetValues = Array.from(set).filter(v => v); let nonNumbers = 0; + facetValues.map(val => Number.isNaN(Number(val)) && nonNumbers++); const facetValueDocSet = (nonNumbers / facetValues.length > .1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2))).map(facetValue => { const doc = new Doc(); -- cgit v1.2.3-70-g09d2 From d01fdacae8e96c99a095dd2c97f62144ab81def5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 6 Apr 2021 13:01:12 -0400 Subject: fix to get text filtering to work. --- src/client/views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ca8777de8..a8a2aaa5a 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -67,7 +67,7 @@ export class CollectionTreeView extends CollectionSubView disposer?.()); } - componentWillMount() { + componentDidMount() { this._disposers.autoheight = reaction(() => this.rootDoc.autoHeight, auto => auto && this.computeHeight(), { fireImmediately: true }); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 8a5425992..827dadae2 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -730,7 +730,7 @@ export class TreeView extends React.Component { return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
this.props.isContentActive(true) && SelectionManager.DeselectAll()} + //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document onKeyDown={this.onKeyDown}>
  • {hideTitle && this.doc.type !== DocumentType.RTF ? diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 0a010c105..718ebca28 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -217,13 +217,19 @@ export class FilterBox extends ViewBoxBaseComponent; if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) { - newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, system: true, _stayInCollection: true, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, _forceActive: true, ignoreClick: true }); + newFacet = Docs.Create.TextDocument("", { + _width: 100, _height: 25, system: true, _stayInCollection: true, target: targetDoc, + treeViewExpandedView: "layout", title: facetHeader, 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; const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`; 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, _height: 40, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", treeViewOpen: true }); + newFacet = Docs.Create.SliderDocument({ + title: facetHeader, _overflow: "visible", _fitWidth: true, + _height: 40, _stayInCollection: true, treeViewExpandedView: "layout", treeViewOpen: true + }); const newFacetField = Doc.LayoutFieldKey(newFacet); const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader); Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox -- cgit v1.2.3-70-g09d2 From ddc432ee518a9201f04d8ea3715ae7d00583fa76 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Tue, 6 Apr 2021 13:14:58 -0400 Subject: finished adding docrangefilters --- src/client/views/collections/CollectionSubView.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 57e1a50bb..0c022eba3 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -82,7 +82,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: return Cast(this.dataField, listSpec(Doc)); } docFilters = () => { - return [...this.props.docFilters(), ...Cast(this.props.Document?._docFilters, listSpec("string"), [])]; + return [...this.props.docFilters(), ...Cast(this.props.Document._docFilters, listSpec("string"), [])]; } docRangeFilters = () => { return [...this.props.docRangeFilters(), ...Cast(this.props.Document._docRangeFilters, listSpec("string"), [])]; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 30d7ed187..2f354c2da 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -287,14 +287,22 @@ export class FilterBox extends ViewBoxBaseComponent { if (FilterBox._filterScope === "Current Dashboard" && e.currentTarget.value === "Current Collection") { - const temp = CurrentUserUtils.ActiveDashboard._docFilters; + const currentDashboardDocFilters = CurrentUserUtils.ActiveDashboard._docFilters; CurrentUserUtils.ActiveDashboard._docFilters = new List(); - (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docFilterList = temp; + (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docFilterList = currentDashboardDocFilters; + + const currentDashboardDocRangeFilters = CurrentUserUtils.ActiveDashboard._docRangeFilters; + CurrentUserUtils.ActiveDashboard._docRangeFilters = new List(); + (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docRangeFilterList = currentDashboardDocRangeFilters; } else if (FilterBox._filterScope === "Current Collection" && e.currentTarget.value === "Current Dashboard") { - const temp = (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docFilterList; + const savedDashboardDocFilters = (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docFilterList; (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docFilterList = undefined; - CurrentUserUtils.ActiveDashboard._docFilters = temp; + CurrentUserUtils.ActiveDashboard._docFilters = savedDashboardDocFilters; + + const savedDashboardDocRangeFilters = (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docRangeFilterList; + (CurrentUserUtils.ActiveDashboard.currentFilter as Doc)._docRangeFilterList = undefined; + CurrentUserUtils.ActiveDashboard._docRangeFilters = savedDashboardDocRangeFilters; } FilterBox._filterScope = e.currentTarget.value; } -- cgit v1.2.3-70-g09d2 From 998e9b239d1d97d5f4a44e8b7fb29c97e02002c4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 6 Apr 2021 14:28:50 -0400 Subject: another fix for texts filters and for not recomputing when a docfilter change doesn't actually affect the colletion children list. --- src/client/views/collections/CollectionSubView.tsx | 5 +++-- src/client/views/collections/CollectionTreeView.tsx | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 57e1a50bb..542cbfe75 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -90,7 +90,8 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: searchFilterDocs = () => { return [...this.props.searchFilterDocs(), ...DocListCast(this.props.Document._searchFilterDocs)]; } - @computed get childDocs() { + @computed.struct get childDocs() { + TraceMobx(); let rawdocs: (Doc | Promise)[] = []; if (this.dataField instanceof Doc) { // if collection data is just a document, then promote it to a singleton list; rawdocs = [this.dataField]; @@ -478,6 +479,6 @@ import { CollectionView, CollectionViewType, CollectionViewProps } from "./Colle import { SelectionManager } from "../../util/SelectionManager"; import { OverlayView } from "../OverlayView"; import { Hypothesis } from "../../util/HypothesisUtils"; -import { GetEffectiveAcl } from "../../../fields/util"; +import { GetEffectiveAcl, TraceMobx } from "../../../fields/util"; import { FilterBox } from "../nodes/FilterBox"; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a8a2aaa5a..82c8a9114 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -49,7 +49,7 @@ export class CollectionTreeView extends CollectionSubView p + Number(getComputedStyle(r).height.replace("px", "")), 0); this.props.setHeight(hgt); } - unobserveHeight = (ref: any) => this.refList.delete(ref); + unobserveHeight = (ref: any) => { + this.refList.delete(ref); + this.rootDoc.autoHeight && this.computeHeight(); + } observerHeight = (ref: any) => { if (ref) { this.refList.add(ref); @@ -116,11 +119,10 @@ export class CollectionTreeView extends CollectionSubView(result); + this.props.removeDocument?.(doc); if (ind > 0) { FormattedTextBox.SelectOnLoad = prev[Id]; - const prevView = DocumentManager.Instance.getDocumentView(prev, this.props.CollectionView); - prevView?.select(false); + DocumentManager.Instance.getDocumentView(prev, this.props.CollectionView)?.select(false); } return true; } -- cgit v1.2.3-70-g09d2 From 13879075b8347abeecbb178596dc839e7ecdfb54 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 6 Apr 2021 16:41:41 -0400 Subject: switched from context menu to a delete button on filterBox filters. don't select treeView items after expanding them. --- src/client/views/collections/TreeView.tsx | 6 ++-- src/client/views/nodes/FilterBox.tsx | 56 +++++++++++++++++++------------ 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 827dadae2..c7322598c 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -152,7 +152,6 @@ export class TreeView extends React.Component { } else { this.props.addDocTab(this.props.document, "add:right"); } - docView?.select(false); } constructor(props: any) { super(props); @@ -483,9 +482,9 @@ export class TreeView extends React.Component { } @computed get headerElements() { - return this.props.treeViewHideHeaderFields() ? (null) + return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? (null) : <> - { this.showContextMenu(e); e.stopPropagation(); }} /> + {this.doc.hideContextMenu ? (null) : { this.showContextMenu(e); e.stopPropagation(); }} />} {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? (null) : {this.treeViewExpandedView} @@ -526,7 +525,6 @@ export class TreeView extends React.Component { }}> {StrCast(doc?.title)}
  • ; - case StyleProp.Decorations: return (null); default: return this.props?.treeView?.props.styleProvider?.(doc, props, property); } } diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index e1227b81d..a43b80e5b 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -31,6 +31,7 @@ import { DefaultStyleProvider, StyleProp } from "../StyleProvider"; import { CollectionViewType } from "../collections/CollectionView"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; import { EditableView } from "../EditableView"; +import { undoBatch } from "../../util/UndoManager"; type FilterBoxDocument = makeInterface<[typeof documentSchema]>; const FilterBoxDocument = makeInterface(documentSchema); @@ -251,10 +252,7 @@ export class FilterBox extends ViewBoxBaseComponent([remove!]); - newFacet.contextMenuLabels = new List(["Remove"]); + newFacet.hideContextMenu = true; Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet); } } @@ -323,23 +321,21 @@ export class FilterBox extends ViewBoxBaseComponent, props: Opt, property: string) { switch (property.split(":")[0]) { case StyleProp.Decorations: - if (doc) { - return doc._viewType === CollectionViewType.Docking || (Doc.IsSystem(doc)) ? (null) : - <> -
    - -
    -
    this.removeFilter(StrCast(doc.title))}> - -
    - ; + if (doc && !doc.treeViewHideHeaderFields) { + return <> +
    + +
    +
    this.removeFilter(StrCast(doc.title))}> + +
    + ; } - default: return DefaultStyleProvider(doc, props, property); - } + return DefaultStyleProvider(doc, props, property); } suppressChildClick = () => ScriptField.MakeScript("")!; @@ -376,6 +372,24 @@ export class FilterBox extends ViewBoxBaseComponent, props: Opt, property: string) => { + switch (property.split(":")[0]) { + case StyleProp.Decorations: + return !doc || doc.treeViewHideHeaderFields ? (null) : // 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 + <> +
    + this.removeFilter(StrCast(doc.title)) + )}> + +
    + ; + } + return this.props.styleProvider?.(doc, props, property); + } + layoutHeight = () => this.layoutDoc[HeightSym](); render() { const facetCollection = this.props.Document; @@ -431,7 +445,6 @@ export class FilterBox extends ViewBoxBaseComponent Date: Tue, 6 Apr 2021 17:59:50 -0400 Subject: little cleanup --- src/client/views/EditableView.tsx | 1 - src/client/views/StyleProvider.tsx | 3 ++- src/client/views/collections/TreeView.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 5daac77ee..03d9efff3 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -47,7 +47,6 @@ export interface EditableProps { toggle?: () => void; background?: string | undefined; placeholder?: string; - fullWidth?: boolean; // used in PropertiesView to make the whole key:value input box clickable } /** diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 3853d5888..d15cd5458 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -69,13 +69,14 @@ export function DefaultStyleProvider(doc: Opt, props: Opt StrListCast(doc?._layerTags).includes(StyleLayers.Background); const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor); const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity); const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle); switch (property.split(":")[0]) { - case StyleProp.TreeViewIcon: return doc ? Doc.toIcon(doc) : "question"; + case StyleProp.TreeViewIcon: return doc?.isFolder ? "chevron-" + (isOpen ? "down" : "right") : doc ? Doc.toIcon(doc) : "question"; case StyleProp.DocContents: return undefined; case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey"; case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null)); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index c7322598c..5cf8a6986 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -441,7 +441,7 @@ export class TreeView extends React.Component { @computed get renderBullet() { TraceMobx(); - const iconType = this.doc.isFolder ? (this.treeViewOpen ? "chevron-down" : "chevron-right") : Doc.toIcon(this.doc); + const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ":open" : "")) || "question"; const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; return
    Date: Tue, 6 Apr 2021 18:39:20 -0400 Subject: reverted back to not setting 'system' for non-system documents. --- src/client/documents/Documents.ts | 2 +- src/client/views/PropertiesView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 2 +- src/fields/Doc.ts | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 65dd826ef..3b40f0cc7 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -652,7 +652,7 @@ export namespace Docs { const viewKeys = ["x", "y", "system"]; // keys that should be addded to the view document even though they don't begin with an "_" const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_"); - dataProps.system = viewProps.system ? (viewProps.system) : (viewProps.system = false); + dataProps.system = viewProps.system; dataProps.isPrototype = true; dataProps.author = Doc.CurrentUserEmail; dataProps.creationDate = new DateField; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 0b1d75970..92fe3acb5 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -28,7 +28,7 @@ import { PresBox } from "./nodes/PresBox"; import { PropertiesButtons } from "./PropertiesButtons"; import { PropertiesDocContextSelector } from "./PropertiesDocContextSelector"; import "./PropertiesView.scss"; -import { DefaultStyleProvider, FilteringStyleProvider } from "./StyleProvider"; +import { DefaultStyleProvider } from "./StyleProvider"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; import { FilterBox } from "./nodes/FilterBox"; import { List } from "../../fields/List"; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index bc5a6129c..b998555d8 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -122,7 +122,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: const docsforFilter: Doc[] = []; childDocs.forEach((d) => { // if (DocUtils.Excluded(d, docFilters)) return; - let notFiltered = d.z || d.system || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); + let notFiltered = d.z || Doc.IsSystem(d) || ((!searchDocs.length || searchDocs.includes(d)) && (DocUtils.FilterDocs([d], docFilters, docRangeFilters, viewSpecScript, this.props.Document).length > 0)); const fieldKey = Doc.LayoutFieldKey(d); const annos = !Field.toString(Doc.LayoutField(d) as Field).includes("CollectionView"); const data = d[annos ? fieldKey + "-annotations" : fieldKey]; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 06b1b8539..01d0a8176 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1147,7 +1147,6 @@ export namespace Doc { dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1; Doc.SetInPlace(ndoc, "title", ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString(), true); } - ndoc && (ndoc.system = false); return ndoc; } export function delegateDragFactory(dragFactory: Doc) { -- cgit v1.2.3-70-g09d2 From fcbe1957d985655167ee8365fbb8f2755bbfd206 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 6 Apr 2021 18:51:01 -0400 Subject: cleanup --- src/client/views/collections/CollectionView.tsx | 4 +--- src/client/views/collections/TreeView.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 91f159d8e..4dc0ee3e6 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,4 +1,4 @@ -import { action, computed, observable } from 'mobx'; +import { computed, observable } from 'mobx'; import { observer } from "mobx-react"; import * as React from 'react'; import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app @@ -35,8 +35,6 @@ import { SubCollectionViewProps } from './CollectionSubView'; import { CollectionTimeView } from './CollectionTimeView'; import { CollectionTreeView } from "./CollectionTreeView"; import './CollectionView.scss'; -import { FilterBox } from '../nodes/FilterBox'; -import { listSpec } from '../../../fields/Schema'; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 5cf8a6986..2cce9c2f5 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -493,9 +493,9 @@ export class TreeView extends React.Component { } showContextMenu = (e: React.MouseEvent) => { - DocumentViewInternal.SelectOnContextsMenu = false; + DocumentViewInternal.SelectAfterContextMenu = false; simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); - DocumentViewInternal.SelectOnContextsMenu = true; + DocumentViewInternal.SelectAfterContextMenu = true; } contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : this.doc.isFolder ? [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 703e78470..5c3d7e415 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -162,6 +162,7 @@ export interface DocumentViewInternalProps extends DocumentViewProps { @observer export class DocumentViewInternal extends DocComponent(Document) { + public static SelectAfterContextMenu = true; // whether a document should be selected after it's contextmenu is triggered. @observable _animateScalingTo = 0; @observable _mediaState = 0; @observable _pendingDoubleClick = false; @@ -746,9 +747,8 @@ export class DocumentViewInternal extends DocComponent SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. } - public static SelectOnContextsMenu = true; rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false; panelHeight = () => this.props.PanelHeight() - this.headerMargin; -- cgit v1.2.3-70-g09d2 From d021eb6fe792e9c76b139b5a706a90a086f3fe53 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 8 Apr 2021 12:59:22 -0400 Subject: made "search" only appear if context menu is > 15 items. --- src/client/views/ContextMenu.tsx | 27 ++-- src/client/views/ContextMenuItem.tsx | 7 +- src/client/views/collections/TreeView.tsx | 17 ++- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 149 +++++++++++---------- 5 files changed, 106 insertions(+), 96 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 1f7abf61a..d96de72e3 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -15,6 +15,7 @@ export class ContextMenu extends React.Component { @observable private _pageY: number = 0; @observable private _display: boolean = false; @observable private _searchString: string = ""; + @observable private _showSearch: boolean = false; // afaik displaymenu can be called before all the items are added to the menu, so can't determine in displayMenu what the height of the menu will be @observable private _yRelativeToTop: boolean = true; @observable selectedIndex = -1; @@ -137,11 +138,13 @@ export class ContextMenu extends React.Component { return y; } + @action - displayMenu = (x: number, y: number, initSearch = "") => { + displayMenu = (x: number, y: number, initSearch = "", showSearch = false) => { //maxX and maxY will change if the UI/font size changes, but will work for any amount //of items added to the menu + this._showSearch = showSearch; this._pageX = x; this._pageY = y; this._searchString = initSearch; @@ -215,11 +218,15 @@ export class ContextMenu extends React.Component { @computed get menuItems() { if (!this._searchString) { - return this._items.map(item => ); + return this._items.map(item => ); } return this.filteredViews; } + @computed get itemsNeedSearch() { + return this._showSearch ? 1 : this._items.reduce((p, mi) => p + ((mi as any).noexpand ? 1 : (mi as any).subitems?.length || 1), 0) > 15; + } + render() { if (!this._display) { return null; @@ -229,12 +236,13 @@ export class ContextMenu extends React.Component { const contents = ( <> - - - - - - + {!this.itemsNeedSearch ? (null) : + + + + + + } {this.menuItems} ); @@ -244,8 +252,7 @@ export class ContextMenu extends React.Component {
    {contents}
    - ) - } + )} ); } diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index e63631161..6fe2abd21 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -4,7 +4,6 @@ import { observer } from "mobx-react"; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { UndoManager } from "../util/UndoManager"; -import { NumberLiteralType } from "typescript"; export interface OriginalMenuProps { description: string; @@ -33,8 +32,8 @@ export class ContextMenuItem extends React.Component this._items.push(i)); + if ((this.props as SubmenuProps).subitems) { + (this.props as SubmenuProps).subitems?.forEach(i => this._items.push(i)); } } @@ -107,7 +106,7 @@ export class ContextMenuItem extends React.Component {this._items.map(prop => )}
    ; - if (!("noexpand" in this.props)) { + if (!(this.props as SubmenuProps).noexpand) { return
    {this._items.map(prop => )}
    ; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 2c3a6c0d7..43f9627e2 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -483,10 +483,10 @@ export class TreeView extends React.Component { } @computed get headerElements() { - return this.props.treeViewHideHeaderFields() || Doc.IsSystem(this.doc) ? (null) + return this.props.treeViewHideHeaderFields() || (Doc.IsSystem(this.doc) && !this.doc.isFolder) ? (null) : <> { this.showContextMenu(e); e.stopPropagation(); }} /> - {this.doc.treeViewExpandedViewLock ? (null) : + {this.doc.isFolder || this.doc.treeViewExpandedViewLock ? (null) : {this.treeViewExpandedView} } @@ -494,11 +494,14 @@ export class TreeView extends React.Component { } showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30); - contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : this.doc.isFolder ? - [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] : - this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ? - [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }] : - [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }] + contextMenuItems = () => { + const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }; + return this.doc.isFolder ? [makeFolder] : + Doc.IsSystem(this.doc) ? [] : + this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ? + [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }, makeFolder] : + [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }]; + } onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick)); onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d14b68fa7..a4f129b8c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -101,7 +101,7 @@ export class MarqueeView extends React.Component 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" })); - const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); - const appearance = cm.findByDescription("UI Controls..."); - const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : []; - !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" }); - DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" }); - !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" }); - - if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { - !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" }); - const existingOnClick = cm.findByDescription("OnClick..."); - const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; - - const zorders = cm.findByDescription("ZOrder..."); - const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : []; - zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" }); - zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" }); - zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" }); - !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" }); - - onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); - onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); - onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" }); - - if (!this.Document.annotationOn) { - const options = cm.findByDescription("Options..."); - const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; - !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); - - onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); - onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); - !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" }); - onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" }); - onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" }); - onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" }); - !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, noexpand: true, subitems: onClicks, icon: "mouse-pointer" }); - } else if (DocListCast(this.Document.links).length) { - onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" }); - onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" }); - onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" }); - !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); + if (!this.props.Document.isFolder) { + const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null); + const appearance = cm.findByDescription("UI Controls..."); + const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : []; + !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" }); + DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" }); + !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" }); + + if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) { + !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" }); + const existingOnClick = cm.findByDescription("OnClick..."); + const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; + + const zorders = cm.findByDescription("ZOrder..."); + const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : []; + zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" }); + zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" }); + zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" }); + !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" }); + + onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); + onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); + onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" }); + + if (!this.Document.annotationOn) { + const options = cm.findByDescription("Options..."); + const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; + !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); + + onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); + onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); + !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" }); + onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" }); + onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" }); + onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" }); + !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, noexpand: true, subitems: onClicks, icon: "mouse-pointer" }); + } else if (DocListCast(this.Document.links).length) { + onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" }); + onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" }); + onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" }); + !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); + } } - } - const funcs: ContextMenuProps[] = []; - if (!Doc.UserDoc().noviceMode && this.layoutDoc.onDragStart) { - funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); - funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); - funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined }); - cm.addItem({ description: "OnDrag...", noexpand: true, subitems: funcs, icon: "asterisk" }); - } + const funcs: ContextMenuProps[] = []; + if (!Doc.UserDoc().noviceMode && this.layoutDoc.onDragStart) { + funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); + funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); + funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined }); + cm.addItem({ description: "OnDrag...", noexpand: true, subitems: funcs, icon: "asterisk" }); + } - const more = cm.findByDescription("More..."); - const moreItems = more && "subitems" in more ? more.subitems : []; - if (!Doc.IsSystem(this.rootDoc)) { - (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" }); - if (!Doc.UserDoc().noviceMode) { - moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" }); - moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" }); - - if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) { - moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" }); - moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" }); - moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" }); + const more = cm.findByDescription("More..."); + const moreItems = more && "subitems" in more ? more.subitems : []; + if (!Doc.IsSystem(this.rootDoc)) { + (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" }); + if (!Doc.UserDoc().noviceMode) { + moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" }); + moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" }); + + if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) { + moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" }); + moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" }); + moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" }); + } + moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); } - moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); } - } - - if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && CurrentUserUtils.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) - moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" }); - } - !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); - cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!); + if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && CurrentUserUtils.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions) + moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" }); + } - const help = cm.findByDescription("Help..."); - const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : []; - !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" }); - helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" }); - !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" }); - cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); + !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); + cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!); + const help = cm.findByDescription("Help..."); + const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : []; + !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" }); + helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" }); + !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" }); + cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); + } if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15); !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. -- cgit v1.2.3-70-g09d2 From ffcb1cdf35e1f666034a1471cdd757c64b03ab52 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 8 Apr 2021 13:51:18 -0400 Subject: from last --- src/client/views/collections/TreeView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 43f9627e2..a4d734a70 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -545,7 +545,7 @@ export class TreeView extends React.Component { } } } - titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - treeBulletWidth())); + titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth())); /** * Renders the EditableView title element for placement into the tree. -- cgit v1.2.3-70-g09d2