From daeb624194c324600674198ebd9ec758383019d4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 12 Sep 2019 08:46:33 -0400 Subject: added custom views for documents --- src/client/views/collections/CollectionView.tsx | 6 ++-- src/client/views/nodes/DocumentView.tsx | 45 +++++++++++++++++++------ 2 files changed, 38 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 6182e82f4..a17899b8b 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -87,7 +87,8 @@ export class CollectionView extends React.Component { onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - let subItems: ContextMenuProps[] = []; + let existingVm = ContextMenu.Instance.findByDescription("View Modes..."); + let subItems: ContextMenuProps[] = existingVm && "subitems" in existingVm ? existingVm.subitems : []; subItems.push({ description: "Freeform", event: () => { this.props.Document.viewType = CollectionViewType.Freeform; delete this.props.Document.usePivotLayout; }, icon: "signature" }); if (CollectionBaseView.InSafeMode()) { ContextMenu.Instance.addItem({ description: "Test Freeform", event: () => this.props.Document.viewType = CollectionViewType.Invalid, icon: "project-diagram" }); @@ -103,7 +104,8 @@ export class CollectionView extends React.Component { break; } } - ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); + !existingVm && ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" }); + let existing = ContextMenu.Instance.findByDescription("Layout..."); let layoutItems: ContextMenuProps[] = 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" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c2143bb82..6960689b4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -9,7 +9,7 @@ import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; import { ScriptField } from '../../../new_fields/ScriptField'; -import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; +import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { RouteStore } from '../../../server/RouteStore'; import { emptyFunction, returnTrue, Utils } from "../../../Utils"; @@ -444,17 +444,32 @@ export class DocumentView extends DocComponent(Docu this.props.addDocTab(kvp, this.dataDoc, "onRight"); } + @undoBatch + makeNativeViewClicked = (): void => { + this.props.Document.customLayout = this.props.Document.layout; + this.props.Document.layout = this.props.Document.nativeLayout; + this.props.Document.type = this.props.Document.nativeType; + } @undoBatch makeCustomViewClicked = (): void => { - let options = { title: "data", width: NumCast(this.props.Document.width), height: NumCast(this.props.Document.height) + 25, x: -NumCast(this.props.Document.width) / 2, y: -NumCast(this.props.Document.height) / 2, }; - let fieldTemplate = this.props.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) : Docs.Create.ImageDocument("http://www.cs.brown.edu", options); - - let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: StrCast(this.Document.title) + "layout", width: NumCast(this.props.Document.width) + 20, height: Math.max(100, NumCast(this.props.Document.height) + 45) }); - let metaKey = "data"; - let proto = Doc.GetProto(docTemplate); - Doc.MakeTemplate(fieldTemplate, metaKey, proto); - - Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined, false); + this.props.Document.nativeLayout = this.props.Document.layout; + this.props.Document.nativeType = this.props.Document.type; + PromiseValue(this.props.Document.customLayout).then(custom => { + if (custom) { + this.props.Document.type = DocumentType.TEMPLATE; + this.props.Document.layout = custom; + } else { + let options = { title: "data", width: NumCast(this.props.Document.width), height: NumCast(this.props.Document.height) + 25, x: -NumCast(this.props.Document.width) / 2, y: -NumCast(this.props.Document.height) / 2, }; + let fieldTemplate = this.props.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) : Docs.Create.ImageDocument("http://www.cs.brown.edu", options); + + let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: StrCast(this.Document.title) + "layout", width: NumCast(this.props.Document.width) + 20, height: Math.max(100, NumCast(this.props.Document.height) + 45) }); + let metaKey = "data"; + let proto = Doc.GetProto(docTemplate); + Doc.MakeTemplate(fieldTemplate, metaKey, proto); + + Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined, false); + } + }); } @undoBatch @@ -630,10 +645,18 @@ export class DocumentView extends DocComponent(Docu subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); + let existingVm = ContextMenu.Instance.findByDescription("View Modes..."); + let vms: ContextMenuProps[] = existingVm && "subitems" in existingVm ? existingVm.subitems : []; + if (this.props.Document.type !== DocumentType.COL && this.props.Document.type !== DocumentType.TEMPLATE) { + vms.push({ description: "Custom Document View", event: this.makeCustomViewClicked, icon: "concierge-bell" }); + } else if (this.props.Document.nativeLayout) { + vms.push({ description: "Native Document View", event: this.makeNativeViewClicked, icon: "concierge-bell" }); + } + !existingVm && cm.addItem({ description: "View Modes...", subitems: vms, icon: "eye" }); + let existingMake = ContextMenu.Instance.findByDescription("Make..."); let makes: ContextMenuProps[] = existingMake && "subitems" in existingMake ? existingMake.subitems : []; makes.push({ description: this.props.Document.isBackground ? "Remove Background" : "Into Background", event: this.makeBackground, icon: this.props.Document.lockedPosition ? "unlock" : "lock" }); - makes.push({ description: "Custom Document View", event: this.makeCustomViewClicked, icon: "concierge-bell" }); makes.push({ description: "Metadata Field View", event: () => this.props.ContainingCollectionView && Doc.MakeTemplate(this.props.Document, StrCast(this.props.Document.title), this.props.ContainingCollectionView.props.Document), icon: "concierge-bell" }) makes.push({ description: "Into Portal", event: this.makeIntoPortal, icon: "window-restore" }); makes.push({ description: this.layoutDoc.ignoreClick ? "Selectable" : "Unselectable", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" }); -- cgit v1.2.3-70-g09d2 From 91480dbd1b734795f514281ee0a2dac2442d6e84 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 12 Sep 2019 11:06:23 -0400 Subject: cleaned up menus. simplified making custom views through template dropdown menu --- src/client/views/ContextMenu.scss | 4 +- src/client/views/ContextMenuItem.tsx | 4 +- src/client/views/DocumentDecorations.scss | 2 +- src/client/views/DocumentDecorations.tsx | 18 +----- src/client/views/TemplateMenu.tsx | 70 ++++++++++++---------- src/client/views/Templates.tsx | 38 +----------- src/client/views/collections/CollectionView.tsx | 5 -- .../collectionFreeForm/CollectionFreeFormView.tsx | 44 +++++++------- src/client/views/nodes/DocumentView.tsx | 59 ++++-------------- src/client/views/nodes/ImageBox.tsx | 5 +- src/client/views/nodes/KeyValueBox.tsx | 27 ++++----- 11 files changed, 96 insertions(+), 180 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index e2c0de8af..8f112de0c 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -124,7 +124,9 @@ } .icon-background { - pointer-events: none; + pointer-events: all; + height:100%; + margin-top: 15px; background-color: transparent; width: 35px; text-align: center; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 5f673b3f3..330b94afa 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -93,9 +93,9 @@ export class ContextMenuItem extends React.Component )} ; return ( -
+
{this.props.icon ? ( - + ) : null} diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index ac8497bd0..4ab5d733f 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -257,7 +257,7 @@ $linkGap : 3px; padding: 2px 12px; list-style: none; - .templateToggle { + .templateToggle, .chromeToggle { text-align: left; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 814d718be..6451fdf5e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -849,24 +849,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let templates: Map = new Map(); Array.from(Object.values(Templates.TemplateList)).map(template => { - let sorted = SelectionManager.ViewsSortedVertically(); - let docTemps = sorted.reduce((res: string[], doc: DocumentView, i) => { - let temps = doc.props.Document.templates; - if (temps instanceof List) { - temps.map(temp => { - if (temp !== Templates.Bullet.Layout || i === 0) { - res.push(temp); - } - }); - } - return res; - }, [] as string[]); let checked = false; - docTemps.forEach(temp => { - if (template.Layout === temp) { - checked = true; - } - }); + SelectionManager.SelectedDocuments().map(doc => checked = checked || (doc.props.Document["show" + template.Name] !== undefined)); templates.set(template, checked); }); diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 393e97a7e..0586b31e4 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -1,16 +1,14 @@ import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../new_fields/Doc"; -import { List } from "../../new_fields/List"; -import './DocumentDecorations.scss'; -import { DocumentView } from "./nodes/DocumentView"; -import { Template } from "./Templates"; -import React = require("react"); -import { undoBatch } from "../util/UndoManager"; +import { DocumentType } from "../documents/DocumentTypes"; import { DocumentManager } from "../util/DocumentManager"; -import { NumCast } from "../../new_fields/Types"; import { DragManager } from "../util/DragManager"; import { SelectionManager } from "../util/SelectionManager"; +import { undoBatch } from "../util/UndoManager"; +import './DocumentDecorations.scss'; +import { DocumentView } from "./nodes/DocumentView"; +import { Template, Templates } from "./Templates"; +import React = require("react"); const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -30,6 +28,17 @@ class TemplateToggle extends React.Component<{ template: Template, checked: bool } } } +@observer +class ChromeToggle extends React.Component<{ checked: boolean, toggle: (event: React.ChangeEvent) => void }> { + render() { + return ( +
  • + this.props.toggle(event)} /> + Chrome +
  • + ); + } +} export interface TemplateMenuProps { docs: DocumentView[]; @@ -45,6 +54,16 @@ export class TemplateMenu extends React.Component { super(props); } + toggleCustom = (e: React.MouseEvent): void => { + this.props.docs.map(dv => { + if (dv.Document.type !== DocumentType.COL && dv.Document.type !== DocumentType.TEMPLATE) { + dv.makeCustomViewClicked(); + } else if (dv.Document.nativeLayout) { + dv.makeNativeViewClicked(); + } + }); + } + toggleFloat = (e: React.MouseEvent): void => { SelectionManager.DeselectAll(); let topDocView = this.props.docs[0]; @@ -80,55 +99,42 @@ export class TemplateMenu extends React.Component { @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { if (event.target.checked) { - if (template.Name === "Bullet") { - let topDocView = this.props.docs[0]; - topDocView.addTemplate(template); - topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document)); - } else { - this.props.docs.map(d => d.addTemplate(template)); - } - this.props.templates.set(template, true); + this.props.docs.map(d => d.props.Document["show" + template.Name] = template.Name.toLowerCase()); } else { - if (template.Name === "Bullet") { - let topDocView = this.props.docs[0]; - topDocView.removeTemplate(template); - topDocView.props.Document.subBulletDocs = undefined; - } else { - this.props.docs.map(d => d.removeTemplate(template)); - } - this.props.templates.set(template, false); + this.props.docs.map(d => d.props.Document["show" + template.Name] = undefined); } } @undoBatch @action clearTemplates = (event: React.MouseEvent) => { - this.props.docs.map(d => d.clearTemplates()); - Array.from(this.props.templates.keys()).map(t => this.props.templates.set(t, false)); + Templates.TemplateList.map(template => this.props.docs.map(d => d.props.Document["show" + template.Name] = false)); } @action - componentWillReceiveProps(nextProps: TemplateMenuProps) { - // this._templates = nextProps.templates; + toggleTemplateActivity = (): void => { + this._hidden = !this._hidden; } + @undoBatch @action - toggleTemplateActivity = (): void => { - this._hidden = !this._hidden; + toggleChrome = (): void => { + this.props.docs.map(dv => dv.layoutDoc.chromeStatus = (dv.layoutDoc.chromeStatus !== "disabled" ? "disabled" : "enabled")); } render() { let templateMenu: Array = []; this.props.templates.forEach((checked, template) => templateMenu.push()); - + templateMenu.push(); return (
    this.toggleTemplateActivity()}>+
      {templateMenu} + - + {/* */}
    ); diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 236704fa2..ef78b60d4 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -57,43 +57,7 @@ export namespace Templates {
    ` ); - export const Header = new Template("Header", TemplatePosition.InnerTop, - `
    -
    - -
    -
    {layout}
    -
    ` ); - - export const Bullet = new Template("Bullet", TemplatePosition.InnerTop, - `< div > -
    {layout}
    -
    - -
    - ` - ); - - export function ImageOverlay(width: number, height: number, field: string = "thumbnail") { - return (`< div > -
    {layout}
    -
    - -
    - `); - } - - export function TitleBar(datastring: string) { - return (`
    -
    - ${datastring} -
    -
    -
    {layout}
    -
    -
    ` ); - } - export const TemplateList: Template[] = [Title, Header, Caption, Bullet]; + export const TemplateList: Template[] = [Title, Caption]; export function sortTemplates(a: Template, b: Template) { if (a.Position < b.Position) { return -1; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a17899b8b..9caa4ea37 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -110,11 +110,6 @@ export class CollectionView extends React.Component { let layoutItems: ContextMenuProps[] = 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" }); !existing && ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "hand-point-right" }); - - let makes = ContextMenu.Instance.findByDescription("Make..."); - let makeItems: ContextMenuProps[] = makes && "subitems" in makes ? makes.subitems : []; - makeItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); - !makes && ContextMenu.Instance.addItem({ description: "Make...", subitems: makeItems, icon: "hand-point-right" }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2591bdd8d..24be5963f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -894,6 +894,30 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { onContextMenu = (e: React.MouseEvent) => { let layoutItems: ContextMenuProps[] = []; + + if (this.childDocs.some(d => d.isTemplate)) { + layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab && 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.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); + layoutItems.push({ + description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`, + event: async () => { + Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; // backward compatibility with databases that didn't have a default background color on prototypes + Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white"; + this.props.Document.useClusters = !this.props.Document.useClusters; + this.updateClusters(); + }, + icon: !this.props.Document.useClusters ? "braille" : "braille" + }); + this.props.Document.useClusters && layoutItems.push({ + description: `${this.props.Document.clusterOverridesDefaultBackground ? "Use Default Backgrounds" : "Clusters Override Defaults"}`, + event: async () => this.props.Document.clusterOverridesDefaultBackground = !this.props.Document.clusterOverridesDefaultBackground, + icon: !this.props.Document.useClusters ? "chalkboard" : "chalkboard" + }); + layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" }); + layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" }); + layoutItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = 10), icon: "paint-brush" }); layoutItems.push({ description: "Import document", icon: "upload", event: () => { const input = document.createElement("input"); @@ -924,26 +948,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { input.click(); } }); - layoutItems.push({ description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`, event: this.fitToContainer, icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt" }); - 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.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`, - event: async () => { - Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb"; // backward compatibility with databases that didn't have a default background color on prototypes - Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white"; - this.props.Document.useClusters = !this.props.Document.useClusters; - this.updateClusters(); - }, - icon: !this.props.Document.useClusters ? "braille" : "braille" - }); - layoutItems.push({ - description: `${this.props.Document.clusterOverridesDefaultBackground ? "Use Default Backgrounds" : "Clusters Override Defaults"}`, - event: async () => this.props.Document.clusterOverridesDefaultBackground = !this.props.Document.clusterOverridesDefaultBackground, - icon: !this.props.Document.useClusters ? "chalkboard" : "chalkboard" - }); - layoutItems.push({ description: "Arrange contents in grid", event: this.arrangeContents, icon: "table" }); - layoutItems.push({ description: "Analyze Strokes", event: this.analyzeStrokes, icon: "paint-brush" }); - layoutItems.push({ description: "Jitter Rotation", event: action(() => this.props.Document.jitterRotation = 10), icon: "paint-brush" }); let noteItems: ContextMenuProps[] = []; let notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6960689b4..2d17c09e5 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -147,14 +147,6 @@ export class DocumentView extends DocComponent(Docu public get ContentDiv() { return this._mainCont.current; } @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); } @computed get topMost(): boolean { return this.props.renderDepth === 0; } - @computed get templates(): List { - let field = this.props.Document.templates; - if (field && field instanceof List) { - return field; - } - return new List(); - } - set templates(templates: List) { this.props.Document.templates = templates; } screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect(); @action @@ -449,6 +441,7 @@ export class DocumentView extends DocComponent(Docu this.props.Document.customLayout = this.props.Document.layout; this.props.Document.layout = this.props.Document.nativeLayout; this.props.Document.type = this.props.Document.nativeType; + this.props.Document.nativeLayout = undefined; } @undoBatch makeCustomViewClicked = (): void => { @@ -553,28 +546,6 @@ export class DocumentView extends DocComponent(Docu } } - @action - addTemplate = (template: Template) => { - this.templates.push(template.Layout); - this.templates = this.templates; - } - - @action - removeTemplate = (template: Template) => { - for (let i = 0; i < this.templates.length; i++) { - if (this.templates[i] === template.Layout) { - this.templates.splice(i, 1); - break; - } - } - this.templates = this.templates; - } - @action - clearTemplates = () => { - this.templates.length = 0; - this.templates = this.templates; - } - @undoBatch @action freezeNativeDimensions = (): void => { @@ -645,25 +616,11 @@ export class DocumentView extends DocComponent(Docu subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); - let existingVm = ContextMenu.Instance.findByDescription("View Modes..."); - let vms: ContextMenuProps[] = existingVm && "subitems" in existingVm ? existingVm.subitems : []; - if (this.props.Document.type !== DocumentType.COL && this.props.Document.type !== DocumentType.TEMPLATE) { - vms.push({ description: "Custom Document View", event: this.makeCustomViewClicked, icon: "concierge-bell" }); - } else if (this.props.Document.nativeLayout) { - vms.push({ description: "Native Document View", event: this.makeNativeViewClicked, icon: "concierge-bell" }); - } - !existingVm && cm.addItem({ description: "View Modes...", subitems: vms, icon: "eye" }); - - let existingMake = ContextMenu.Instance.findByDescription("Make..."); - let makes: ContextMenuProps[] = existingMake && "subitems" in existingMake ? existingMake.subitems : []; - makes.push({ description: this.props.Document.isBackground ? "Remove Background" : "Into Background", event: this.makeBackground, icon: this.props.Document.lockedPosition ? "unlock" : "lock" }); - makes.push({ description: "Metadata Field View", event: () => this.props.ContainingCollectionView && Doc.MakeTemplate(this.props.Document, StrCast(this.props.Document.title), this.props.ContainingCollectionView.props.Document), icon: "concierge-bell" }) - makes.push({ description: "Into Portal", event: this.makeIntoPortal, icon: "window-restore" }); - makes.push({ description: this.layoutDoc.ignoreClick ? "Selectable" : "Unselectable", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" }); - !existingMake && cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" }); let existingOnClick = ContextMenu.Instance.findByDescription("OnClick..."); let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : []; + onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); + onClicks.push({ description: this.layoutDoc.ignoreClick ? "Select" : "Do Nothing", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" }); onClicks.push({ description: this.props.Document.isButton || this.props.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.makeBtnClicked, icon: "concierge-bell" }); onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) }); onClicks.push({ @@ -676,6 +633,10 @@ export class DocumentView extends DocComponent(Docu let existing = ContextMenu.Instance.findByDescription("Layout..."); let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; + layoutItems.push({ description: this.props.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.props.Document.lockedPosition ? "unlock" : "lock" }); + if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.layout instanceof Doc) { + layoutItems.push({ description: "Make View of Metadata Field", event: () => this.props.ContainingCollectionView && Doc.MakeTemplate(this.props.Document, StrCast(this.props.Document.title), this.props.ContainingCollectionView.props.Document), icon: "concierge-bell" }) + } layoutItems.push({ description: `${this.layoutDoc.chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.layoutDoc.chromeStatus = (this.layoutDoc.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" }); layoutItems.push({ description: `${this.layoutDoc.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc.autoHeight = !this.layoutDoc.autoHeight, icon: "plus" }); layoutItems.push({ description: this.props.Document.ignoreAspect || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" }); @@ -685,6 +646,11 @@ export class DocumentView extends DocComponent(Docu if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) { layoutItems.push({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } + if (this.props.Document.type !== DocumentType.COL && this.props.Document.type !== DocumentType.TEMPLATE) { + layoutItems.push({ description: "Use Custom Layout", event: this.makeCustomViewClicked, icon: "concierge-bell" }); + } else if (this.props.Document.nativeLayout) { + layoutItems.push({ description: "Use Native Layout", event: this.makeNativeViewClicked, icon: "concierge-bell" }); + } !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" }); if (!ClientUtils.RELEASE) { let copies: ContextMenuProps[] = []; @@ -698,7 +664,6 @@ export class DocumentView extends DocComponent(Docu !existingAnalyze && cm.addItem({ description: "Analyzers...", subitems: analyzers, icon: "hand-point-right" }); cm.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin" }); //I think this should work... and it does! A miracle! cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) }); - cm.addItem({ description: "Move To Overlay", icon: "laptop-code", event: () => ((o: Doc) => o && Doc.AddDocToList(o, "data", this.props.Document))(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc) }); cm.addItem({ description: "Download document", icon: "download", event: async () => { let y = JSON.parse(await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6fc94a140..19788c21a 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -216,12 +216,13 @@ export class ImageBox extends DocComponent(ImageD funcs.push({ description: "Record 1sec audio", event: this.recordAudioAnnotation, icon: "expand-arrows-alt" }); funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" }); - let modes: ContextMenuProps[] = []; + let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers..."); + let modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : []; modes.push({ description: "Generate Tags", event: this.generateMetadata, icon: "tag" }); modes.push({ description: "Find Faces", event: this.extractFaces, icon: "camera" }); + !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: modes, icon: "hand-point-right" }) ContextMenu.Instance.addItem({ description: "Image Funcs...", subitems: funcs, icon: "asterisk" }); - ContextMenu.Instance.addItem({ description: "Analyze...", subitems: modes, icon: "eye" }); } } diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 653c5c27f..f80f414b1 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -2,26 +2,21 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { CompileScript, ScriptOptions, CompiledScript } from "../../util/Scripting"; -import { FieldView, FieldViewProps } from './FieldView'; -import "./KeyValueBox.scss"; -import { KeyValuePair } from "./KeyValuePair"; -import React = require("react"); -import { NumCast, Cast, FieldValue, StrCast } from "../../../new_fields/Types"; -import { Doc, Field, FieldResult, DocListCastAsync } from "../../../new_fields/Doc"; -import { ComputedField, ScriptField } from "../../../new_fields/ScriptField"; -import { SetupDrag } from "../../util/DragManager"; -import { Docs } from "../../documents/Documents"; -import { RawDataOperationParameters } from "../../northstar/model/idea/idea"; -import { Templates } from "../Templates"; +import { Doc, Field, FieldResult } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; -import { TextField } from "../../util/ProsemirrorCopy/prompt"; import { RichTextField } from "../../../new_fields/RichTextField"; -import { ImageField } from "../../../new_fields/URLField"; -import { SelectionManager } from "../../util/SelectionManager"; import { listSpec } from "../../../new_fields/Schema"; -import { CollectionViewType } from "../collections/CollectionBaseView"; +import { ComputedField, ScriptField } from "../../../new_fields/ScriptField"; +import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { ImageField } from "../../../new_fields/URLField"; +import { Docs } from "../../documents/Documents"; +import { SetupDrag } from "../../util/DragManager"; +import { CompiledScript, CompileScript, ScriptOptions } from "../../util/Scripting"; import { undoBatch } from "../../util/UndoManager"; +import { FieldView, FieldViewProps } from './FieldView'; +import "./KeyValueBox.scss"; +import { KeyValuePair } from "./KeyValuePair"; +import React = require("react"); export type KVPScript = { script: CompiledScript; -- cgit v1.2.3-70-g09d2