diff options
Diffstat (limited to 'src/client/views/collections/CollectionView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionView.tsx | 207 |
1 files changed, 22 insertions, 185 deletions
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 6dd21ef7f..ba8e23447 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,6 +1,3 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faEye } from '@fortawesome/free-regular-svg-icons'; -import { faColumns, faCopy, faEllipsisV, faFingerprint, faGlobeAmericas, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable } from 'mobx'; import { observer } from "mobx-react"; @@ -18,7 +15,7 @@ import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx, GetEffectiveAcl, SharingPermissions, distributeAcls } from '../../../fields/util'; -import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils, returnEmptyDoclist } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; @@ -53,8 +50,6 @@ export const Flyout = higflyout.default; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); -library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faGlobeAmericas, faEllipsisV, faImage, faEye as any, faCopy); - export enum CollectionViewType { Invalid = "invalid", Freeform = "freeform", @@ -69,7 +64,7 @@ export enum CollectionViewType { Carousel = "carousel", Carousel3D = "3D Carousel", Linear = "linear", - Staff = "staff", + //Staff = "staff", Map = "map", Grid = "grid", Pile = "pileup" @@ -139,6 +134,9 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus } const docs = doc instanceof Doc ? [doc] : doc; + + + if (docs.find(doc => Doc.AreProtosEqual(doc, this.props.Document))) return false; const targetDataDoc = this.props.Document[DataSym]; const docList = DocListCast(targetDataDoc[this.props.fieldKey]); const added = docs.filter(d => !docList.includes(d)); @@ -159,7 +157,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus } if (effectiveAcl === AclAddonly) { - added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); + added.map(doc => { + Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc); + doc.context = this.props.Document; + }); } else { added.map(doc => { @@ -177,14 +178,11 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", ""); doc.displayTimecode = undefined; } + doc._stayInCollection = undefined; doc.context = this.props.Document; }); - added.map(add => Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); - // targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, ...added]); (targetDataDoc[this.props.fieldKey] as List<Doc>).push(...added); targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); - const lastModified = "lastModified"; - targetDataDoc[lastModified] = new DateField(new Date(Date.now())); } } } @@ -200,11 +198,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus const value = DocListCast(targetDataDoc[this.props.fieldKey]); const toRemove = value.filter(v => docs.includes(v)); if (toRemove.length !== 0) { - const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc; + const recent = Cast(Doc.UserDoc().myRecentlyClosedDocs, Doc) as Doc; toRemove.forEach(doc => { Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - doc.deleted = true; }); return true; } @@ -253,7 +250,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus case CollectionViewType.Schema: return (<CollectionSchemaView key="collview" {...props} />); case CollectionViewType.Docking: return (<CollectionDockingView key="collview" {...props} />); case CollectionViewType.Tree: return (<CollectionTreeView key="collview" {...props} />); - case CollectionViewType.Staff: return (<CollectionStaffView key="collview" {...props} />); + //case CollectionViewType.Staff: return (<CollectionStaffView key="collview" {...props} />); case CollectionViewType.Multicolumn: return (<CollectionMulticolumnView key="collview" {...props} />); case CollectionViewType.Multirow: return (<CollectionMultirowView key="rpwview" {...props} />); case CollectionViewType.Linear: { return (<CollectionLinearView key="collview" {...props} />); } @@ -274,7 +271,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus return this.SubViewHelper(type, renderProps); } - setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc, addExtras: boolean) { const subItems: ContextMenuProps[] = []; @@ -286,7 +282,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus subItems.push({ description: "Tree", event: () => func(CollectionViewType.Tree), icon: "tree" }); subItems.push({ description: "Stacking", event: () => func(CollectionViewType.Stacking), icon: "ellipsis-v" }); subItems.push({ description: "Stacking (AutoHeight)", event: () => func(CollectionViewType.Stacking)._autoHeight = true, icon: "ellipsis-v" }); - subItems.push({ description: "Staff", event: () => func(CollectionViewType.Staff), icon: "music" }); subItems.push({ description: "Multicolumn", event: () => func(CollectionViewType.Multicolumn), icon: "columns" }); subItems.push({ description: "Multirow", event: () => func(CollectionViewType.Multirow), icon: "columns" }); subItems.push({ description: "Masonry", event: () => func(CollectionViewType.Masonry), icon: "columns" }); @@ -309,7 +304,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus this.setupViewTypes("UI Controls...", vtype => { const newRendition = Doc.MakeAlias(this.props.Document); newRendition._viewType = vtype; - this.props.addDocTab(newRendition, "onRight"); + this.props.addDocTab(newRendition, "add:right"); return newRendition; }, false); @@ -317,10 +312,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus const optionItems = options && "subitems" in options ? options.subitems : []; !Doc.UserDoc().noviceMode ? optionItems.splice(0, 0, { description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }) : null; if (this.props.Document.childLayout instanceof Doc) { - optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); + optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "add:right"), icon: "project-diagram" }); } if (this.props.Document.childClickedOpenTemplateView instanceof Doc) { - optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "onRight"), icon: "project-diagram" }); + optionItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childClickedOpenTemplateView as Doc, "add:right"), icon: "project-diagram" }); } !Doc.UserDoc().noviceMode && optionItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" }); @@ -335,7 +330,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus description: `Edit ${func.name} script`, icon: "edit", event: (obj: any) => { const alias = Doc.MakeAlias(this.props.Document); DocUtils.makeCustomViewClicked(alias, undefined, func.key); - this.props.addDocTab(alias, "onRight"); + this.props.addDocTab(alias, "add:right"); } })); DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick => @@ -371,6 +366,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus onMovePrevRequest={action(() => this._curLightboxImg = (this._curLightboxImg + images.length - 1) % images.length)} onMoveNextRequest={action(() => this._curLightboxImg = (this._curLightboxImg + 1) % images.length)} />); } + get _facetWidth() { return NumCast(this.props.Document._facetWidth); } set _facetWidth(value) { this.props.Document._facetWidth = value; } @@ -394,9 +390,11 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, doc)).filter(pair => pair.layout); return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types } + get childDocList() { return Cast(this.dataField, listSpec(Doc)); } + get childDocs() { const dfield = this.dataField; const rawdocs = (dfield instanceof Doc) ? [dfield] : Cast(dfield, listSpec(Doc), Cast(this.props.Document.rootDocument, Doc, null) ? [Cast(this.props.Document.rootDocument, Doc, null)] : []); @@ -404,91 +402,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus const viewSpecScript = ScriptCast(this.props.Document.viewSpecScript); return viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; } - @computed get _allFacets() { - TraceMobx(); - const facets = new Set<string>(["type", "text", "data", "author", "ACL"]); - this.childDocs.filter(child => child).forEach(child => child && Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); - Doc.AreProtosEqual(this.dataDoc, this.props.Document) && this.childDocs.filter(child => child).forEach(child => Object.keys(child).forEach(key => facets.add(key))); - return Array.from(facets).filter(f => !f.startsWith("_") && !["proto", "zIndex", "isPrototype", "context", "text-noTemplate"].includes(f)).sort(); - } - - /** - * Responds to clicking the check box in the flyout menu - */ - facetClick = (facetHeader: string) => { - 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); - } - } - } else { - const allCollectionDocs = DocListCast(this.dataDoc[this.props.fieldKey]); - var rtfields = 0; - const facetValues = Array.from(allCollectionDocs.reduce((set, child) => { - const field = child[facetHeader] as Field; - const fieldStr = Field.toString(field); - if (field instanceof RichTextField || (typeof (field) === "string" && fieldStr.split(" ").length > 2)) rtfields++; - return set.add(fieldStr); - }, 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); - } - }); - let newFacet: Opt<Doc>; - if (facetHeader === "text" || rtfields / allCollectionDocs.length > 0.1) { - newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, 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.target = this.props.Document; - newFacet._textBoxPadding = 4; - const scriptText = `setDocFilter(this.target, "${facetHeader}", text, "match")`; - newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" }); - } else if (nonNumbers / facetValues.length < .1) { - newFacet = Docs.Create.SliderDocument({ title: facetHeader, treeViewExpandedView: "layout", treeViewOpen: true }); - const newFacetField = Doc.LayoutFieldKey(newFacet); - 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 - const extendedMinVal = minVal - Math.min(1, Math.abs(maxVal - minVal) * .05); - const extendedMaxVal = maxVal + Math.min(1, Math.abs(maxVal - minVal) * .05); - newFacet[newFacetField + "-min"] = ranged === undefined ? extendedMinVal : ranged[0]; - newFacet[newFacetField + "-max"] = ranged === undefined ? extendedMaxVal : ranged[1]; - Doc.GetProto(newFacet)[newFacetField + "-minThumb"] = extendedMinVal; - Doc.GetProto(newFacet)[newFacetField + "-maxThumb"] = extendedMaxVal; - 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 = new Doc(); - newFacet.title = facetHeader; - newFacet.treeViewOpen = true; - newFacet.type = DocumentType.COL; - const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.dataDoc }; - newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, {}, capturedVariables); - } - newFacet && Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet); - } - } onPointerDown = (e: React.PointerEvent) => { setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => { @@ -497,77 +410,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0), false); } - filterBackground = () => "rgba(105, 105, 105, 0.432)"; - get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } // this makes the tree view collection ignore these filters (otherwise, the filters would filter themselves) - @computed get scriptField() { - const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)"; - const script = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); - return script ? () => script : undefined; - } - @computed get filterView() { - TraceMobx(); - const facetCollection = this.props.Document; - 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[this.props.fieldKey + "-filter"]).some(d => d.title === facet)} /> - <span className="checkmark" /> - {facet} - </label>)} - </div> - ); - - 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}> - <div className="collectionTimeView-button"> - <FontAwesomeIcon icon={faEdit} size={"lg"} /> - <span className="collectionTimeView-span">Facet Filters</span> - </div> - </Flyout> - </div> - <div className="collectionTimeView-tree" key="tree"> - <CollectionTreeView - PanelPosition={""} - Document={facetCollection} - DataDoc={facetCollection} - fieldKey={`${this.props.fieldKey}-filter`} - CollectionView={this} - docFilters={returnEmptyFilter} - ContainingCollectionDoc={this.props.ContainingCollectionDoc} - ContainingCollectionView={this.props.ContainingCollectionView} - PanelWidth={this.facetWidth} - PanelHeight={this.props.PanelHeight} - NativeHeight={returnZero} - NativeWidth={returnZero} - LibraryPath={emptyPath} - rootSelected={this.props.rootSelected} - renderDepth={1} - dropAction={this.props.dropAction} - ScreenToLocalTransform={this.props.ScreenToLocalTransform} - addDocTab={returnFalse} - pinToPres={returnFalse} - isSelected={returnFalse} - select={returnFalse} - bringToFront={emptyFunction} - active={this.props.active} - whenActiveChanged={returnFalse} - treeViewHideTitle={true} - ContentScaling={returnOne} - focus={returnFalse} - treeViewHideHeaderFields={true} - onCheckedClick={this.scriptField} - ignoreFields={this.ignoreFields} - annotationsKey={""} - dontRegisterView={true} - backgroundColor={this.filterBackground} - moveDocument={returnFalse} - removeDocument={returnFalse} - addDocument={returnFalse} /> - </div> - </div>; - } - childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null); childLayoutString = this.props.childLayoutString || StrCast(this.props.Document.childLayoutString); @@ -584,10 +426,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus ChildLayoutTemplate: this.childLayoutTemplate, ChildLayoutString: this.childLayoutString, }; - const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document.isBackground || this.collectionViewType === CollectionViewType.Linear ? undefined : - `${Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`; + const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document._isBackground || this.collectionViewType === CollectionViewType.Linear ? undefined : + `${CurrentUserUtils.ActiveDashboard?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`; return (<div className={"collectionView"} onContextMenu={this.onContextMenu} - style={{ pointerEvents: this.props.Document.isBackground ? "none" : undefined, boxShadow }}> + style={{ pointerEvents: this.props.Document._isBackground ? "none" : undefined, boxShadow }}> {this.showIsTagged()} <div className="collectionView-facetCont" style={{ display: this.props.PanelPosition === "absolute" ? "flex" : "", justifyContent: this.props.PanelPosition === "absolute" ? "center" : "", width: `calc(100% - ${this.facetWidth()}px)` }}> {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)} @@ -598,11 +440,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus Utils.CorsProxy(Cast(d.data, ImageField)!.url.href) : Cast(d.data, ImageField)!.url.href : ""))} - {(Doc.UserDoc()?.noviceMode || !this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) : - <div className="collectionView-filterDragger" title="library View Dragger" onPointerDown={this.onPointerDown} - style={{ right: this.facetWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "60%" }} /> - } - {Doc.UserDoc()?.noviceMode || this.facetWidth() < 10 ? (null) : this.filterView} </div>); } } |
