diff options
-rw-r--r-- | src/client/util/DragManager.ts | 30 | ||||
-rw-r--r-- | src/client/views/collections/CollectionViewChromes.tsx | 71 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 11 | ||||
-rw-r--r-- | src/client/views/nodes/ButtonBox.scss | 19 | ||||
-rw-r--r-- | src/client/views/nodes/ButtonBox.tsx | 42 | ||||
-rw-r--r-- | src/new_fields/Doc.ts | 14 |
6 files changed, 111 insertions, 76 deletions
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 24c093213..748fb9d13 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,5 +1,5 @@ import { action, runInAction } from "mobx"; -import { Doc } from "../../new_fields/Doc"; +import { Doc, Field } from "../../new_fields/Doc"; import { Cast, StrCast } from "../../new_fields/Types"; import { URLField } from "../../new_fields/URLField"; import { emptyFunction } from "../../Utils"; @@ -9,6 +9,11 @@ import { DocumentManager } from "./DocumentManager"; import { LinkManager } from "./LinkManager"; import { SelectionManager } from "./SelectionManager"; import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField"; +import { Docs } from "../documents/Documents"; +import { CompileScript } from "./Scripting"; +import { ScriptField } from "../../new_fields/ScriptField"; +import { List } from "../../new_fields/List"; +import { PrefetchProxy } from "../../new_fields/Proxy"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -247,6 +252,27 @@ export namespace DragManager { }); } + export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], downX: number, downY: number, options?: DragOptions) { + let dragData = new DragManager.DocumentDragData([], [undefined]); + runInAction(() => StartDragFunctions.map(func => func())); + StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : + (dropData: { [id: string]: any }) => { + let bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: title }); + let compiled = CompileScript(script, { + params: { doc: Doc.name }, + typecheck: false, + editable: true + }); + if (compiled.compiled) { + let scriptField = new ScriptField(compiled); + bd.onClick = scriptField; + } + params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); + bd.buttonParams = new List<string>(params); + dropData.droppedDocuments = [bd]; + }); + } + export function StartLinkedDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { dragData.moveDocument = moveLinkedDocument; @@ -482,7 +508,7 @@ export namespace DragManager { // if (parent && dragEle) parent.appendChild(dragEle); }); if (target) { - if (finishDrag) finishDrag(dragData); + finishDrag && finishDrag(dragData); target.dispatchEvent( new CustomEvent<DropEvent>("dashOnDrop", { diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 352bcd4a6..15bef39b3 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -286,20 +286,22 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro } } + + commands = [{ + // 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"], + immediate: (draggedDocs: Doc[]) => Doc.GetProto(this.props.CollectionView.props.Document).data = new List<Doc>(draggedDocs) + }, + { + title: "set template", script: "this.target.childLayout = this.source ? this.source[0] : undefined", params: ["target", "source"], + immediate: (draggedDocs: Doc[]) => this.props.CollectionView.props.Document.childLayout = draggedDocs.length ? draggedDocs[0] : undefined + }]; @undoBatch @action protected drop(e: Event, de: DragManager.DropEvent): boolean { - if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.draggedDocuments.length) { - if (this._currentKey === "Set Template") { - this.props.CollectionView.props.Document.childLayout = de.data.draggedDocuments[0]; - } - if (this._currentKey === "Set Content") { - Doc.GetProto(this.props.CollectionView.props.Document).data = new List<Doc>(de.data.draggedDocuments); - } - e.stopPropagation(); - return true; - } + if (de.data instanceof DragManager.DocumentDragData && de.data.draggedDocuments.length) { + this.commands.filter(c => c.title === this._currentKey).map(c => c.immediate(de.data.draggedDocuments)); + e.stopPropagation(); } return true; } @@ -317,9 +319,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro } } } - @observable private _currentKey: string = ""; - @observable _allCommands: string[] = ["Set Template", "Set Content"]; private autosuggestRef = React.createRef<Autosuggest>(); renderSuggestion = (suggestion: string) => { @@ -340,38 +340,19 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro this.suggestions = []; } getKeySuggestions = async (value: string): Promise<string[]> => { - return this._allCommands.filter(c => c.indexOf(value) !== -1); + return this.commands.filter(c => c.title.indexOf(value) !== -1).map(c => c.title); } autoSuggestDown = (e: React.PointerEvent) => { e.stopPropagation(); } + dragCommandDown = (e: React.PointerEvent) => { - let de = new DragManager.DocumentDragData([this.props.CollectionView.props.Document], [undefined]); - DragManager.StartDocumentDrag([this._commandRef.current!], de, e.clientX, e.clientY, { - finishDrag: (dropData: { [id: string]: any }) => { - let bd = Docs.Create.ButtonDocument({ width: 150, height: 50, title: this._currentKey }); - let script = `getProto(target).data = copyField(this.source);`; - let compiled = CompileScript(script, { - params: { doc: Doc.name }, - capturedVariables: { target: this.props.CollectionView.props.Document }, - typecheck: false, - editable: true - }); - if (compiled.compiled) { - let scriptField = new ScriptField(compiled); - bd.onClick = scriptField; - } - dropData.droppedDocuments = [bd]; - }, - handlers: { - dragComplete: action(() => { - }), - }, - hideSource: false - }); - e.preventDefault(); + this.commands.filter(c => c.title === this._currentKey).map(c => + DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title, + { target: this.props.CollectionView.props.Document }, c.params, e.clientX, e.clientY)); e.stopPropagation(); + e.preventDefault(); } render() { @@ -419,7 +400,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro <div className="collectionViewBaseChrome-viewSpecsMenu-row"> <div className="collectionViewBaseChrome-viewSpecsMenu-rowLeft"> CREATED WITHIN: - </div> + </div> <select className="collectionViewBaseChrome-viewSpecsMenu-rowMiddle" style={{ textTransform: "uppercase", textAlign: "center" }} value={this._dateWithinValue} @@ -442,15 +423,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro placeholder="Value" /> </div> <div className="collectionViewBaseChrome-viewSpecsMenu-lastRow"> - <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.addKeyRestriction}> - ADD KEY RESTRICTION - </button> - <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.applyFilter}> - APPLY FILTER - </button> - <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.clearFilter}> - CLEAR - </button> + <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.addKeyRestriction}> ADD KEY RESTRICTION </button> + <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.applyFilter}> APPLY FILTER </button> + <button className="collectonViewBaseChrome-viewSpecsMenu-lastRowButton" onClick={this.clearFilter}> CLEAR </button> </div> </div> </div> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 224e8047d..0a2dcbe3b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -187,8 +187,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { componentDidMount() { this._childLayoutDisposer = reaction(() => [this.childDocs, Cast(this.props.Document.childLayout, Doc)], - async (args) => args[1] instanceof Doc && - this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc), undefined))); + async (args) => { + this.childDocs.filter(doc => args[1] instanceof Doc || doc.layout instanceof Doc).map(async doc => { + if (!Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc)) { + Doc.ApplyTemplateTo(args[1] as Doc, (await doc), undefined); + } + }); + }); } componentWillUnmount() { this._childLayoutDisposer && this._childLayoutDisposer(); @@ -291,7 +296,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (super.drop(e, de)) { if (de.data instanceof DragManager.DocumentDragData) { if (de.data.droppedDocuments.length) { - let z = NumCast(de.data.draggedDocuments[0].z); + let z = NumCast(de.data.droppedDocuments[0].z); let x = (z ? xpo : xp) - de.data.xOffset; let y = (z ? ypo : yp) - de.data.yOffset; let dropX = NumCast(de.data.droppedDocuments[0].x); diff --git a/src/client/views/nodes/ButtonBox.scss b/src/client/views/nodes/ButtonBox.scss index 5ed435505..75a790667 100644 --- a/src/client/views/nodes/ButtonBox.scss +++ b/src/client/views/nodes/ButtonBox.scss @@ -3,14 +3,29 @@ height: 100%; pointer-events: all; border-radius: inherit; - display:table; + display:flex; + flex-direction: column; } .buttonBox-mainButton { width: 100%; height: 100%; border-radius: inherit; + text-align: center; + display: table; +} +.buttonBox-mainButtonCenter { + height: 100%; display:table-cell; vertical-align: middle; - text-align: center; +} + +.buttonBox-params { + display:flex; + flex-direction: row; +} + +.buttonBox-missingParam { + width:100%; + background: lightgray; }
\ No newline at end of file diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index ca5f0acc2..54848344b 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -1,25 +1,19 @@ -import * as React from 'react'; -import { FieldViewProps, FieldView } from './FieldView'; -import { createSchema, makeInterface } from '../../../new_fields/Schema'; -import { ScriptField } from '../../../new_fields/ScriptField'; -import { DocComponent } from '../DocComponent'; -import { ContextMenu } from '../ContextMenu'; import { library } from '@fortawesome/fontawesome-svg-core'; import { faEdit } from '@fortawesome/free-regular-svg-icons'; -import { emptyFunction } from '../../../Utils'; -import { ScriptBox } from '../ScriptBox'; -import { CompileScript } from '../../util/Scripting'; -import { OverlayView } from '../OverlayView'; -import { Doc } from '../../../new_fields/Doc'; - -import './ButtonBox.scss'; +import { action, computed } from 'mobx'; import { observer } from 'mobx-react'; -import { DocumentIconContainer } from './DocumentIcon'; -import { StrCast, BoolCast } from '../../../new_fields/Types'; +import * as React from 'react'; +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; +import { List } from '../../../new_fields/List'; +import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema'; +import { ScriptField } from '../../../new_fields/ScriptField'; +import { BoolCast, StrCast, Cast } from '../../../new_fields/Types'; import { DragManager } from '../../util/DragManager'; import { undoBatch } from '../../util/UndoManager'; -import { action, computed } from 'mobx'; -import { List } from '../../../new_fields/List'; +import { DocComponent } from '../DocComponent'; +import './ButtonBox.scss'; +import { FieldView, FieldViewProps } from './FieldView'; + library.add(faEdit as any); @@ -52,12 +46,24 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt drop = (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.DocumentDragData) { Doc.GetProto(this.dataDoc).source = new List<Doc>(de.data.droppedDocuments); + e.stopPropagation(); } } + // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")") render() { + let params = Cast(this.props.Document.buttonParams, listSpec("string")); + let missingParams = params && params.filter(p => this.props.Document[p] === undefined); + params && params.map(async p => await DocListCastAsync(this.props.Document[p])); // bcz: really hacky form of prefetching ... return ( <div className="buttonBox-outerDiv" ref={this.createDropTarget} > - <div className="buttonBox-mainButton" style={{ background: StrCast(this.props.Document.backgroundColor), color: StrCast(this.props.Document.color, "black") }} >{this.Document.text || this.Document.title}</div> + <div className="buttonBox-mainButton" style={{ background: StrCast(this.props.Document.backgroundColor), color: StrCast(this.props.Document.color, "black") }} > + <div className="buttonBox-mainButtonCenter"> + {(this.Document.text || this.Document.title)} + </div> + </div> + <div className="buttonBox-params" > + {!missingParams || !missingParams.length ? (null) : missingParams.map(m => <div key={m} className="buttonBox-missingParam">{m}</div>)} + </div> </div> ); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index f6114d476..4833ad259 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -525,9 +525,18 @@ export namespace Doc { return otherdoc; } export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetData?: Doc) { + if (!templateDoc) { + target.layout = undefined; + target.nativeWidth = undefined; + target.nativeHeight = undefined; + target.onClick = undefined; + return; + } let temp = Doc.MakeDelegate(templateDoc); target.nativeWidth = Doc.GetProto(target).nativeWidth = undefined; target.nativeHeight = Doc.GetProto(target).nativeHeight = undefined; + !templateDoc.nativeWidth && (target.nativeWidth = 0); + !templateDoc.nativeHeight && (target.nativeHeight = 0); target.width = templateDoc.width; target.height = templateDoc.height; target.onClick = templateDoc.onClick instanceof ObjectField && templateDoc.onClick[Copy](); @@ -541,8 +550,6 @@ export namespace Doc { target.miniLayout = StrCast(templateDoc.miniLayout); target.detailedLayout = target.layout; } - !templateDoc.nativeWidth && (target.nativeWidth = 0); - !templateDoc.nativeHeight && (target.nativeHeight = 0); } export function MakeTemplate(fieldTemplate: Doc, metaKey: string, templateDataDoc: Doc) { @@ -627,4 +634,5 @@ export namespace Doc { } Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(doc.title).replace(/\([0-9]*\)/, "") + `(${n})`; }); Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); }); -Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); });
\ No newline at end of file +Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); +Scripting.addGlobal(function aliasDocs(field: any) { return new List<Doc>(field.map((d: any) => Doc.MakeAlias(d))); });
\ No newline at end of file |