diff options
-rw-r--r-- | src/Utils.ts | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTimeView.scss | 1 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 24 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 143 | ||||
-rw-r--r-- | src/client/views/nodes/FieldView.tsx | 3 |
6 files changed, 99 insertions, 82 deletions
diff --git a/src/Utils.ts b/src/Utils.ts index 3786b4f6f..e3ec10dcd 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -498,7 +498,7 @@ export function setupMoveUpEvents( }; const _upEvent = (e: PointerEvent): void => { upEvent(e); - if (Math.abs(e.clientX - (target as any)._downX) < 4 || Math.abs(e.clientY - (target as any)._downY) < 4) { + if (Math.abs(e.clientX - (target as any)._downX) < 4 && Math.abs(e.clientY - (target as any)._downY) < 4) { clickEvent(e); } document.removeEventListener("pointermove", _moveEvent); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a5480d567..11f214625 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -48,8 +48,8 @@ export interface SubCollectionViewProps extends CollectionViewProps { layoutEngine?: () => string; } -export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { - class CollectionSubView extends DocComponent<SubCollectionViewProps, T>(schemaCtor) { +export function CollectionSubView<T,X>(schemaCtor: (doc: Doc) => T, moreProps?:X) { + class CollectionSubView extends DocComponent<X&SubCollectionViewProps, T>(schemaCtor) { private dropDisposer?: DragManager.DragDropDisposer; private gestureDisposer?: GestureUtils.GestureEventDisposer; protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer; @@ -130,7 +130,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField); const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; - const filteredDocs = docFilters.length ? childDocs.filter(d => { + const filteredDocs = docFilters.length && !this.props.dontRegisterView ? childDocs.filter(d => { for (const facetKey of Object.keys(filterFacets)) { const facet = filterFacets[facetKey]; const satisfiesFacet = Object.keys(facet).some(value => @@ -195,7 +195,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { @undoBatch @action protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean { - const docDragData = de.complete.docDragData; + const docDragData = de.complete.docDragData; (this.props.Document.dropConverter instanceof ScriptField) && this.props.Document.dropConverter.script.run({ dragData: docDragData }); /// bcz: check this if (docDragData) { diff --git a/src/client/views/collections/CollectionTimeView.scss b/src/client/views/collections/CollectionTimeView.scss index be745000e..fa7c87f4e 100644 --- a/src/client/views/collections/CollectionTimeView.scss +++ b/src/client/views/collections/CollectionTimeView.scss @@ -48,6 +48,7 @@ .collectionTimeView-flyout { width: 400px; display: block; + text-align: left; .collectionTimeView-flyout-item { background-color: lightgray; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f8f8a0943..c02c4ac3f 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -6,7 +6,7 @@ import { observer } from "mobx-react"; import { Doc, DocListCast, Field, HeightSym, WidthSym, DataSym, Opt } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; -import { Document, listSpec } from '../../../new_fields/Schema'; +import { Document, listSpec, createSchema, makeInterface } from '../../../new_fields/Schema'; import { ComputedField, ScriptField } from '../../../new_fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../new_fields/Types'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; @@ -29,7 +29,7 @@ import { ImageBox } from '../nodes/ImageBox'; import { KeyValueBox } from '../nodes/KeyValueBox'; import { ScriptBox } from '../ScriptBox'; import { Templates } from '../Templates'; -import { CollectionSubView } from "./CollectionSubView"; +import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); import { CollectionViewType } from './CollectionView'; @@ -46,7 +46,7 @@ export interface TreeViewProps { renderDepth: number; deleteDoc: (doc: Doc) => boolean; moveDocument: DragManager.MoveFunction; - dropAction: "alias" | "copy" | undefined; + dropAction: dropActionType; addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; panelWidth: () => number; @@ -632,8 +632,16 @@ class TreeView extends React.Component<TreeViewProps> { } } +export type collectionTreeViewProps = { + treeViewHideTitle?: boolean; + treeViewHideHeaderFields?: boolean; + onCheckedClick?: ScriptField; +}; + +let xx: collectionTreeViewProps = {}; + @observer -export class CollectionTreeView extends CollectionSubView(Document) { +export class CollectionTreeView extends CollectionSubView(Document, xx) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; @@ -665,7 +673,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { const doAddDoc = () => Doc.AddDocToList(this.props.Document[DataSym], this.props.fieldKey, doc, relativeTo, before, false, false, false); if (this.props.Document.resolvedDataDoc instanceof Promise) { - this.props.Document.resolvedDataDoc.then(resolved => doAddDoc()); + this.props.Document.resolvedDataDoc.then((resolved: any) => doAddDoc()); } else { doAddDoc(); } @@ -773,7 +781,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { onWheel={(e: React.WheelEvent) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} ref={this.createTreeDropTarget}> - {(this.props.Document.treeViewHideTitle ? (null) : <EditableView + {(this.props.treeViewHideTitle || this.props.Document.treeViewHideTitle ? (null) : <EditableView contents={this.dataDoc.title} editing={false} display={"block"} @@ -792,8 +800,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { { TreeView.GetChildElements(childDocs, this.props.Document, this.props.Document, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.backgroundColor, this.props.ScreenToLocalTransform, - this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => BoolCast(this.props.Document.treeViewHideHeaderFields), - BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, ScriptCast(this.props.Document.onCheckedClick), this.props.ignoreFields) + this.outerXf, this.props.active, this.props.PanelWidth, this.props.ChromeHeight, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.props.Document.treeViewHideHeaderFields), + BoolCast(this.props.Document.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick || ScriptCast(this.props.Document.onCheckedClick), this.props.ignoreFields) } </ul> </div > diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a1f173746..ab553b206 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -8,7 +8,7 @@ import * as React from 'react'; import Lightbox from 'react-image-lightbox-with-rotate'; import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app import { DateField } from '../../../new_fields/DateField'; -import { DataSym, Doc, DocListCast, Field } from '../../../new_fields/Doc'; +import { DataSym, Doc, DocListCast, Field, Opt } from '../../../new_fields/Doc'; import { List } from '../../../new_fields/List'; import { BoolCast, Cast, NumCast, StrCast } from '../../../new_fields/Types'; import { ImageField } from '../../../new_fields/URLField'; @@ -320,64 +320,63 @@ export class CollectionView extends Touchable<FieldViewProps> { * Responds to clicking the check box in the flyout menu */ facetClick = (facetHeader: string) => { - const facetCollection = this.props.Document._facetCollection; - if (facetCollection instanceof Doc) { - const found = DocListCast(facetCollection.data).findIndex(doc => doc.title === facetHeader); - if (found !== -1) { - (facetCollection.data as List<Doc>).splice(found, 1); - const docFilter = Cast(this.props.Document._docFilters, listSpec("string")); - if (docFilter) { - let index: number; - while ((index = docFilter.findIndex(item => item === facetHeader)) !== -1) { - docFilter.splice(index, 3); - } + const facetCollection = this.props.Document; + const found = DocListCast(facetCollection[this.props.fieldKey + "-filter"]).findIndex(doc => doc.title === facetHeader); + if (found !== -1) { + (facetCollection[this.props.fieldKey + "-filter"] as List<Doc>).splice(found, 1); + const docFilter = Cast(this.props.Document._docFilters, listSpec("string")); + if (docFilter) { + let index: number; + while ((index = docFilter.findIndex(item => item === facetHeader)) !== -1) { + docFilter.splice(index, 3); } - const docRangeFilters = Cast(this.props.Document._docRangeFilters, listSpec("string")); - if (docRangeFilters) { - let index: number; - while ((index = docRangeFilters.findIndex(item => item === facetHeader)) !== -1) { - docRangeFilters.splice(index, 3); - } + } + const docRangeFilters = Cast(this.props.Document._docRangeFilters, listSpec("string")); + if (docRangeFilters) { + let index: number; + while ((index = docRangeFilters.findIndex(item => item === facetHeader)) !== -1) { + docRangeFilters.splice(index, 3); } - } else { - const allCollectionDocs = DocListCast(this.dataDoc[this.props.fieldKey]); - const facetValues = Array.from(allCollectionDocs.reduce((set, child) => - set.add(Field.toString(child[facetHeader] as Field)), new Set<string>())); - - let nonNumbers = 0; - let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE; - facetValues.map(val => { - const num = Number(val); - if (Number.isNaN(num)) { - nonNumbers++; - } else { - minVal = Math.min(num, minVal); - maxVal = Math.max(num, maxVal); - } - }); - if (nonNumbers / allCollectionDocs.length < .1) { - const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader); - const newFacet = Docs.Create.SliderDocument({ title: facetHeader }); - Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox - newFacet.treeViewExpandedView = "layout"; - newFacet.treeViewOpen = true; - newFacet._sliderMin = ranged === undefined ? minVal : ranged[0]; - newFacet._sliderMax = ranged === undefined ? maxVal : ranged[1]; - newFacet._sliderMinThumb = minVal; - newFacet._sliderMaxThumb = maxVal; - newFacet.target = this.props.Document; - const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`; - newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" }); - - Doc.AddDocToList(facetCollection, "data", newFacet); + } + } else { + const allCollectionDocs = DocListCast(this.dataDoc[this.props.fieldKey]); + const facetValues = Array.from(allCollectionDocs.reduce((set, child) => + set.add(Field.toString(child[facetHeader] as Field)), new Set<string>())); + + let nonNumbers = 0; + let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE; + facetValues.map(val => { + const num = Number(val); + if (Number.isNaN(num)) { + nonNumbers++; } else { - const newFacet = Docs.Create.TreeDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true }); - const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.dataDoc }; - const params = { layoutDoc: Doc.name, dataDoc: Doc.name, }; - newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, params, capturedVariables); - Doc.AddDocToList(facetCollection, "data", newFacet); + minVal = Math.min(num, minVal); + maxVal = Math.max(num, maxVal); } + }); + let newFacet: Opt<Doc>; + if (nonNumbers / allCollectionDocs.length < .1) { + newFacet = Docs.Create.SliderDocument({ title: facetHeader }); + const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader); + Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox + newFacet.treeViewExpandedView = "layout"; + newFacet.treeViewOpen = true; + newFacet._sliderMin = ranged === undefined ? minVal : ranged[0]; + newFacet._sliderMax = ranged === undefined ? maxVal : ranged[1]; + newFacet._sliderMinThumb = minVal; + newFacet._sliderMaxThumb = maxVal; + newFacet.target = this.props.Document; + const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`; + newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" }); + + Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet); + } else { + newFacet = Docs.Create.TreeDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true }); + const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.dataDoc }; + const params = { layoutDoc: Doc.name, dataDoc: Doc.name, }; + newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, params, capturedVariables); } + Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet); } } @@ -388,27 +387,24 @@ export class CollectionView extends Touchable<FieldViewProps> { return false; }), returnFalse, action(() => this._facetWidth = this._facetWidth < 15 ? 200 : 0)); } + filterBackground = () => "dimGray"; + @computed get scriptField() { + const scriptText = "setDocFilter(containingTreeView.target, heading, this.title, checked)"; + return ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); + } @computed get filterView() { - const facetCollection = Cast(this.props.Document?._facetCollection, Doc); - if (this._facetWidth && facetCollection === undefined) setTimeout(() => { - const scriptText = "setDocFilter(containingTreeView.target, heading, this.title, checked)"; - const facetCollection = Docs.Create.TreeDocument([], { title: "facetFilters", _yMargin: 0, treeViewHideTitle: true, treeViewHideHeaderFields: true }); - facetCollection.target = this.props.Document; - facetCollection.onCheckedClick = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); - this.props.Document.excludeFields = new List<string>(["_facetCollection", "_docFilters"]); - - this.props.Document._facetCollection = facetCollection; - }, 0); + const facetCollection = this.props.Document; + this._facetWidth && setTimeout(() => facetCollection.target = this.props.Document, 0); const flyout = ( <div className="collectionTimeView-flyout" style={{ width: `${this._facetWidth}`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}> {this._allFacets.map(facet => <label className="collectionTimeView-flyout-item" key={`${facet}`} onClick={e => this.facetClick(facet)}> - <input type="checkbox" onChange={e => { }} checked={DocListCast((this.props.Document._facetCollection as Doc)?.data).some(d => d.title === facet)} /> + <input type="checkbox" onChange={e => { }} checked={DocListCast(this.props.Document[this.props.fieldKey + "-filter"]).some(d => d.title === facet)} /> <span className="checkmark" /> {facet} </label>)} </div> ); - return !facetCollection ? (null) : + return !this._facetWidth || this.props.dontRegisterView ? (null) : <div className="collectionTimeView-treeView" style={{ width: `${this._facetWidth}px`, overflow: this._facetWidth < 15 ? "hidden" : undefined }}> <div className="collectionTimeView-addFacet" style={{ width: `${this._facetWidth}px` }} onPointerDown={e => e.stopPropagation()}> <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}> @@ -419,8 +415,19 @@ export class CollectionView extends Touchable<FieldViewProps> { </Flyout> </div> <div className="collectionTimeView-tree" key="tree"> - <CollectionTreeView {...this.props} CollectionView={this} annotationsKey={""} PanelWidth={this.facetWidth} - DataDoc={undefined} Document={facetCollection} + <CollectionTreeView {...this.props} + CollectionView={this} + treeViewHideTitle={true} + treeViewHideHeaderFields={true} + onCheckedClick={this.scriptField!} + ignoreFields={["_facetCollection", "_docFilters"]} + annotationsKey={""} + dontRegisterView={true} + PanelWidth={this.facetWidth} + DataDoc={facetCollection} + Document={facetCollection} + backgroundColor={this.filterBackground} + fieldKey={`${this.props.fieldKey}-filter`} moveDocument={(doc: Doc) => false} removeDocument={(doc: Doc) => false} addDocument={(doc: Doc) => false} /> diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 6619330a1..0305f43d5 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -10,6 +10,7 @@ import { Transform } from "../../util/Transform"; import { CollectionView } from "../collections/CollectionView"; import { AudioBox } from "./AudioBox"; import { VideoBox } from "./VideoBox"; +import { dropActionType } from "../../util/DragManager"; // // these properties get assigned through the render() method of the DocumentView when it creates this node. @@ -25,7 +26,7 @@ export interface FieldViewProps { DataDoc?: Doc; LibraryPath: Doc[]; onClick?: ScriptField; - dropAction: dropAction; + dropAction: dropActionType; isSelected: (outsideReaction?: boolean) => boolean; select: (isCtrlPressed: boolean) => void; renderDepth: number; |