diff options
| author | Stanley Yip <stanley_yip@brown.edu> | 2020-02-09 14:58:57 -0500 |
|---|---|---|
| committer | Stanley Yip <stanley_yip@brown.edu> | 2020-02-09 14:58:57 -0500 |
| commit | f6179334d6f2942631caa17b7c8ae2531d87c7c4 (patch) | |
| tree | 091da0ef7bedb900c958c28cebe4058fade644cf /src/client/views/collections/CollectionStackingViewFieldColumn.tsx | |
| parent | 07141291bee793955d7061f4e479942d7aceda67 (diff) | |
| parent | 87167fd126e161b29d8d798a5f04e3cf159aae16 (diff) | |
recommender system works
Diffstat (limited to 'src/client/views/collections/CollectionStackingViewFieldColumn.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionStackingViewFieldColumn.tsx | 161 |
1 files changed, 108 insertions, 53 deletions
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index b9d334b10..2a9f903bb 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -2,17 +2,14 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faPalette } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, observable, trace, runInAction } from "mobx"; +import { action, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, WidthSym } from "../../../new_fields/Doc"; -import { Id } from "../../../new_fields/FieldSymbols"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { ScriptField } from "../../../new_fields/ScriptField"; import { NumCast, StrCast } from "../../../new_fields/Types"; -import { Utils } from "../../../Utils"; import { Docs } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; -import { CompileScript } from "../../util/Scripting"; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; @@ -20,6 +17,13 @@ import { anchorPoints, Flyout } from "../DocumentDecorations"; import { EditableView } from "../EditableView"; import { CollectionStackingView } from "./CollectionStackingView"; import "./CollectionStackingView.scss"; +import { TraceMobx } from "../../../new_fields/util"; +import { FormattedTextBox } from "../nodes/FormattedTextBox"; +import { ImageField } from "../../../new_fields/URLField"; +import { ImageBox } from "../nodes/ImageBox"; +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { RichTextField } from "../../../new_fields/RichTextField"; library.add(faPalette); @@ -53,28 +57,28 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC this._dropRef = ele; this.dropDisposer && this.dropDisposer(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.columnDrop.bind(this) } }); + this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this)); } } @undoBatch columnDrop = action((e: Event, de: DragManager.DropEvent) => { this._createAliasSelected = false; - if (de.data instanceof DragManager.DocumentDragData) { - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(this._heading); + if (de.complete.docDragData) { + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const castedValue = this.getValue(this._heading); if (castedValue) { - de.data.droppedDocuments.forEach(d => d[key] = castedValue); + de.complete.docDragData.droppedDocuments.forEach(d => d[key] = castedValue); } else { - de.data.droppedDocuments.forEach(d => d[key] = undefined); + de.complete.docDragData.droppedDocuments.forEach(d => d[key] = undefined); } this.props.parent.drop(e, de); e.stopPropagation(); } }); getValue = (value: string): any => { - let parsed = parseInt(value); + const parsed = parseInt(value); if (!isNaN(parsed)) { return parsed; } @@ -90,8 +94,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action headingChanged = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let castedValue = this.getValue(value); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const castedValue = this.getValue(value); if (castedValue) { if (this.props.parent.sectionHeaders) { if (this.props.parent.sectionHeaders.map(i => i.heading).indexOf(castedValue.toString()) > -1) { @@ -134,12 +138,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action addDocument = (value: string, shiftDown?: boolean) => { + if (!value) return false; this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); - let newDoc = Docs.Create.TextDocument({ height: 18, width: 200, documentText: "@@@" + value, title: value, autoHeight: true }); + const key = StrCast(this.props.parent.props.Document.sectionFilter); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, title: value, _autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); - let maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); - let heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; + const maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); + const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; newDoc.heading = heading; return this.props.parent.props.addDocument(newDoc); } @@ -147,10 +152,10 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @action deleteColumn = () => { this._createAliasSelected = false; - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const key = StrCast(this.props.parent.props.Document.sectionFilter); this.props.docList.forEach(d => d[key] = undefined); if (this.props.parent.sectionHeaders && this.props.headingObject) { - let index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); + const index = this.props.parent.sectionHeaders.indexOf(this.props.headingObject); this.props.parent.sectionHeaders.splice(index, 1); } } @@ -166,10 +171,10 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } startDrag = (e: PointerEvent) => { - let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); + const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { - let alias = Doc.MakeAlias(this.props.parent.props.Document); - let key = StrCast(this.props.parent.props.Document.sectionFilter); + const alias = Doc.MakeAlias(this.props.parent.props.Document); + const key = StrCast(this.props.parent.props.Document.sectionFilter); let value = this.getValue(this._heading); value = typeof value === "string" ? `"${value}"` : value; alias.viewSpecScript = ScriptField.MakeFunction(`doc.${key} === ${value}`, { doc: Doc.name }); @@ -195,7 +200,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC e.stopPropagation(); e.preventDefault(); - let [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); + const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); this._startDragPosition = { x: dx, y: dy }; if (this._createAliasSelected) { @@ -208,17 +213,17 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } renderColorPicker = () => { - let selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; - - let pink = PastelSchemaPalette.get("pink2"); - let purple = PastelSchemaPalette.get("purple4"); - let blue = PastelSchemaPalette.get("bluegreen1"); - let yellow = PastelSchemaPalette.get("yellow4"); - let red = PastelSchemaPalette.get("red2"); - let green = PastelSchemaPalette.get("bluegreen7"); - let cyan = PastelSchemaPalette.get("bluegreen5"); - let orange = PastelSchemaPalette.get("orange1"); - let gray = "#f1efeb"; + const selected = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; + + const pink = PastelSchemaPalette.get("pink2"); + const purple = PastelSchemaPalette.get("purple4"); + const blue = PastelSchemaPalette.get("bluegreen1"); + const yellow = PastelSchemaPalette.get("yellow4"); + const red = PastelSchemaPalette.get("red2"); + const green = PastelSchemaPalette.get("bluegreen7"); + const cyan = PastelSchemaPalette.get("bluegreen5"); + const orange = PastelSchemaPalette.get("orange1"); + const gray = "#f1efeb"; return ( <div className="collectionStackingView-colorPicker"> @@ -243,7 +248,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } renderMenu = () => { - let selected = this._createAliasSelected; + const selected = this._createAliasSelected; return ( <div className="collectionStackingView-optionPicker"> <div className="optionOptions"> @@ -255,23 +260,73 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC @observable private collapsed: boolean = false; - private toggleVisibility = action(() => { - this.collapsed = !this.collapsed; - }); + private toggleVisibility = action(() => this.collapsed = !this.collapsed); @observable _headingsHack: number = 1; + menuCallback = (x: number, y: number) => { + ContextMenu.Instance.clearItems(); + const layoutItems: ContextMenuProps[] = []; + const docItems: ContextMenuProps[] = []; + + const dataDoc = this.props.parent.props.DataDoc || this.props.parent.Document; + Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof (dataDoc[fieldKey]) === "string").map(fieldKey => + docItems.push({ + description: ":" + fieldKey, event: () => { + const created = Docs.Get.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.parent.props.Document)); + if (created) { + if (this.props.parent.Document.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this.props.parent.props.Document); + } + return this.props.parent.props.addDocument(created); + } + }, icon: "compress-arrows-alt" + })); + Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => DocListCast(dataDoc[fieldKey]).length).map(fieldKey => + docItems.push({ + description: ":" + fieldKey, event: () => { + const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey }); + if (created) { + if (this.props.parent.Document.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this.props.parent.props.Document); + } + return this.props.parent.props.addDocument(created); + } + }, icon: "compress-arrows-alt" + })); + layoutItems.push({ description: ":freeform", event: () => this.props.parent.props.addDocument(Docs.Create.FreeformDocument([], { _width: 200, _height: 200, _LODdisable: true })), icon: "compress-arrows-alt" }); + layoutItems.push({ description: ":carousel", event: () => this.props.parent.props.addDocument(Docs.Create.CarouselDocument([], { _width: 400, _height: 200, _LODdisable: true })), icon: "compress-arrows-alt" }); + layoutItems.push({ description: ":columns", event: () => this.props.parent.props.addDocument(Docs.Create.MulticolumnDocument([], { _width: 200, _height: 200 })), icon: "compress-arrows-alt" }); + layoutItems.push({ description: ":image", event: () => this.props.parent.props.addDocument(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { _width: 200, _height: 200 })), icon: "compress-arrows-alt" }); + + ContextMenu.Instance.addItem({ description: "Doc Fields ...", subitems: docItems, icon: "eye" }); + ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" }); + ContextMenu.Instance.setDefaultItem("::", (name: string): void => { + Doc.GetProto(this.props.parent.props.Document)[name] = ""; + const created = Docs.Create.TextDocument("", { title: name, _width: 250, _autoHeight: true }); + if (created) { + if (this.props.parent.Document.isTemplateDoc) { + Doc.MakeMetadataFieldTemplate(created, this.props.parent.props.Document); + } + this.props.parent.props.addDocument(created); + } + }); + const pt = this.props.screenToLocalTransform().inverse().transformPoint(x, y); + ContextMenu.Instance.displayMenu(pt[0], pt[1]); + } + render() { - let cols = this.props.cols(); - let key = StrCast(this.props.parent.props.Document.sectionFilter); + TraceMobx(); + const cols = this.props.cols(); + const key = StrCast(this.props.parent.props.Document.sectionFilter); let templatecols = ""; - let headings = this.props.headings(); - let heading = this._heading; - let style = this.props.parent; - let singleColumn = style.isStackingView; - let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); - let evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; - let headerEditableViewProps = { + const headings = this.props.headings(); + const heading = this._heading; + const style = this.props.parent; + const singleColumn = style.isStackingView; + const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx); + const evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; + const headerEditableViewProps = { GetValue: () => evContents, SetValue: this.headingChanged, contents: evContents, @@ -281,7 +336,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC toggle: this.toggleVisibility, color: this._color }; - let newEditableViewProps = { + const newEditableViewProps = { GetValue: () => "", SetValue: this.addDocument, contents: "+ NEW", @@ -290,12 +345,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC toggle: this.toggleVisibility, color: this._color }; - let headingView = this.props.headingObject ? + const headingView = this.props.headingObject ? <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef} style={{ width: (style.columnWidth) / ((uniqueHeadings.length + - ((this.props.parent.props.Document.chromeStatus !== 'view-mode' && this.props.parent.props.Document.chromeStatus !== 'disabled') ? 1 : 0)) || 1) + ((this.props.parent.props.Document._chromeStatus !== 'view-mode' && this.props.parent.props.Document._chromeStatus !== 'disabled') ? 1 : 0)) || 1) }}> <div className={"collectionStackingView-collapseBar" + (this.props.headingObject.collapsed === true ? " active" : "")} onClick={this.collapseSection}></div> {/* the default bucket (no key value) has a tooltip that describes what it is. @@ -335,7 +390,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC </div> </div> : (null); for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `; - let chromeStatus = this.props.parent.props.Document.chromeStatus; + const chromeStatus = this.props.parent.props.Document._chromeStatus; return ( <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }} ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}> @@ -360,7 +415,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton" style={{ width: style.columnWidth / style.numGroupColumns }}> - <EditableView {...newEditableViewProps} /> + <EditableView {...newEditableViewProps} menuCallback={this.menuCallback} /> </div> : null} </div> } |
