From cc2cbf44ba5c30a70bad2ffd7a57d2c6d17d0e4e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Mon, 20 Jan 2020 16:09:43 -0500 Subject: finalLayoutKey changes and sorted facet values --- src/client/views/collections/CollectionPivotView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 53ad433b3..ad2e05908 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -76,7 +76,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { facetValues.add(child[facet]?.toString() || "(null)"); }); - const newFacetVals = facetValues.toArray().map(val => Docs.Create.TextDocument({ title: val.toString() })); + const newFacetVals = facetValues.toArray().sort().map(val => Docs.Create.TextDocument({ title: val.toString() })); const newFacet = Docs.Create.FreeformDocument(newFacetVals, { title: facet, treeViewOpen: true, isFacetFilter: true }); Doc.AddDocToList(facetCollection, "data", newFacet); } -- cgit v1.2.3-70-g09d2 From 69e068d77731c25d9f1dbafb8c7d279e343a4e55 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 21 Jan 2020 00:11:41 -0500 Subject: fixed up creating template fields in stacking views (+ after the template is made) --- .../views/collections/CollectionPivotView.tsx | 37 +++++++++++++++------- .../CollectionStackingViewFieldColumn.tsx | 6 ++++ src/client/views/collections/CollectionView.tsx | 6 ++++ .../views/collections/CollectionViewChromes.tsx | 10 ++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 -- src/client/views/nodes/DocumentView.tsx | 3 +- src/new_fields/Doc.ts | 5 +++ src/new_fields/documentSchemas.ts | 7 ++++ src/new_fields/util.ts | 4 +-- 9 files changed, 61 insertions(+), 20 deletions(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index ad2e05908..07ad5683c 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -2,7 +2,7 @@ import { CollectionSubView } from "./CollectionSubView"; import React = require("react"); import { computed, action, IReactionDisposer, reaction, runInAction, observable } from "mobx"; import { faEdit, faChevronCircleUp } from "@fortawesome/free-solid-svg-icons"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Doc, DocListCast, Field, DocCastAsync } from "../../../new_fields/Doc"; import "./CollectionPivotView.scss"; import { observer } from "mobx-react"; import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; @@ -15,10 +15,15 @@ import { anchorPoints, Flyout } from "../TemplateMenu"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { List } from "../../../new_fields/List"; import { Set } from "typescript-collections"; +import { PrefetchProxy } from "../../../new_fields/Proxy"; @observer export class CollectionPivotView extends CollectionSubView(doc => doc) { - componentDidMount = () => { + private _narrativeDisposer: IReactionDisposer | undefined; + componentWillUnmount() { + this._narrativeDisposer?.(); + } + componentDidMount() { this.props.Document.freeformLayoutEngine = "pivot"; if (true || !this.props.Document.facetCollection) { const facetCollection = Docs.Create.FreeformDocument([], { title: "facetFilters", yMargin: 0, treeViewHideTitle: true }); @@ -34,16 +39,24 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { facetCollection.onCheckedClick = new ScriptField(script); } - const openDocText = "const alias = getAlias(this); alias.layoutKey = 'layout_detailed'; useRightSplit(alias); "; - const openDocScript = CompileScript(openDocText, { - params: { this: Doc.name, heading: "boolean", checked: "boolean", context: Doc.name }, - typecheck: false, - editable: true, - }); - if (openDocScript.compiled) { - this.props.Document.onChildClick = new ScriptField(openDocScript); - } - + this._narrativeDisposer = reaction(() => this.props.Document.childDetailed, + (childDetailed) => + DocCastAsync(childDetailed).then(childDetailed => { + if (childDetailed instanceof Doc) { + let captured: { [name: string]: Field } = {}; + captured["childDetailed"] = new PrefetchProxy(childDetailed); + const openDocText = "const alias = getAlias(this); Doc.ApplyTemplateTo(childDetailed, alias, 'layout_detailed'); useRightSplit(alias); "; + const openDocScript = CompileScript(openDocText, { + params: { this: Doc.name, heading: "boolean", context: Doc.name }, + typecheck: false, + editable: true, + capturedVariables: captured + }); + if (openDocScript.compiled) { + this.props.Document.onChildClick = new ScriptField(openDocScript); + } + } + }), { fireImmediately: true }); this.props.Document.facetCollection = facetCollection; this.props.Document.fitToBox = true; } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 23a664359..229a23294 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -142,6 +142,12 @@ export class CollectionStackingViewFieldColumn extends React.Component { const existing = ContextMenu.Instance.findByDescription("Layout..."); const layoutItems = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }); + if (this.props.Document.childLayout instanceof Doc) { + layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, undefined, "onRight"), icon: "project-diagram" }); + } + if (this.props.Document.childDetailed instanceof Doc) { + layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, undefined, "onRight"), icon: "project-diagram" }); + } !existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" }); const more = ContextMenu.Instance.findByDescription("More..."); diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 996c7671e..075c48134 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -39,10 +39,15 @@ export class CollectionViewBaseChrome extends React.Component Doc.setChildLayout(this.props.CollectionView.props.Document, draggedDocs.length ? draggedDocs[0] : undefined) }; + _narrativeCommand = { + title: "set detailed template", script: "setChildLayout(this.target, this.source?.[0])", params: ["target", "source"], + initialize: emptyFunction, + immediate: (draggedDocs: Doc[]) => Doc.setChildDetailed(this.props.CollectionView.props.Document, draggedDocs.length ? draggedDocs[0] : undefined) + }; _contentCommand = { // title: "set content", script: "getProto(this.target).data = aliasDocs(this.source.map(async p => await p));", params: ["target", "source"], // bcz: doesn't look like we can do async stuff in scripting... title: "set content", script: "getProto(this.target).data = aliasDocs(this.source);", params: ["target", "source"], @@ -54,7 +59,7 @@ export class CollectionViewBaseChrome extends React.Component { this.props.CollectionView.props.Document.panX = 0; this.props.CollectionView.props.Document.panY = 0; this.props.CollectionView.props.Document.scale = 1; }, initialize: (button: Doc) => { button.restoredPanX = this.props.CollectionView.props.Document.panX; button.restoredPanY = this.props.CollectionView.props.Document.panY; button.restoredScale = this.props.CollectionView.props.Document.scale; } }; - _freeform_commands = [this._contentCommand, this._templateCommand, this._viewCommand]; + _freeform_commands = [this._contentCommand, this._templateCommand, this._narrativeCommand, this._viewCommand]; _stacking_commands = [this._contentCommand, this._templateCommand]; _masonry_commands = [this._contentCommand, this._templateCommand]; _tree_commands = []; @@ -64,6 +69,7 @@ export class CollectionViewBaseChrome extends React.Component { const layoutItems: ContextMenuProps[] = []; - if (this.childDocs.some(d => BoolCast(d.isTemplateDoc))) { - layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); - } layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" }); layoutItems.push({ description: `${this.Document.LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document.LODdisable = !this.Document.LODdisable, icon: "table" }); layoutItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document.fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 63bb6b18c..e91013be4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -659,7 +659,8 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action - setCustomView = (custom: boolean): void => { + setCustomView = + (custom: boolean): void => { if (this.props.ContainingCollectionView?.props.DataDoc || this.props.ContainingCollectionView?.props.Document.isTemplateDoc) { Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.Document); } else { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index e0ab5d97c..29834256a 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -746,6 +746,11 @@ export namespace Doc { source.dragFactory instanceof Doc && source.dragFactory.isTemplateDoc ? source.dragFactory : source && source.layout instanceof Doc && source.layout.isTemplateDoc ? source.layout : undefined; } + export function setChildDetailed(target: Doc, source?: Doc) { + target.childDetailed = source && source.isTemplateDoc ? source : source && + source.dragFactory instanceof Doc && source.dragFactory.isTemplateDoc ? source.dragFactory : + source && source.layout instanceof Doc && source.layout.isTemplateDoc ? source.layout : undefined; + } export function MakeDocFilter(docFilters: string[]) { let docFilterText = ""; diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index d5c34e128..3683e5820 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -68,6 +68,13 @@ export const positionSchema = createSchema({ z: "number", }); +export const collectionSchema = createSchema({ + childLayout: Doc, // layout template for children of a collecion + childDetailed: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field) + onChildClick: ScriptField, // script to run for each child when its clicked + onCheckedClick: ScriptField, // script to run when a checkbox is clicked next to a child in a tree view +}); + export type Document = makeInterface<[typeof documentSchema]>; export const Document = makeInterface(documentSchema); diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 4147be278..3255c6172 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -1,7 +1,7 @@ import { UndoManager } from "../client/util/UndoManager"; import { Doc, Field, FieldResult, UpdatingFromServer } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; -import { ProxyField } from "./Proxy"; +import { ProxyField, PrefetchProxy } from "./Proxy"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action, trace } from "mobx"; @@ -52,7 +52,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number value = new ProxyField(value); } if (value instanceof ObjectField) { - if (value[Parent] && value[Parent] !== receiver) { + if (value[Parent] && value[Parent] !== receiver && !(value instanceof PrefetchProxy)) { throw new Error("Can't put the same object in multiple documents at the same time"); } value[Parent] = receiver; -- cgit v1.2.3-70-g09d2 From 119f90cc5c4ef773133f1bfd18a813dde9487f94 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 21 Jan 2020 10:26:45 -0500 Subject: buxton templating fixes --- .../views/collections/CollectionPivotView.tsx | 5 ++-- .../views/collections/CollectionTreeView.tsx | 29 +++++++++++++--------- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 07ad5683c..816939a41 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -43,8 +43,9 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { (childDetailed) => DocCastAsync(childDetailed).then(childDetailed => { if (childDetailed instanceof Doc) { - let captured: { [name: string]: Field } = {}; - captured["childDetailed"] = new PrefetchProxy(childDetailed); + const targetKey = "childDetailed"; + const captured: { [name: string]: Field } = {}; + captured[targetKey] = new PrefetchProxy(childDetailed); const openDocText = "const alias = getAlias(this); Doc.ApplyTemplateTo(childDetailed, alias, 'layout_detailed'); useRightSplit(alias); "; const openDocScript = CompileScript(openDocText, { params: { this: Doc.name, heading: "boolean", context: Doc.name }, diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 3a208038c..4a6dffc1c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -634,22 +634,27 @@ export class CollectionTreeView extends CollectionSubView(Document) { } ContextMenu.Instance.addItem({ description: "Buxton Layout", icon: "eye", event: () => { - const { TextDocument, ImageDocument } = Docs.Create; + const { TextDocument, ImageDocument, MulticolumnDocument } = Docs.Create; + const { Document } = this.props; + const fallback = "http://www.cs.brown.edu/~bcz/face.gif"; const wrapper = Docs.Create.StackingDocument([ - ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "hero" }), + ImageDocument(fallback, { title: "hero" }), + MulticolumnDocument([], { title: "data", height: 100 }), ...["short_description", "year", "company", "degrees_of_freedom"].map(key => TextDocument({ title: key })) ], { autoHeight: true, chromeStatus: "disabled" }); wrapper.disableLOD = true; - makeTemplate(wrapper, true); - const detailedLayout = Doc.MakeAlias(wrapper); - const cardLayout = ImageBox.LayoutString("hero"); - this.childLayoutPairs.forEach(({ layout }) => { - const proto = Doc.GetProto(layout); - proto.layout = cardLayout; - proto.layout_detailed = detailedLayout; - layout.showTitle = "title"; - layout.showTitleHover = "titlehover"; - }); + wrapper.isTemplateDoc = makeTemplate(wrapper, true); + + const cardLayout = ImageDocument(fallback); + const proto = Doc.GetProto(cardLayout); + proto.layout = ImageBox.LayoutString("hero"); + cardLayout.showTitle = "title"; + cardLayout.showTitleHover = "titlehover"; + cardLayout.isTemplateField = true; // make this document act like a template field + cardLayout.isTemplateDoc = true; // but it's also a template doc itself... a little weird + + Document.childLayout = cardLayout; + Document.childDetailed = wrapper; } }); const existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); -- cgit v1.2.3-70-g09d2 From 74bad9d9deadeaf4959906e89457c16ed564fd01 Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 21 Jan 2020 16:09:30 -0500 Subject: initial commit --- src/client/documents/Documents.ts | 1 + .../views/collections/CollectionPivotView.tsx | 18 +++++-------- .../views/collections/CollectionTreeView.tsx | 7 +++-- src/new_fields/Doc.ts | 30 ++++++++++++++++++++++ 4 files changed, 41 insertions(+), 15 deletions(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 91085cd0f..6cb3f604e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -129,6 +129,7 @@ export interface DocumentOptions { isExpanded?: boolean; // is linear view expanded textTransform?: string; // is linear view expanded letterSpacing?: string; // is linear view expanded + treeViewChecked?: ScriptField; // computes whether or not the checkbox for this facet is checked } class EmptyBox { diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 816939a41..546fa3744 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -10,7 +10,7 @@ import { CollectionTreeView } from "./CollectionTreeView"; import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; import { Docs } from "../../documents/Documents"; import { ScriptField } from "../../../new_fields/ScriptField"; -import { CompileScript } from "../../util/Scripting"; +import { CompileScript, Scripting } from "../../util/Scripting"; import { anchorPoints, Flyout } from "../TemplateMenu"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { List } from "../../../new_fields/List"; @@ -43,9 +43,8 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { (childDetailed) => DocCastAsync(childDetailed).then(childDetailed => { if (childDetailed instanceof Doc) { - const targetKey = "childDetailed"; const captured: { [name: string]: Field } = {}; - captured[targetKey] = new PrefetchProxy(childDetailed); + captured.childDetailed = new PrefetchProxy(childDetailed); const openDocText = "const alias = getAlias(this); Doc.ApplyTemplateTo(childDetailed, alias, 'layout_detailed'); useRightSplit(alias); "; const openDocScript = CompileScript(openDocText, { params: { this: Doc.name, heading: "boolean", context: Doc.name }, @@ -76,6 +75,9 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { return facets.toArray(); } + /** + * Responds to clicking the check box in the flyout menu + */ facetClick = (facet: string) => { const facetCollection = this.props.Document.facetCollection; if (facetCollection instanceof Doc) { @@ -84,15 +86,9 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { //Doc.RemoveDocFromList(facetCollection, "data", DocListCast(facetCollection.data)[found]); (facetCollection.data as List).splice(found, 1); } else { - const facetValues = new Set(); - this.childDocs.forEach(child => { - Object.keys(Doc.GetProto(child)).forEach(key => child[key] instanceof Doc && facetValues.add((child[key] as Doc)[facet]?.toString() || "(null)")); - facetValues.add(child[facet]?.toString() || "(null)"); - }); - - const newFacetVals = facetValues.toArray().sort().map(val => Docs.Create.TextDocument({ title: val.toString() })); - const newFacet = Docs.Create.FreeformDocument(newFacetVals, { title: facet, treeViewOpen: true, isFacetFilter: true }); + const newFacet = Docs.Create.FreeformDocument([], { title: facet, treeViewOpen: true, isFacetFilter: true }); Doc.AddDocToList(facetCollection, "data", newFacet); + newFacet.data = ScriptField.MakeFunction("readFacetData()", { params: {} }); } } } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4a6dffc1c..2e9f0379c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -373,12 +373,12 @@ class TreeView extends React.Component { @action bulletClick = (e: React.MouseEvent) => { if (this.props.onCheckedClick && this.props.document.type !== DocumentType.COL) { - this.props.document.treeViewChecked = this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check"; + // this.props.document.treeViewChecked = this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check"; ScriptCast(this.props.onCheckedClick).script.run({ this: this.props.document.isTemplateField && this.props.dataDoc ? this.props.dataDoc : this.props.document, heading: this.props.containingCollection.title, checked: this.props.document.treeViewChecked === "check" ? false : this.props.document.treeViewChecked === "x" ? "x" : "none", - context: this.props.treeViewId + context: this.props.treeViewId, }, console.log); } else { this.treeViewOpen = !this.treeViewOpen; @@ -634,12 +634,11 @@ export class CollectionTreeView extends CollectionSubView(Document) { } ContextMenu.Instance.addItem({ description: "Buxton Layout", icon: "eye", event: () => { - const { TextDocument, ImageDocument, MulticolumnDocument } = Docs.Create; + const { TextDocument, ImageDocument } = Docs.Create; const { Document } = this.props; const fallback = "http://www.cs.brown.edu/~bcz/face.gif"; const wrapper = Docs.Create.StackingDocument([ ImageDocument(fallback, { title: "hero" }), - MulticolumnDocument([], { title: "data", height: 100 }), ...["short_description", "year", "company", "degrees_of_freedom"].map(key => TextDocument({ title: key })) ], { autoHeight: true, chromeStatus: "disabled" }); wrapper.disableLOD = true; diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index fa5ca1489..74b8df1a0 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -16,6 +16,7 @@ import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, u import { intersectRect } from "../Utils"; import { UndoManager } from "../client/util/UndoManager"; import { computedFn } from "mobx-utils"; +import { Docs } from "../client/documents/Documents"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -823,4 +824,33 @@ Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: an } const docFilterText = Doc.MakeDocFilter(docFilters); container.viewSpecScript = docFilterText ? ScriptField.MakeFunction(docFilterText, { doc: Doc.name }) : undefined; +}); + +Scripting.addGlobal(function readFacetData(target: Doc, facet: string) { + const facetValues = new Set(); + DocListCast(target.dataField).forEach(child => { + Object.keys(Doc.GetProto(child)).forEach(key => child[key] instanceof Doc && facetValues.add((child[key] as Doc)[facet]?.toString() || "(null)")); + facetValues.add(child[facet]?.toString() || "(null)"); + }); + return Array.from(facetValues).sort().map(val => { + const capturedVariables: { [name: string]: Field } = {}; + capturedVariables.facet = val; + capturedVariables.container = target; + return Docs.Create.TextDocument({ + title: val.toString(), + treeViewChecked: ScriptField.MakeFunction("readCheckedState(container, facetValue)", { capturedVariables }) + }); + }); +}); + +Scripting.addGlobal(function readCheckedState(container: Doc, facetValue: string) { + const docFilters = Cast(container.docFilter, listSpec("string"), []); + for (let i = 0; i < docFilters.length; i += 3) { + const key = docFilters[i]; + const value = docFilters[i + 1]; + if (key === facetValue) { + return value; + } + } + return false; }); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 8a4a8212b024e2804596a08ea820be646c9a7c0f Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Tue, 21 Jan 2020 19:02:43 -0500 Subject: functional but incomplete updating logic --- src/client/documents/Documents.ts | 2 - .../views/collections/CollectionPivotView.tsx | 30 ++++++++---- src/client/views/collections/CollectionSubView.tsx | 10 +++- .../views/collections/CollectionTreeView.tsx | 2 +- src/new_fields/Doc.ts | 55 +++++++++++----------- src/new_fields/ScriptField.ts | 13 ++--- 6 files changed, 67 insertions(+), 45 deletions(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6cb3f604e..d7292837c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -129,7 +129,6 @@ export interface DocumentOptions { isExpanded?: boolean; // is linear view expanded textTransform?: string; // is linear view expanded letterSpacing?: string; // is linear view expanded - treeViewChecked?: ScriptField; // computes whether or not the checkbox for this facet is checked } class EmptyBox { @@ -789,7 +788,6 @@ export namespace DocUtils { }); } - @undoBatch export function MakeLink(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, title: string = "", description: string = "", id?: string) { const sv = DocumentManager.Instance.getDocumentView(source.doc); if (sv && sv.props.ContainingCollectionDoc === target.doc) return; diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 546fa3744..f31f1aba6 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -9,7 +9,7 @@ import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormV import { CollectionTreeView } from "./CollectionTreeView"; import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; import { Docs } from "../../documents/Documents"; -import { ScriptField } from "../../../new_fields/ScriptField"; +import { ScriptField, ComputedField } from "../../../new_fields/ScriptField"; import { CompileScript, Scripting } from "../../util/Scripting"; import { anchorPoints, Flyout } from "../TemplateMenu"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -25,7 +25,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { } componentDidMount() { this.props.Document.freeformLayoutEngine = "pivot"; - if (true || !this.props.Document.facetCollection) { + if (!this.props.Document.facetCollection) { const facetCollection = Docs.Create.FreeformDocument([], { title: "facetFilters", yMargin: 0, treeViewHideTitle: true }); facetCollection.target = this.props.Document; @@ -38,7 +38,6 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { if (script.compiled) { facetCollection.onCheckedClick = new ScriptField(script); } - this._narrativeDisposer = reaction(() => this.props.Document.childDetailed, (childDetailed) => DocCastAsync(childDetailed).then(childDetailed => { @@ -78,17 +77,32 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { /** * Responds to clicking the check box in the flyout menu */ - facetClick = (facet: string) => { - const facetCollection = this.props.Document.facetCollection; + facetClick = (facetHeader: string) => { + const { Document, fieldKey } = this.props; + const facetCollection = Document.facetCollection; if (facetCollection instanceof Doc) { - const found = DocListCast(facetCollection.data).findIndex(doc => doc.title === facet); + const found = DocListCast(facetCollection.data).findIndex(doc => doc.title === facetHeader); if (found !== -1) { //Doc.RemoveDocFromList(facetCollection, "data", DocListCast(facetCollection.data)[found]); (facetCollection.data as List).splice(found, 1); } else { - const newFacet = Docs.Create.FreeformDocument([], { title: facet, treeViewOpen: true, isFacetFilter: true }); + const newFacet = Docs.Create.FreeformDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true }); Doc.AddDocToList(facetCollection, "data", newFacet); - newFacet.data = ScriptField.MakeFunction("readFacetData()", { params: {} }); + const { dataDoc } = this; + const capturedVariables = { + layoutDoc: Document, + dataDoc, + dataKey: fieldKey, + facetHeader + }; + const params = { + layoutDoc: Doc.name, + dataDoc: Doc.name, + dataKey: "string", + facetHeader: "string" + }; + newFacet.container = dataDoc; + newFacet.data = ComputedField.MakeFunction("readFacetData(layoutDoc, dataDoc, dataKey, facetHeader)", params, capturedVariables); } } } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5f4ee3669..9357b0507 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -90,7 +90,15 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { // 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.props.annotationsKey ? (this.extensionDoc ? this.extensionDoc[this.props.annotationsKey] : undefined) : this.dataDoc[this.props.fieldKey]; + const { annotationsKey, fieldKey } = this.props; + const { extensionDoc, dataDoc } = this; + if (annotationsKey) { + if (extensionDoc) { + return extensionDoc[annotationsKey]; + } + return undefined; + } + return dataDoc[fieldKey]; } get childLayoutPairs(): { layout: Doc; data: Doc; }[] { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2e9f0379c..ffaad2ddd 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -377,7 +377,7 @@ class TreeView extends React.Component { ScriptCast(this.props.onCheckedClick).script.run({ this: this.props.document.isTemplateField && this.props.dataDoc ? this.props.dataDoc : this.props.document, heading: this.props.containingCollection.title, - checked: this.props.document.treeViewChecked === "check" ? false : this.props.document.treeViewChecked === "x" ? "x" : "none", + checked: this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check", context: this.props.treeViewId, }, console.log); } else { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 74b8df1a0..69d478a48 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -1,4 +1,4 @@ -import { observable, ObservableMap, runInAction, action, untracked } from "mobx"; +import { observable, ObservableMap, runInAction } from "mobx"; import { alias, map, serializable } from "serializr"; import { DocServer } from "../client/DocServer"; import { DocumentType } from "../client/documents/DocumentTypes"; @@ -11,7 +11,7 @@ import { PrefetchProxy, ProxyField } from "./Proxy"; import { FieldId, RefField } from "./RefField"; import { listSpec } from "./Schema"; import { ComputedField, ScriptField } from "./ScriptField"; -import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast, ToConstructor } from "./Types"; +import { BoolCast, Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; import { intersectRect } from "../Utils"; import { UndoManager } from "../client/util/UndoManager"; @@ -807,16 +807,15 @@ Scripting.addGlobal(function matchFieldValue(doc: Doc, key: string, value: any) } return false; }); -Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers: string) { +Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: string) { const docFilters = Cast(container.docFilter, listSpec("string"), []); - let found = false; - for (let i = 0; i < docFilters.length && !found; i += 3) { + for (let i = 0; i < docFilters.length; i += 3) { if (docFilters[i] === key && docFilters[i + 1] === value) { - found = true; docFilters.splice(i, 3); + break; } } - if (!found || modifiers !== "none") { + if (modifiers !== undefined) { docFilters.push(key); docFilters.push(value); docFilters.push(modifiers); @@ -826,31 +825,33 @@ Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: an container.viewSpecScript = docFilterText ? ScriptField.MakeFunction(docFilterText, { doc: Doc.name }) : undefined; }); -Scripting.addGlobal(function readFacetData(target: Doc, facet: string) { +Scripting.addGlobal(function readFacetData(layoutDoc: Doc, dataDoc: Doc, dataKey: string, facetHeader: string) { const facetValues = new Set(); - DocListCast(target.dataField).forEach(child => { - Object.keys(Doc.GetProto(child)).forEach(key => child[key] instanceof Doc && facetValues.add((child[key] as Doc)[facet]?.toString() || "(null)")); - facetValues.add(child[facet]?.toString() || "(null)"); - }); - return Array.from(facetValues).sort().map(val => { - const capturedVariables: { [name: string]: Field } = {}; - capturedVariables.facet = val; - capturedVariables.container = target; - return Docs.Create.TextDocument({ - title: val.toString(), - treeViewChecked: ScriptField.MakeFunction("readCheckedState(container, facetValue)", { capturedVariables }) - }); + DocListCast(dataDoc[dataKey]).forEach(child => { + Object.keys(Doc.GetProto(child)).forEach(key => child[key] instanceof Doc && facetValues.add((child[key] as Doc)[facetHeader]?.toString() || "(null)")); + facetValues.add(child[facetHeader]?.toString() || "(null)"); }); + const text = "determineCheckedState(layoutDoc, facetHeader, facetValue)"; + const params = { + layoutDoc: Doc.name, + facetHeader: "string", + facetValue: "string" + }; + const capturedVariables = { layoutDoc, facetHeader }; + return new List(Array.from(facetValues).sort().map(facetValue => { + const value = Docs.Create.TextDocument({ title: facetValue.toString() }); + value.treeViewChecked = ComputedField.MakeFunction(text, params, { ...capturedVariables, facetValue }); + return value; + })); }); -Scripting.addGlobal(function readCheckedState(container: Doc, facetValue: string) { - const docFilters = Cast(container.docFilter, listSpec("string"), []); +Scripting.addGlobal(function determineCheckedState(layoutDoc: Doc, facetHeader: string, facetValue: string) { + const docFilters = Cast(layoutDoc.docFilter, listSpec("string"), []); for (let i = 0; i < docFilters.length; i += 3) { - const key = docFilters[i]; - const value = docFilters[i + 1]; - if (key === facetValue) { - return value; + const [header, value, state] = docFilters.slice(i, i + 3); + if (header === facetHeader && value === facetValue) { + return state; } } - return false; + return undefined; }); \ No newline at end of file diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 09a18c258..f8a8d1226 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -3,7 +3,7 @@ import { CompiledScript, CompileScript, scriptingGlobal, ScriptOptions } from ". import { Copy, ToScriptString, ToString, Parent, SelfProxy } from "./FieldSymbols"; import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; import { Deserializable, autoObject } from "../client/util/SerializationHelper"; -import { Doc } from "../new_fields/Doc"; +import { Doc, Field } from "../new_fields/Doc"; import { Plugins } from "./util"; import { computedFn } from "mobx-utils"; import { ProxyField } from "./Proxy"; @@ -104,12 +104,13 @@ export class ScriptField extends ObjectField { [ToString]() { return "script field"; } - public static CompileScript(script: string, params: object = {}, addReturn = false) { + public static CompileScript(script: string, params: object = {}, addReturn = false, capturedVariables?: { [name: string]: Field }) { const compiled = CompileScript(script, { params: { this: Doc.name, _last_: "any", ...params }, typecheck: false, editable: true, - addReturn: addReturn + addReturn: addReturn, + capturedVariables }); return compiled; } @@ -130,12 +131,12 @@ export class ComputedField extends ScriptField { _lastComputedResult: any; //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ this: doc, _last_: this._lastComputedResult }, console.log).result); - public static MakeScript(script: string, params: object = {}, ) { + public static MakeScript(script: string, params: object = {}) { const compiled = ScriptField.CompileScript(script, params, false); return compiled.compiled ? new ComputedField(compiled) : undefined; } - public static MakeFunction(script: string, params: object = {}) { - const compiled = ScriptField.CompileScript(script, params, true); + public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Field }) { + const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); return compiled.compiled ? new ComputedField(compiled) : undefined; } } -- cgit v1.2.3-70-g09d2 From 613c2c8de636927fb38a7a32ec6b0427b238db2b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 21 Jan 2020 21:33:42 -0500 Subject: added filter resizer for pivot viewer. fixed click/drag confusion with mainview divider. --- src/client/views/MainView.tsx | 5 +- .../views/collections/CollectionPivotView.scss | 13 +++- .../views/collections/CollectionPivotView.tsx | 90 +++++++++++++--------- 3 files changed, 70 insertions(+), 38 deletions(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d7656aba4..0958c434a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -307,8 +307,10 @@ export class MainView extends React.Component { ; } + _canClick = false; onPointerDown = (e: React.PointerEvent) => { if (this._flyoutTranslate) { + this._canClick = true; this._flyoutSizeOnDown = e.clientX; document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -339,11 +341,12 @@ export class MainView extends React.Component { @action onPointerMove = (e: PointerEvent) => { this.flyoutWidth = Math.max(e.clientX, 0); + Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false); this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; } @action onPointerUp = (e: PointerEvent) => { - if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4) { + if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4 && this._canClick) { this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0; this.flyoutWidth && (this.sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30); } diff --git a/src/client/views/collections/CollectionPivotView.scss b/src/client/views/collections/CollectionPivotView.scss index bd3d6c77b..2ddcc97ea 100644 --- a/src/client/views/collections/CollectionPivotView.scss +++ b/src/client/views/collections/CollectionPivotView.scss @@ -45,7 +45,7 @@ } .collectionPivotView-tree { display:inline-block; - width: 200px; + width: 100%; height: calc(100% - 30px); } } @@ -54,4 +54,15 @@ width: calc(100% - 200px); height: 100%; } + .collectionPivotView-dragger { + background-color: lightgray; + height: 40px; + width: 20px; + position: absolute; + border-radius: 10px; + top: 55%; + border: 1px black solid; + z-index: 2; + left:-10px; + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index f31f1aba6..8e712e370 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -65,7 +65,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { return Doc.fieldExtensionDoc(this.props.DataDoc || this.props.Document, this.props.fieldKey); } - bodyPanelWidth = () => this.props.PanelWidth() - 200; + bodyPanelWidth = () => this.props.PanelWidth() - this._facetWidth; getTransform = () => this.props.ScreenToLocalTransform().translate(-200, 0); @computed get _allFacets() { @@ -78,39 +78,53 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { * Responds to clicking the check box in the flyout menu */ facetClick = (facetHeader: string) => { - const { Document, fieldKey } = this.props; - const facetCollection = Document.facetCollection; + const facetCollection = this.props.Document.facetCollection; if (facetCollection instanceof Doc) { const found = DocListCast(facetCollection.data).findIndex(doc => doc.title === facetHeader); if (found !== -1) { - //Doc.RemoveDocFromList(facetCollection, "data", DocListCast(facetCollection.data)[found]); (facetCollection.data as List).splice(found, 1); } else { const newFacet = Docs.Create.FreeformDocument([], { 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); - const { dataDoc } = this; - const capturedVariables = { - layoutDoc: Document, - dataDoc, - dataKey: fieldKey, - facetHeader - }; - const params = { - layoutDoc: Doc.name, - dataDoc: Doc.name, - dataKey: "string", - facetHeader: "string" - }; - newFacet.container = dataDoc; - newFacet.data = ComputedField.MakeFunction("readFacetData(layoutDoc, dataDoc, dataKey, facetHeader)", params, capturedVariables); } } } + _canClick = false; + _facetWidthOnDown = 0; + @observable _facetWidth = 200; + onPointerDown = (e: React.PointerEvent) => { + this._canClick = true; + this._facetWidthOnDown = e.screenX; + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointerup", this.onPointerUp); + e.stopPropagation(); + e.preventDefault(); + } + + + @action + onPointerMove = (e: PointerEvent) => { + this._facetWidth = Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0); + Math.abs(e.movementX) > 6 && (this._canClick = false); + } + @action + onPointerUp = (e: PointerEvent) => { + if (Math.abs(e.screenX - this._facetWidthOnDown) < 6 && this._canClick) { + this._facetWidth = this._facetWidth < 15 ? 200 : 0; + } + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + } render() { const facetCollection = Cast(this.props.Document?.facetCollection, Doc, null); const flyout = ( -
+
{this._allFacets.map(facet => )}
); - return !facetCollection ? (null) :
-
-
e.stopPropagation()}> - -
- Facet Filters - -
-
+ return !facetCollection ? (null) : +
+
+
-
- +
+
e.stopPropagation()}> + +
+ Facet Filters + +
+
+
+
+ +
-
-
- -
-
; +
+ +
+
; } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 6b1e9b68c3d409df6ea2a8909b99d5d8d75226c5 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 22 Jan 2020 12:53:40 -0500 Subject: various fixes to pivot view related things. --- src/client/documents/Documents.ts | 3 +- .../views/collections/CollectionPivotView.tsx | 39 ++++++++++------------ .../views/collections/CollectionTreeView.tsx | 33 +++++++++--------- .../CollectionFreeFormLayoutEngines.tsx | 6 +--- .../collections/collectionFreeForm/MarqueeView.tsx | 1 + src/scraping/buxton/scraper.py | 6 +++- .../authentication/models/current_user_utils.ts | 2 +- 7 files changed, 45 insertions(+), 45 deletions(-) (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 634c223a7..e86ed52f3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -88,7 +88,7 @@ export interface DocumentOptions { defaultBackgroundColor?: string; dropAction?: dropActionType; chromeStatus?: string; - disableLOD?: boolean; + LODdisable?: boolean; columnWidth?: number; fontSize?: number; curPage?: number; @@ -107,6 +107,7 @@ export interface DocumentOptions { ischecked?: ScriptField; // returns whether a font icon box is checked activePen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts) onClick?: ScriptField; + onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked onPointerDown?: ScriptField; onPointerUp?: ScriptField; dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index 8e712e370..f23540529 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -26,36 +26,33 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { componentDidMount() { this.props.Document.freeformLayoutEngine = "pivot"; if (!this.props.Document.facetCollection) { - const facetCollection = Docs.Create.FreeformDocument([], { title: "facetFilters", yMargin: 0, treeViewHideTitle: true }); + const facetCollection = Docs.Create.TreeDocument([], { title: "facetFilters", yMargin: 0, treeViewHideTitle: true }); facetCollection.target = this.props.Document; - const scriptText = "setDocFilter(context.target, heading, this.title, checked)"; + const scriptText = "setDocFilter(containingTreeView.target, heading, this.title, checked)"; const script = CompileScript(scriptText, { - params: { this: Doc.name, heading: "boolean", checked: "boolean", context: Doc.name }, + params: { this: Doc.name, heading: "boolean", checked: "boolean", containingTreeView: Doc.name }, typecheck: false, editable: true, }); if (script.compiled) { facetCollection.onCheckedClick = new ScriptField(script); } - this._narrativeDisposer = reaction(() => this.props.Document.childDetailed, - (childDetailed) => - DocCastAsync(childDetailed).then(childDetailed => { - if (childDetailed instanceof Doc) { - const captured: { [name: string]: Field } = {}; - captured.childDetailed = new PrefetchProxy(childDetailed); - const openDocText = "const alias = getAlias(this); Doc.ApplyTemplateTo(childDetailed, alias, 'layout_detailed'); useRightSplit(alias); "; - const openDocScript = CompileScript(openDocText, { - params: { this: Doc.name, heading: "boolean", context: Doc.name }, - typecheck: false, - editable: true, - capturedVariables: captured - }); - if (openDocScript.compiled) { - this.props.Document.onChildClick = new ScriptField(openDocScript); - } + const openDocText = "const alias = getAlias(this); Doc.ApplyTemplateTo(childDetailed, alias, 'layout_detailed'); useRightSplit(alias); "; + this._narrativeDisposer = reaction(() => DocCastAsync(this.props.Document.childDetailed), + (childDetailedPromise) => childDetailedPromise.then(childDetailed => { + if (childDetailed) { + const openDocScript = CompileScript(openDocText, { + params: { this: Doc.name, heading: "boolean", containingTreeView: Doc.name }, + capturedVariables: { childDetailed: new PrefetchProxy(childDetailed) }, + typecheck: false, + editable: true, + }); + if (openDocScript.compiled) { + this.props.Document.onChildClick = new ScriptField(openDocScript); } - }), { fireImmediately: true }); + } + }), { fireImmediately: true }); this.props.Document.facetCollection = facetCollection; this.props.Document.fitToBox = true; } @@ -84,7 +81,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { if (found !== -1) { (facetCollection.data as List).splice(found, 1); } else { - const newFacet = Docs.Create.FreeformDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true }); + 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); diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2433cc40e..bef587786 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -32,6 +32,7 @@ import { Templates } from '../Templates'; import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); +import { CollectionViewType } from './CollectionView'; export interface TreeViewProps { @@ -377,7 +378,7 @@ class TreeView extends React.Component { this: this.props.document.isTemplateField && this.props.dataDoc ? this.props.dataDoc : this.props.document, heading: this.props.containingCollection.title, checked: this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check", - context: this.props.treeViewId, + containingTreeView: this.props.treeViewId, }, console.log); } else { this.treeViewOpen = !this.treeViewOpen; @@ -635,32 +636,32 @@ export class CollectionTreeView extends CollectionSubView(Document) { description: "Buxton Layout", icon: "eye", event: () => { const { TextDocument, ImageDocument, MulticolumnDocument } = Docs.Create; const { Document } = this.props; - const fallback = "http://www.cs.brown.edu/~bcz/face.gif"; - const imageRack = MulticolumnDocument([], { title: "data", height: 100 }); - const wrapper = Docs.Create.StackingDocument([ - ImageDocument(fallback, { title: "hero" }), - imageRack, - ...["short_description", "year", "company", "degrees_of_freedom"].map(key => TextDocument({ title: key })) - ], { autoHeight: true, chromeStatus: "disabled", disableLOD: true, title: "detailed layout stack" }); - wrapper.isTemplateDoc = makeTemplate(wrapper); - imageRack.onChildClick = ScriptField.MakeFunction(`containingCollection.resolvedDataDoc.hero = copyField(this.data)`, { containingCollection: Doc.name }); - - const cardLayout = ImageDocument(fallback); + const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif"; + + const detailedLayout = Docs.Create.StackingDocument([ + ImageDocument(fallbackImg, { title: "activeHero" }), + MulticolumnDocument([], { title: "data", height: 100, onChildClick: ScriptField.MakeFunction(`containingCollection.resolvedDataDoc.activeHero = copyField(this.data)`, { containingCollection: Doc.name }) }), + TextDocument({ title: "short_description", autoHeight: true }), + ...["year", "company", "degrees_of_freedom"].map(key => TextDocument({ title: key, height: 30 })) + ], { autoHeight: true, chromeStatus: "disabled", title: "detailed layout stack" }); + detailedLayout.isTemplateDoc = makeTemplate(detailedLayout); + + const cardLayout = ImageDocument(fallbackImg, { isTemplateDoc: true, isTemplateField: true }); // this acts like a template doc and a template field ... a little weird, but seems to work? cardLayout.proto!.layout = ImageBox.LayoutString("hero"); cardLayout.showTitle = "title"; cardLayout.showTitleHover = "titlehover"; - cardLayout.isTemplateField = true; // make this document act like a template field - cardLayout.isTemplateDoc = true; // but it's also a template doc itself... a little weird Document.childLayout = cardLayout; - Document.childDetailed = wrapper; + Document.childDetailed = detailedLayout; + Document.viewType = CollectionViewType.Pivot; + Document.pivotField = "company"; } }); const existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; onClicks.push({ description: "Edit onChecked Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Checked Changed ...", this.props.Document, - "onCheckedClick", obj.x, obj.y, { heading: "boolean", checked: "boolean", context: Doc.name }) + "onCheckedClick", obj.x, obj.y, { heading: "boolean", checked: "boolean", treeViewContainer: Doc.name }) }); !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 5c6336248..32097816d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -59,11 +59,7 @@ export function computePivotLayout(poolData: ObservableMap, pivotDo let numCols = NumCast(pivotDoc.pivotNumColumns, Math.ceil(Math.sqrt(minSize))); const docMap = new Map(); const groupNames: PivotData[] = []; - if (panelDim[0] < 2500) numCols = Math.min(5, numCols); - if (panelDim[0] < 2000) numCols = Math.min(4, numCols); - if (panelDim[0] < 1400) numCols = Math.min(3, numCols); - if (panelDim[0] < 1000) numCols = Math.min(2, numCols); - if (panelDim[0] < 600) numCols = 1; + numCols = Math.min(panelDim[0] / pivotAxisWidth, numCols) const expander = 1.05; const gap = .15; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 523edb918..584d18372 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -331,6 +331,7 @@ export class MarqueeView extends React.Component Date: Wed, 22 Jan 2020 15:41:04 -0500 Subject: basic cleanup for warnings --- src/client/apis/youtube/YoutubeBox.tsx | 2 +- src/client/util/ProseMirrorEditorView.tsx | 74 ---------------------- src/client/util/RichTextMenu.tsx | 68 ++++++++++---------- src/client/util/RichTextSchema.tsx | 2 +- src/client/views/EditableView.tsx | 2 +- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionPivotView.tsx | 11 ++-- .../views/collections/CollectionTreeView.tsx | 2 +- .../views/collections/CollectionViewChromes.tsx | 3 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 3 + src/client/views/linking/LinkMenu.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 2 +- src/client/views/search/SearchItem.tsx | 1 - src/new_fields/Doc.ts | 10 +-- src/new_fields/documentSchemas.ts | 1 + src/server/Websocket/Websocket.ts | 2 - 17 files changed, 59 insertions(+), 132 deletions(-) delete mode 100644 src/client/util/ProseMirrorEditorView.tsx (limited to 'src/client/views/collections/CollectionPivotView.tsx') diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx index fd3d9e2f1..d654e2530 100644 --- a/src/client/apis/youtube/YoutubeBox.tsx +++ b/src/client/apis/youtube/YoutubeBox.tsx @@ -46,7 +46,7 @@ export class YoutubeBox extends React.Component { * When component mounts, last search's results are laoded in based on the back up stored * in the document of the props. */ - async componentWillMount() { + async componentDidMount() { //DocServer.getYoutubeChannels(); const castedSearchBackUp = Cast(this.props.Document.cachedSearchResults, Doc); const awaitedBackUp = await castedSearchBackUp; diff --git a/src/client/util/ProseMirrorEditorView.tsx b/src/client/util/ProseMirrorEditorView.tsx deleted file mode 100644 index b42adfbb4..000000000 --- a/src/client/util/ProseMirrorEditorView.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React from "react"; -import { EditorView } from "prosemirror-view"; -import { EditorState } from "prosemirror-state"; - -export interface ProseMirrorEditorViewProps { - /* EditorState instance to use. */ - editorState: EditorState; - /* Called when EditorView produces new EditorState. */ - onEditorState: (editorState: EditorState) => any; -} - -/** - * This wraps ProseMirror's EditorView into React component. - * This code was found on https://discuss.prosemirror.net/t/using-with-react/904 - */ -export class ProseMirrorEditorView extends React.Component { - - private _editorView?: EditorView; - - _createEditorView = (element: HTMLDivElement | null) => { - if (element !== null) { - this._editorView = new EditorView(element, { - state: this.props.editorState, - dispatchTransaction: this.dispatchTransaction, - }); - } - } - - dispatchTransaction = (tx: any) => { - // In case EditorView makes any modification to a state we funnel those - // modifications up to the parent and apply to the EditorView itself. - const editorState = this.props.editorState.apply(tx); - if (this._editorView) { - this._editorView.updateState(editorState); - } - this.props.onEditorState(editorState); - } - - focus() { - if (this._editorView) { - this._editorView.focus(); - } - } - - componentWillReceiveProps(nextProps: { editorState: EditorState; }) { - // In case we receive new EditorState through props — we apply it to the - // EditorView instance. - if (this._editorView) { - if (nextProps.editorState !== this.props.editorState) { - this._editorView.updateState(nextProps.editorState); - } - } - } - - componentWillUnmount() { - if (this._editorView) { - this._editorView.destroy(); - } - } - - shouldComponentUpdate() { - // Note that EditorView manages its DOM itself so we'd ratrher don't mess - // with it. - return false; - } - - render() { - // Render just an empty div which is then used as a container for an - // EditorView instance. - return ( -
- ); - } -} \ No newline at end of file diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx index f070589ae..eb5c90654 100644 --- a/src/client/util/RichTextMenu.tsx +++ b/src/client/util/RichTextMenu.tsx @@ -73,7 +73,7 @@ export default class RichTextMenu extends AntimodeMenu { this.fontSizeOptions = [ { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize }, { mark: schema.marks.pFontSize.create({ fontSize: 8 }), title: "Set font size", label: "8pt", command: this.changeFontSize }, - { mark: schema.marks.pFontSize.create({ fontSize: 9 }), title: "Set font size", label: "8pt", command: this.changeFontSize }, + { mark: schema.marks.pFontSize.create({ fontSize: 9 }), title: "Set font size", label: "9pt", command: this.changeFontSize }, { mark: schema.marks.pFontSize.create({ fontSize: 10 }), title: "Set font size", label: "10pt", command: this.changeFontSize }, { mark: schema.marks.pFontSize.create({ fontSize: 12 }), title: "Set font size", label: "12pt", command: this.changeFontSize }, { mark: schema.marks.pFontSize.create({ fontSize: 14 }), title: "Set font size", label: "14pt", command: this.changeFontSize }, @@ -312,22 +312,22 @@ export default class RichTextMenu extends AntimodeMenu { } return ( - ); } - createMarksDropdown(activeOption: string, options: { mark: Mark | null, title: string, label: string, command: (mark: Mark, view: EditorView) => void, hidden?: boolean, style?: {} }[]): JSX.Element { + createMarksDropdown(activeOption: string, options: { mark: Mark | null, title: string, label: string, command: (mark: Mark, view: EditorView) => void, hidden?: boolean, style?: {} }[], key: string): JSX.Element { const items = options.map(({ title, label, hidden, style }) => { if (hidden) { return label === activeOption ? - : - ; + : + ; } return label === activeOption ? - : - ; + : + ; }); const self = this; @@ -340,19 +340,19 @@ export default class RichTextMenu extends AntimodeMenu { } }); } - return ; + return ; } - createNodesDropdown(activeOption: string, options: { node: NodeType | any | null, title: string, label: string, command: (node: NodeType | any) => void, hidden?: boolean, style?: {} }[]): JSX.Element { + createNodesDropdown(activeOption: string, options: { node: NodeType | any | null, title: string, label: string, command: (node: NodeType | any) => void, hidden?: boolean, style?: {} }[], key: string): JSX.Element { const items = options.map(({ title, label, hidden, style }) => { if (hidden) { return label === activeOption ? - : - ; + : + ; } return label === activeOption ? - : - ; + : + ; }); const self = this; @@ -363,7 +363,7 @@ export default class RichTextMenu extends AntimodeMenu { } }); } - return ; + return ; } changeFontSize = (mark: Mark, view: EditorView) => { @@ -472,7 +472,7 @@ export default class RichTextMenu extends AntimodeMenu {
; return ( - + ); } @@ -535,21 +535,21 @@ export default class RichTextMenu extends AntimodeMenu { ; const dropdownContent = -
+

Change font color:

{this.fontColors.map(color => { if (color) { return this.activeFontColor === color ? - : - ; + : + ; } })}
; return ( - + ); } @@ -582,7 +582,7 @@ export default class RichTextMenu extends AntimodeMenu { } const button = - ; @@ -594,15 +594,15 @@ export default class RichTextMenu extends AntimodeMenu { {this.highlightColors.map(color => { if (color) { return this.activeHighlightColor === color ? - : - ; + : + ; } })}
; return ( - + ); } @@ -635,7 +635,7 @@ export default class RichTextMenu extends AntimodeMenu {
; return ( - + ); } @@ -773,7 +773,7 @@ export default class RichTextMenu extends AntimodeMenu { render() { - const row1 =
{[ + const row1 =
{[ this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)), this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)), this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)), @@ -787,14 +787,14 @@ export default class RichTextMenu extends AntimodeMenu { this.createButton("indent", "Summarize", undefined, this.insertSummarizer), ]}
; - const row2 =
-
- {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions), - this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions), - this.createNodesDropdown(this.activeListType, this.listTypeOptions)]} + const row2 =
+
+ {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size"), + this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family"), + this.createNodesDropdown(this.activeListType, this.listTypeOptions, "nodes")]}
-
- {this.getDragger()} @@ -864,12 +864,12 @@ class ButtonDropdown extends React.Component { : <> {this.props.button} - } - {this.showDropdown ? this.props.dropdownContent : <>} + {this.showDropdown ? this.props.dropdownContent : (null)}
); } diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 1f70cafc4..5751c8c7e 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -306,7 +306,7 @@ export const marks: { [index: string]: MarkSpec } = { } }], toDOM(node: any) { - return node.attrs.color ? ['span', { style: 'color:' + node.attrs.color }] : ['span', { style: 'color: black' }]; + return node.attrs.color ? ['span', { style: 'color:' + node.attrs.color }] : ['span', 0]; } }, diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 0d677b8ce..394caba72 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -66,7 +66,7 @@ export class EditableView extends React.Component { } @action - componentWillReceiveProps(nextProps: EditableProps) { + componentDidUpdate(nextProps: EditableProps) { // this is done because when autosuggest is turned on, the suggestions are passed in as a prop, // so when the suggestions are passed in, and no editing prop is passed in, it used to set it // to false. this will no longer do so -syip diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 0958c434a..79e0cfea5 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -64,7 +64,7 @@ export class MainView extends React.Component { public isPointerDown = false; - componentWillMount() { + componentDidMount() { const tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx index f23540529..aa68cc18f 100644 --- a/src/client/views/collections/CollectionPivotView.tsx +++ b/src/client/views/collections/CollectionPivotView.tsx @@ -28,6 +28,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { if (!this.props.Document.facetCollection) { const facetCollection = Docs.Create.TreeDocument([], { title: "facetFilters", yMargin: 0, treeViewHideTitle: true }); facetCollection.target = this.props.Document; + facetCollection.dontCopyOnAlias = true; const scriptText = "setDocFilter(containingTreeView.target, heading, this.title, checked)"; const script = CompileScript(scriptText, { @@ -122,8 +123,8 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) { const facetCollection = Cast(this.props.Document?.facetCollection, Doc, null); const flyout = (
- {this._allFacets.map(facet =>