aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/CollectionView.tsx
diff options
context:
space:
mode:
authorMelissa Zhang <mzhang19096@gmail.com>2020-09-30 22:01:44 -0600
committerMelissa Zhang <mzhang19096@gmail.com>2020-09-30 22:01:44 -0600
commit09aab9558a26a2d7c8e3d485aca578960af72821 (patch)
treeb53bdc6f2fcb269b74a097f56bfeec248e7f918b /src/client/views/collections/CollectionView.tsx
parentbd827b97c719abeadf243ba4f8b2ba417badb65b (diff)
parent852ddf70b7ed3d027eb5cb8415df4df77b8652a6 (diff)
pull from master
Diffstat (limited to 'src/client/views/collections/CollectionView.tsx')
-rw-r--r--src/client/views/collections/CollectionView.tsx373
1 files changed, 83 insertions, 290 deletions
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 2064b0be4..522f46280 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,24 +1,17 @@
-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";
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 '../../../fields/DateField';
-import { AclAddonly, AclReadonly, DataSym, Doc, DocListCast, Field, Opt, AclEdit, AclSym, AclPrivate, AclAdmin } from '../../../fields/Doc';
+import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, Field } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { ObjectField } from '../../../fields/ObjectField';
-import { RichTextField } from '../../../fields/RichTextField';
-import { listSpec } from '../../../fields/Schema';
-import { ComputedField, ScriptField } from '../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, 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 { distributeAcls, GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
+import { returnFalse, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
@@ -26,6 +19,7 @@ import { ImageUtils } from '../../util/Import & Export/ImageUtils';
import { InteractionUtils } from '../../util/InteractionUtils';
import { UndoManager } from '../../util/UndoManager';
import { ContextMenu } from "../ContextMenu";
+import { ContextMenuProps } from '../ContextMenuItem';
import { FieldView, FieldViewProps } from '../nodes/FieldView';
import { Touchable } from '../Touchable';
import { CollectionCarousel3DView } from './CollectionCarousel3DView';
@@ -40,21 +34,16 @@ import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultir
import { CollectionPileView } from './CollectionPileView';
import { CollectionSchemaView } from "./CollectionSchemaView";
import { CollectionStackingView } from './CollectionStackingView';
-import { CollectionStaffView } from './CollectionStaffView';
import { SubCollectionViewProps } from './CollectionSubView';
import { CollectionTimeView } from './CollectionTimeView';
import { CollectionTreeView } from "./CollectionTreeView";
import './CollectionView.scss';
-import { ContextMenuProps } from '../ContextMenuItem';
-import { table } from 'console';
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
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",
@@ -76,10 +65,9 @@ export enum CollectionViewType {
}
export interface CollectionViewCustomProps {
filterAddDocument?: (doc: Doc | Doc[]) => boolean; // allows a document that renders a Collection view to filter or modify any documents added to the collection (see PresBox for an example)
- childLayoutTemplate?: () => Opt<Doc>; // specify a layout Doc template to use for children of the collection
- childLayoutString?: string; // specify a layout string to use for children of the collection
childOpacity?: () => number;
hideFilter?: true;
+ childIgnoreNativeSize?: boolean;
}
export interface CollectionRenderProps {
@@ -90,8 +78,8 @@ export interface CollectionRenderProps {
whenActiveChanged: (isActive: boolean) => void;
PanelWidth: () => number;
PanelHeight: () => number;
- ChildLayoutTemplate?: () => Doc;
- ChildLayoutString?: string;
+ ChildLayoutTemplate?: () => Doc;// specify a layout Doc template to use for children of the collection
+ ChildLayoutString?: string;// specify a layout string to use for children of the collection
}
@observer
@@ -99,8 +87,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
public static LayoutString(fieldStr: string) { return FieldView.LayoutString(CollectionView, fieldStr); }
_isChildActive = false; //TODO should this be observable?
- get _isLightboxOpen() { return BoolCast(this.props.Document.isLightboxOpen); }
- set _isLightboxOpen(value) { this.props.Document.isLightboxOpen = value; }
+ get _isLightboxOpen() { return BoolCast(this.props.Document._isLightboxOpen); }
+ set _isLightboxOpen(value) { this.props.Document._isLightboxOpen = value; }
@observable private _curLightboxImg = 0;
@observable private static _safeMode = false;
public static SetSafeMode(safeMode: boolean) { this._safeMode = safeMode; }
@@ -156,13 +144,17 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
added.forEach(d => {
for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
if (d.author === key.substring(4).replace("_", ".") && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d, true);
- else distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
+ //else if (this.props.Document[key] === SharingPermissions.Admin) distributeAcls(key, SharingPermissions.Add, d, true);
+ //else distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
}
});
}
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 => {
@@ -183,12 +175,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
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()));
}
}
}
@@ -198,16 +186,21 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
@action.bound
removeDocument = (doc: any): boolean => {
const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
- if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) {
+ const docAcl = GetEffectiveAcl(doc);
+ if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin || docAcl === AclAdmin) {
const docs = doc instanceof Doc ? [doc] : doc as Doc[];
const targetDataDoc = this.props.Document[DataSym];
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);
+ const ind = (targetDataDoc[this.props.fieldKey] as List<Doc>).indexOf(doc);
+ (targetDataDoc[this.props.fieldKey] as List<Doc>).splice(ind, 0);
+ if (ind !== -1) {
+ Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc);
+ recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true);
+ }
});
return true;
}
@@ -250,7 +243,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
}
screenToLocalTransform = () => this.props.renderDepth ? this.props.ScreenToLocalTransform() : this.props.ScreenToLocalTransform().scale(this.props.PanelWidth() / this.bodyPanelWidth());
- private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
+ private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
+ TraceMobx();
const props: SubCollectionViewProps = { ...this.props, ...renderProps, ScreenToLocalTransform: this.screenToLocalTransform, CollectionView: this, annotationsKey: "" };
switch (type) {
case CollectionViewType.Schema: return (<CollectionSchemaView key="collview" {...props} />);
@@ -269,15 +263,10 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
case CollectionViewType.Map: return (<CollectionMapView key="collview" {...props} />);
case CollectionViewType.Grid: return (<CollectionGridView key="gridview" {...props} />);
case CollectionViewType.Freeform:
- default: { this.props.Document._freeformLayoutEngine = undefined; return (<CollectionFreeFormView key="collview" {...props} />); }
+ default: { this.props.Document._freeformLayoutEngine = undefined; return (<CollectionFreeFormView key="collview" {...props} ChildLayoutString={props.ChildLayoutString} />); }
}
}
- private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
- return this.SubViewHelper(type, renderProps);
- }
-
-
setupViewTypes(category: string, func: (viewType: CollectionViewType) => Doc, addExtras: boolean) {
const subItems: ContextMenuProps[] = [];
@@ -287,23 +276,24 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
}
subItems.push({ description: "Schema", event: () => func(CollectionViewType.Schema), icon: "th-list" });
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" });
+ !Doc.UserDoc().noviceMode && subItems.push({ description: "Stacking", event: () => func(CollectionViewType.Stacking), icon: "ellipsis-v" });
+ subItems.push({ description: "Stacking", event: () => func(CollectionViewType.Stacking)._autoHeight = true, icon: "ellipsis-v" });
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" });
subItems.push({ description: "Carousel", event: () => func(CollectionViewType.Carousel), icon: "columns" });
subItems.push({ description: "3D Carousel", event: () => func(CollectionViewType.Carousel3D), icon: "columns" });
- subItems.push({ description: "Pivot/Time", event: () => func(CollectionViewType.Time), icon: "columns" });
- subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" });
+ !Doc.UserDoc().noviceMode && subItems.push({ description: "Pivot/Time", event: () => func(CollectionViewType.Time), icon: "columns" });
+ !Doc.UserDoc().noviceMode && subItems.push({ description: "Map", event: () => func(CollectionViewType.Map), icon: "globe-americas" });
subItems.push({ description: "Grid", event: () => func(CollectionViewType.Grid), icon: "th-list" });
- addExtras && subItems.push({ description: "lightbox", event: action(() => this._isLightboxOpen = true), icon: "eye" });
+ subItems.push({ description: "lightbox", event: action(() => this._isLightboxOpen = true), icon: "eye" });
- const existingVm = ContextMenu.Instance.findByDescription(category);
- const catItems = existingVm && "subitems" in existingVm ? existingVm.subitems : [];
- catItems.push({ description: "Add a Perspective...", addDivider: true, noexpand: true, subitems: subItems, icon: "eye" });
- !existingVm && ContextMenu.Instance.addItem({ description: category, subitems: catItems, icon: "eye" });
+ if (!Doc.IsSystem(this.props.Document) && !this.props.Document.annotationOn) {
+ const existingVm = ContextMenu.Instance.findByDescription(category);
+ const catItems = existingVm && "subitems" in existingVm ? existingVm.subitems : [];
+ catItems.push({ description: "Add a Perspective...", addDivider: true, noexpand: true, subitems: subItems, icon: "eye" });
+ !existingVm && ContextMenu.Instance.addItem({ description: category, subitems: catItems, icon: "eye" });
+ }
}
onContextMenu = (e: React.MouseEvent): void => {
@@ -312,7 +302,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);
@@ -320,34 +310,34 @@ 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" });
!options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "hand-point-right" });
- const existingOnClick = cm.findByDescription("OnClick...");
- const onClicks = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
- const funcs = [
- { key: "onChildClick", name: "On Child Clicked" },
- { key: "onChildDoubleClick", name: "On Child Double Clicked" }];
- funcs.map(func => onClicks.push({
- 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");
- }
- }));
- DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick =>
- onClicks.push({
- description: `Set child ${childClick.title}`,
- icon: "edit",
- event: () => Doc.GetProto(this.props.Document)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)),
+ if (!Doc.UserDoc().noviceMode && !this.props.Document.annotationOn) {
+ const existingOnClick = cm.findByDescription("OnClick...");
+ const onClicks = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
+ const funcs = [{ key: "onChildClick", name: "On Child Clicked" }, { key: "onChildDoubleClick", name: "On Child Double Clicked" }];
+ funcs.map(func => onClicks.push({
+ 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, "add:right");
+ }
}));
- !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
+ DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick =>
+ onClicks.push({
+ description: `Set child ${childClick.title}`,
+ icon: "edit",
+ event: () => Doc.GetProto(this.props.Document)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)),
+ }));
+ !Doc.IsSystem(this.props.Document) && !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
+ }
if (!Doc.UserDoc().noviceMode) {
const more = cm.findByDescription("More...");
@@ -358,222 +348,31 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
}
}
- lightbox = (images: string[]) => {
+ lightbox = (images: { image: string, title: string, caption: string }[]) => {
if (!images.length) return (null);
- const mainPath = path.extname(images[this._curLightboxImg]);
- const nextPath = path.extname(images[(this._curLightboxImg + 1) % images.length]);
- const prevPath = path.extname(images[(this._curLightboxImg + images.length - 1) % images.length]);
- const main = images[this._curLightboxImg].replace(mainPath, "_o" + mainPath);
- const next = images[(this._curLightboxImg + 1) % images.length].replace(nextPath, "_o" + nextPath);
- const prev = images[(this._curLightboxImg + images.length - 1) % images.length].replace(prevPath, "_o" + prevPath);
+ const mainPath = path.extname(images[this._curLightboxImg].image);
+ const nextPath = path.extname(images[(this._curLightboxImg + 1) % images.length].image);
+ const prevPath = path.extname(images[(this._curLightboxImg + images.length - 1) % images.length].image);
+ const main = images[this._curLightboxImg].image.replace(mainPath, "_o" + mainPath);
+ const title = images[this._curLightboxImg].title;
+ const caption = images[this._curLightboxImg].caption;
+ const next = images[(this._curLightboxImg + 1) % images.length].image.replace(nextPath, "_o" + nextPath);
+ const prev = images[(this._curLightboxImg + images.length - 1) % images.length].image.replace(prevPath, "_o" + prevPath);
return !this._isLightboxOpen ? (null) : (<Lightbox key="lightbox"
mainSrc={main}
nextSrc={next}
prevSrc={prev}
+ imageTitle={title}
+ imageCaption={caption}
onCloseRequest={action(() => this._isLightboxOpen = false)}
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; }
bodyPanelWidth = () => this.props.PanelWidth();
- facetWidth = () => Math.max(0, Math.min(this.props.PanelWidth() - 25, this._facetWidth));
-
- @computed get dataDoc() {
- return (this.props.DataDoc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) :
- this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document)); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
- }
- // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc.
- // When a document has a DataDoc but it's not a template, then it contains its own rendering data, but needs to pass the DataDoc through
- // to its children which may be templates.
- // If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey'
- @computed get dataField() {
- return this.dataDoc[this.props.fieldKey];
- }
-
- get childLayoutPairs(): { layout: Doc; data: Doc; }[] {
- const { Document, DataDoc } = this.props;
- 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)] : []);
- const docs = rawdocs.filter(d => d && !(d instanceof Promise)).map(d => d as Doc);
- 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.sytem = true;
- 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[]) => {
- this._facetWidth = this.props.PanelWidth() - Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0);
- return false;
- }), 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);
+ @computed get childLayoutString() { return StrCast(this.props.Document.childLayoutString); }
render() {
TraceMobx();
@@ -588,25 +387,19 @@ 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.treeViewOutlineMode || 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)}
- </div>
- {this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => d.type === DocumentType.IMG).map(d =>
- Cast(d.data, ImageField) ?
- (Cast(d.data, ImageField)!.url.href.indexOf(window.location.origin) === -1) ?
- 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}
+ {this.collectionViewType !== undefined ? this.SubView(this.collectionViewType, props) : (null)}
+ {this.lightbox(DocListCast(this.props.Document[this.props.fieldKey]).filter(d => Cast(d.data, ImageField, null)).map(d =>
+ ({
+ image: (Cast(d.data, ImageField)!.url.href.indexOf(window.location.origin) === -1) ?
+ Utils.CorsProxy(Cast(d.data, ImageField)!.url.href) : Cast(d.data, ImageField)!.url.href,
+ title: StrCast(d.title),
+ caption: Field.toString(d.caption as Field)
+ })))}
</div>);
}
}