diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/StyleProvider.tsx | 10 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 46 | ||||
-rw-r--r-- | src/client/views/nodes/FilterBox.tsx | 2 |
3 files changed, 37 insertions, 21 deletions
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index a530ff90a..ca9826ab9 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -24,6 +24,7 @@ import { SliderBox } from './nodes/SliderBox'; import "./StyleProvider.scss"; import React = require("react"); import { InkingStroke } from './InkingStroke'; +import { TreeSort } from './collections/TreeView'; export enum StyleLayers { Background = "background" @@ -31,6 +32,7 @@ export enum StyleLayers { export enum StyleProp { TreeViewIcon = "treeViewIcon", + TreeViewSortings = "treeViewSortings",// options for how to sort tree view items 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 @@ -98,6 +100,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps return <img src={url} width={20} height={15} style={{ margin: "auto", display: "block", objectFit: "contain" }} />; } return Doc.toIcon(doc, isOpen); + + case StyleProp.TreeViewSortings: + const allSorts: { [key: string]: { color: string, label: string } | undefined } = {}; + allSorts[TreeSort.Down] = { color: "blue", label: "↓" }; + allSorts[TreeSort.Up] = { color: "crimson", label: "↑" }; + if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: "green", label: "z" }; + allSorts[TreeSort.None] = { color: "darkgray", label: '\u00A0\u00A0\u00A0' }; + return allSorts; case StyleProp.DocContents: return undefined; case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : 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 647476784..72480b094 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -67,7 +67,12 @@ export interface TreeViewProps { const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("px", "")); }; -@observer +export enum TreeSort { + Up = "up", + Down = "down", + Zindex = "z", + None = "none" +}; /** * Renders a treeView of a collection of documents * @@ -75,11 +80,11 @@ const treeBulletWidth = function () { return Number(TREE_BULLET_WIDTH.replace("p * treeViewOpen : flag denoting whether the documents sub-tree (contents) is visible or hidden * treeViewExpandedView : name of field whose contents are being displayed as the document's subtree */ +@observer export class TreeView extends React.Component<TreeViewProps> { static _editTitleOnLoad: Opt<{ id: string, parent: TreeView | CollectionTreeView | undefined }>; static _openTitleScript: Opt<ScriptField | undefined>; static _openLevelScript: Opt<ScriptField | undefined>; - static _sortUIMap = [["up", "crimson", "↑"], ["down", "blue", "↓"], ["z", "green", "z"], ["x", "darkgray", '\u00A0\u00A0\u00A0']]; private _header: React.RefObject<HTMLDivElement> = React.createRef(); private _tref = React.createRef<HTMLDivElement>(); @observable _docRef: Opt<DocumentView>; @@ -410,17 +415,18 @@ export class TreeView extends React.Component<TreeViewProps> { @computed get renderContent() { TraceMobx(); const expandKey = this.treeViewExpandedView; + const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } }; if (["links", "annotations", "aliases", this.fieldKey].includes(expandKey)) { - const sorting = StrCast(this.doc.treeViewSortCriterion); - const color = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[1]; - const label = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[2]; + const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None); + const sortKeys = Object.keys(sortings); + const curSortIndex = Math.max(0, sortKeys.findIndex(val => val === sorting)); const key = (expandKey === "annotations" ? `${this.fieldKey}-` : "") + expandKey; const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key); const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => { // if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't), // then the modification would be done here const ordering = StrCast(this.doc.treeViewSortCriterion); - if (ordering === "z") { + if (ordering === TreeSort.Zindex) { const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering); doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000; docs.push(doc); @@ -433,17 +439,15 @@ export class TreeView extends React.Component<TreeViewProps> { const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true); const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs; let downX = 0, downY = 0; - const sortings = this.props.treeView.rootDoc === Doc.UserDoc().myFilesystem ? ["up", "down", "x"] : ["up", "down", "z", "x"]; - const curSort = Math.max(0, sortings.indexOf(Cast(this.doc.treeViewSortCriterion, "string", null))); return <> - {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: color }} > - {label} + {!docs?.length ? (null) : <div className={'treeView-sorting'} style={{ background: sortings[sorting]?.color }} > + {sortings[sorting]?.label} </div>} <ul key={expandKey + "more"} title="click to change sort order" className={this.doc.treeViewHideTitle ? "no-indent" : ""} onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }} onClick={(e) => { if (this.props.isContentActive() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) { - !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortings[(curSort + 1) % sortings.length]); + !this.props.treeView.outlineMode && (this.doc.treeViewSortCriterion = sortKeys[(curSortIndex + 1) % sortKeys.length]); e.stopPropagation(); } }}> @@ -791,9 +795,9 @@ export class TreeView extends React.Component<TreeViewProps> { } @computed get renderBorder() { - const sorting = StrCast(this.doc.treeViewSortCriterion); - const color = (TreeView._sortUIMap.find((sortUIfields) => sortUIfields[0] === sorting) ?? TreeView._sortUIMap.lastElement())[1]; - return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`} style={{ borderColor: color }}> + const sorting = StrCast(this.doc.treeViewSortCriterion, TreeSort.None); + const sortings = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewSortings) as { [key: string]: { color: string, label: string } }; + return <div className={`treeView-border${this.props.treeView.outlineMode ? "outline" : ""}`} style={{ borderColor: sortings[sorting]?.color }}> {!this.treeViewOpen ? (null) : this.renderContent} </div>; } @@ -827,11 +831,11 @@ export class TreeView extends React.Component<TreeViewProps> { public static sortDocs(childDocs: Doc[], criterion: string | undefined) { const docs = childDocs.slice(); - if (criterion) { + if (criterion !== TreeSort.None) { const sortAlphaNum = (a: string, b: string): 0 | 1 | -1 => { const reN = /[0-9]*$/; - const aA = a.replace(reN, ""); // get rid of trailing numbers - const bA = b.replace(reN, ""); + const aA = a.replace(reN, "") ? a.replace(reN, "") : +a; // get rid of trailing numbers + const bA = b.replace(reN, "") ? b.replace(reN, "") : +b; if (aA === bA) { // if header string matches, then compare numbers numerically const aN = parseInt(a.match(reN)![0], 10); const bN = parseInt(b.match(reN)![0], 10); @@ -841,10 +845,10 @@ export class TreeView extends React.Component<TreeViewProps> { } }; docs.sort(function (d1, d2): 0 | 1 | -1 { - const a = (criterion === "up" ? d2 : d1); - const b = (criterion === "down" ? d1 : d2); - const first = a[criterion === "z" ? "zIndex" : "title"]; - const second = b[criterion === "z" ? "zIndex" : "title"]; + const a = (criterion === TreeSort.Up ? d2 : d1); + const b = (criterion === TreeSort.Up ? d1 : d2); + const first = a[criterion === TreeSort.Zindex ? "zIndex" : "title"]; + const second = b[criterion === TreeSort.Zindex ? "zIndex" : "title"]; if (typeof first === 'number' && typeof second === 'number') return (first - second) > 0 ? 1 : -1; if (typeof first === 'string' && typeof second === 'string') return sortAlphaNum(first, second); return criterion ? 1 : -1; diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index ba65acee0..dc0ab5ec2 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -386,6 +386,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() { options={options} isMulti={false} onChange={val => this.facetClick((val as UserOptions).value)} + onKeyDown={e => e.stopPropagation()} value={null} closeMenuOnSelect={true} /> @@ -420,6 +421,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() { whenChildContentsActiveChanged={returnFalse} treeViewHideTitle={true} focus={returnFalse} + onCheckedClick={this.scriptField} treeViewHideHeaderFields={false} dontRegisterView={true} styleProvider={this.FilterStyleProvider} |