From 99ffc8ec1508f05dfb126318b1215a3ee597738f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 7 Jun 2019 18:30:48 -0400 Subject: Fixed some schema stuff? Tests aren't running --- src/fields/ScriptField.ts | 28 ++++++++++++---------------- src/new_fields/Schema.ts | 8 +++++--- src/new_fields/util.ts | 8 ++++---- 3 files changed, 21 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index ac46ccf90..d4fed1a1d 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -26,32 +26,28 @@ const optionsSchema = createSimpleSchema({ params: optional(map(primitive())) }); +const scriptSchema = createSimpleSchema({ + options: object(optionsSchema), + originalScript: true +}); + function deserializeScript(script: ScriptField) { - const comp = CompileScript(script.scriptString, script.options); + const comp = CompileScript(script.script.originalScript, script.script.options); if (!comp.compiled) { throw new Error("Couldn't compile loaded script"); } - (script as any)._script = comp; + (script as any).script = comp; } @Deserializable("script", deserializeScript) export class ScriptField extends ObjectField { - protected readonly _script: CompiledScript; + @serializable(object(scriptSchema)) + readonly script: CompiledScript; constructor(script: CompiledScript) { super(); - this._script = script; - } - - @serializable(custom(object(optionsSchema).serializer, () => SKIP)) - get options() { - return this._script && this._script.options; - } - - @serializable(custom(primitive().serializer, () => SKIP)) - get scriptString(): string { - return this._script && this._script.originalScript; + this.script = script; } // init(callback: (res: Field) => any) { @@ -76,7 +72,7 @@ export class ScriptField extends ObjectField { // } [Copy](): ObjectField { - return new ScriptField(this._script); + return new ScriptField(this.script); } [ToScriptString]() { @@ -88,7 +84,7 @@ export class ScriptField extends ObjectField { export class ComputedField extends ScriptField { @computed get value() { - const val = this._script.run({ this: (this[Parent] as any)[SelfProxy] }); + const val = this.script.run({ this: (this[Parent] as any)[SelfProxy] }); if (val.success) { return val.result; } diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index 40ffaecd5..2355304d5 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -2,6 +2,7 @@ import { Interface, ToInterface, Cast, ToConstructor, HasTail, Head, Tail, ListS import { Doc, Field } from "./Doc"; import { ObjectField } from "./ObjectField"; import { RefField } from "./RefField"; +import { SelfProxy } from "./FieldSymbols"; type AllToInterface = { 1: ToInterface> & AllToInterface>, @@ -56,9 +57,10 @@ export function makeInterface(...schemas: T): InterfaceFu } }); const fn = (doc: Doc) => { - if (!(doc instanceof Doc)) { - throw new Error("Currently wrapping a schema in another schema isn't supported"); - } + doc = doc[SelfProxy]; + // if (!(doc instanceof Doc)) { + // throw new Error("Currently wrapping a schema in another schema isn't supported"); + // } const obj = Object.create(proto, { doc: { value: doc, writable: false } }); return obj; }; diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index ad07d05a3..d9c2a9866 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -6,7 +6,7 @@ import { FieldValue } from "./Types"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action } from "mobx"; -import { Parent, OnUpdate, Update, Id } from "./FieldSymbols"; +import { Parent, OnUpdate, Update, Id, SelfProxy } from "./FieldSymbols"; import { ComputedField } from "../fields/ScriptField"; export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { @@ -18,6 +18,7 @@ export const setter = action(function (target: any, prop: string | symbol | numb target[prop] = value; return true; } + value = value[SelfProxy] || value; const curValue = target.__fields[prop]; if (curValue === value || (curValue instanceof ProxyField && value instanceof RefField && curValue.fieldId === value[Id])) { // TODO This kind of checks correctly in the case that curValue is a ProxyField and value is a RefField, but technically @@ -28,11 +29,10 @@ export const setter = action(function (target: any, prop: string | symbol | numb value = new ProxyField(value); } if (value instanceof ObjectField) { - //TODO Instead of target, maybe use target[Self] - if (value[Parent] && value[Parent] !== target) { + if (value[Parent] && value[Parent] !== receiver) { throw new Error("Can't put the same object in multiple documents at the same time"); } - value[Parent] = target; + value[Parent] = receiver; value[OnUpdate] = updateFunction(target, prop, value, receiver); } if (curValue instanceof ObjectField) { -- cgit v1.2.3-70-g09d2 From 6abf829099e4f61f2f557078f645fb9f2aa2414c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 8 Jun 2019 22:58:23 -0400 Subject: Moved ScriptField to new_fields --- src/client/util/Scripting.ts | 2 +- src/fields/ScriptField.ts | 93 ------------------------------------------- src/new_fields/ScriptField.ts | 93 +++++++++++++++++++++++++++++++++++++++++++ src/new_fields/util.ts | 2 +- 4 files changed, 95 insertions(+), 95 deletions(-) delete mode 100644 src/fields/ScriptField.ts create mode 100644 src/new_fields/ScriptField.ts (limited to 'src') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 40e2ad6bb..688716d5f 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -12,7 +12,7 @@ import { Doc, Field } from '../../new_fields/Doc'; import { ImageField, PdfField, VideoField, AudioField } from '../../new_fields/URLField'; import { List } from '../../new_fields/List'; import { RichTextField } from '../../new_fields/RichTextField'; -import { ScriptField, ComputedField } from '../../fields/ScriptField'; +import { ScriptField, ComputedField } from '../../new_fields/ScriptField'; export interface ScriptSucccess { success: true; diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts deleted file mode 100644 index d4fed1a1d..000000000 --- a/src/fields/ScriptField.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { ObjectField } from "../new_fields/ObjectField"; -import { CompiledScript, CompileScript } from "../client/util/Scripting"; -import { Copy, ToScriptString, Parent, SelfProxy } from "../new_fields/FieldSymbols"; -import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; -import { Deserializable } from "../client/util/SerializationHelper"; -import { computed } from "mobx"; - -function optional(propSchema: PropSchema) { - return custom(value => { - if (value !== undefined) { - return propSchema.serializer(value); - } - return SKIP; - }, (jsonValue: any, context: any, oldValue: any, callback: (err: any, result: any) => void) => { - if (jsonValue !== undefined) { - return propSchema.deserializer(jsonValue, callback, context, oldValue); - } - return SKIP; - }); -} - -const optionsSchema = createSimpleSchema({ - requiredType: true, - addReturn: true, - typecheck: true, - params: optional(map(primitive())) -}); - -const scriptSchema = createSimpleSchema({ - options: object(optionsSchema), - originalScript: true -}); - -function deserializeScript(script: ScriptField) { - const comp = CompileScript(script.script.originalScript, script.script.options); - if (!comp.compiled) { - throw new Error("Couldn't compile loaded script"); - } - (script as any).script = comp; -} - -@Deserializable("script", deserializeScript) -export class ScriptField extends ObjectField { - @serializable(object(scriptSchema)) - readonly script: CompiledScript; - - constructor(script: CompiledScript) { - super(); - - this.script = script; - } - - // init(callback: (res: Field) => any) { - // const options = this.options!; - // const keys = Object.keys(options.options.capturedIds); - // Server.GetFields(keys).then(fields => { - // let captured: { [name: string]: Field } = {}; - // keys.forEach(key => captured[options.options.capturedIds[key]] = fields[key]); - // const opts: ScriptOptions = { - // addReturn: options.options.addReturn, - // params: options.options.params, - // requiredType: options.options.requiredType, - // capturedVariables: captured - // }; - // const script = CompileScript(options.script, opts); - // if (!script.compiled) { - // throw new Error("Can't compile script"); - // } - // this._script = script; - // callback(this); - // }); - // } - - [Copy](): ObjectField { - return new ScriptField(this.script); - } - - [ToScriptString]() { - return "script field"; - } -} - -@Deserializable("computed", deserializeScript) -export class ComputedField extends ScriptField { - @computed - get value() { - const val = this.script.run({ this: (this[Parent] as any)[SelfProxy] }); - if (val.success) { - return val.result; - } - return undefined; - } -} \ No newline at end of file diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts new file mode 100644 index 000000000..0839a823d --- /dev/null +++ b/src/new_fields/ScriptField.ts @@ -0,0 +1,93 @@ +import { ObjectField } from "./ObjectField"; +import { CompiledScript, CompileScript } from "../client/util/Scripting"; +import { Copy, ToScriptString, Parent, SelfProxy } from "./FieldSymbols"; +import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; +import { Deserializable } from "../client/util/SerializationHelper"; +import { computed } from "mobx"; + +function optional(propSchema: PropSchema) { + return custom(value => { + if (value !== undefined) { + return propSchema.serializer(value); + } + return SKIP; + }, (jsonValue: any, context: any, oldValue: any, callback: (err: any, result: any) => void) => { + if (jsonValue !== undefined) { + return propSchema.deserializer(jsonValue, callback, context, oldValue); + } + return SKIP; + }); +} + +const optionsSchema = createSimpleSchema({ + requiredType: true, + addReturn: true, + typecheck: true, + params: optional(map(primitive())) +}); + +const scriptSchema = createSimpleSchema({ + options: object(optionsSchema), + originalScript: true +}); + +function deserializeScript(script: ScriptField) { + const comp = CompileScript(script.script.originalScript, script.script.options); + if (!comp.compiled) { + throw new Error("Couldn't compile loaded script"); + } + (script as any).script = comp; +} + +@Deserializable("script", deserializeScript) +export class ScriptField extends ObjectField { + @serializable(object(scriptSchema)) + readonly script: CompiledScript; + + constructor(script: CompiledScript) { + super(); + + this.script = script; + } + + // init(callback: (res: Field) => any) { + // const options = this.options!; + // const keys = Object.keys(options.options.capturedIds); + // Server.GetFields(keys).then(fields => { + // let captured: { [name: string]: Field } = {}; + // keys.forEach(key => captured[options.options.capturedIds[key]] = fields[key]); + // const opts: ScriptOptions = { + // addReturn: options.options.addReturn, + // params: options.options.params, + // requiredType: options.options.requiredType, + // capturedVariables: captured + // }; + // const script = CompileScript(options.script, opts); + // if (!script.compiled) { + // throw new Error("Can't compile script"); + // } + // this._script = script; + // callback(this); + // }); + // } + + [Copy](): ObjectField { + return new ScriptField(this.script); + } + + [ToScriptString]() { + return "script field"; + } +} + +@Deserializable("computed", deserializeScript) +export class ComputedField extends ScriptField { + @computed + get value() { + const val = this.script.run({ this: this[Parent] }); + if (val.success) { + return val.result; + } + return undefined; + } +} \ No newline at end of file diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index d9c2a9866..a37abb732 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -7,7 +7,7 @@ import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action } from "mobx"; import { Parent, OnUpdate, Update, Id, SelfProxy } from "./FieldSymbols"; -import { ComputedField } from "../fields/ScriptField"; +import { ComputedField } from "./ScriptField"; export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { if (SerializationHelper.IsSerializing()) { -- cgit v1.2.3-70-g09d2 From af8e5cf1bfbfa2d57b4fd89c72306a71d8cabe1d Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 20 Jun 2019 11:32:54 -0400 Subject: Fixed context menu search --- src/client/views/ContextMenu.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index fd2f970da..69692dbb8 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -167,17 +167,22 @@ export class ContextMenu extends React.Component { console.log(this.pageX); console.log(); + const contents = ( + <> + + + + + + + {this.menuItems} + + ); return ( { this._width = r.offset.width; this._height = r.offset.height; })}> {({ measureRef }) => (
- - - - - - - {this.menuItems} + {contents}
) } -- cgit v1.2.3-70-g09d2 From 1f24c5010a1cf6365265ea1f02327bb81a98134a Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 20 Jun 2019 14:54:55 -0400 Subject: Doc.GetProto change and swapped KVP syntax --- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 3 ++- src/new_fields/Doc.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 917be734d..3d626eef0 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -54,7 +54,7 @@ export class KeyValueBox extends React.Component { field = res.result; } if (Field.IsField(field, true)) { - let target = !eq ? doc : Doc.GetProto(doc); + let target = eq ? doc : Doc.GetProto(doc); target[key] = field; return true; } diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index dd1bca7f6..420a1ad94 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -61,10 +61,11 @@ export class KeyValuePair extends React.Component { { + const onDelegate = Object.keys(props.Document).includes(props.fieldKey); let field = FieldValue(props.Document[props.fieldKey]); if (Field.IsField(field)) { - return Field.toScriptString(field); + return (onDelegate ? "=" : "") + Field.toScriptString(field); } return ""; }} diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1b0ff812f..de4bc4d5d 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -207,7 +207,7 @@ export namespace Doc { // gets the document's prototype or returns the document if it is a prototype export function GetProto(doc: Doc) { - return Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : doc.proto!; + return Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc); } export function allKeys(doc: Doc): string[] { -- cgit v1.2.3-70-g09d2 From 9b3e80def0be6c09c31b5176817a54323d217d81 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 20 Jun 2019 15:06:41 -0400 Subject: Handled more events in editable view --- src/client/views/EditableView.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 0f6281b5c..97a2d19dd 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -72,10 +72,14 @@ export class EditableView extends React.Component { e.stopPropagation(); } + stopPropagation(e: React.SyntheticEvent) { + e.stopPropagation(); + } + render() { if (this._editing) { return this._editing = false)} + onBlur={action(() => this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} style={{ display: this.props.display }} />; } else { return ( -- cgit v1.2.3-70-g09d2 From a5dc0e04add05f2f5bf1e17f1ac0a5e0aba1ea41 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 20 Jun 2019 16:27:44 -0400 Subject: Added hidden flag to documents --- src/client/views/nodes/DocumentView.tsx | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index acd5e4cf2..280804630 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -89,6 +89,7 @@ const schema = createSchema({ nativeWidth: "number", nativeHeight: "number", backgroundColor: "string", + hidden: "boolean" }); export const positionSchema = createSchema({ @@ -538,6 +539,9 @@ export class DocumentView extends DocComponent(Docu } render() { + if (this.Document.hidden) { + return null; + } var scaling = this.props.ContentScaling(); var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; -- cgit v1.2.3-70-g09d2 From a39b2854b848006c19460685d7bf4005a9f650ae Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 20 Jun 2019 17:09:50 -0400 Subject: moved AddDocToList to Doc utils --- src/client/views/collections/CollectionTreeView.tsx | 18 ++++-------------- src/new_fields/Doc.ts | 10 ++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c51c16883..443c763bf 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -251,16 +251,6 @@ class TreeView extends React.Component { return false; } - public static AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean) { - let list = Cast(target[key], listSpec(Doc)); - if (list) { - let ind = relativeTo ? list.indexOf(relativeTo) : -1; - if (ind === -1) list.push(doc); - else list.splice(before ? ind : ind + 1, 0, doc); - } - return true; - } - docTransform = () => { let { scale, translateX, translateY } = Utils.GetScreenTransform(this._dref.current!); let outerXf = this.props.outerXf(); @@ -273,7 +263,7 @@ class TreeView extends React.Component { let contentElement: (JSX.Element | null) = null; let docList = Cast(this.props.document[this._chosenKey], listSpec(Doc)); let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey); - let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before); + let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => Doc.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before); let doc = Cast(this.props.document[this._chosenKey], Doc); let docWidth = () => NumCast(this.props.document.nativeWidth) ? Math.min(this.props.document[WidthSym](), this.props.panelWidth() - 5) : this.props.panelWidth() - 5; if (!this._collapsed) { @@ -334,7 +324,7 @@ class TreeView extends React.Component { if (StrCast(docList[i - 1].layout).indexOf("CollectionView") !== -1) { let fieldKeysub = StrCast(docList[i - 1].layout).split("fieldKey")[1]; let fieldKey = fieldKeysub.split("\"")[1]; - TreeView.AddDocToList(docList[i - 1], fieldKey, child); + Doc.AddDocToList(docList[i - 1], fieldKey, child); remove(child); } } @@ -403,7 +393,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { render() { let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; - let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); + let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); return !this.childDocs ? (null) : ( @@ -423,7 +413,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { Doc.GetProto(this.props.Document).title = value; let doc = Docs.FreeformDocument([], { title: "", x: 0, y: 0, width: 100, height: 25, templates: new List([Templates.Title.Layout]) }); TreeView.loadId = doc[Id]; - TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true); + Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true); }} />
    diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1b0ff812f..7bae7a02d 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -222,6 +222,16 @@ export namespace Doc { return Array.from(results); } + export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean) { + let list = Cast(target[key], listSpec(Doc)); + if (list) { + let ind = relativeTo ? list.indexOf(relativeTo) : -1; + if (ind === -1) list.push(doc); + else list.splice(before ? ind : ind + 1, 0, doc); + } + return true; + } + export function MakeAlias(doc: Doc) { if (!GetT(doc, "isPrototype", "boolean", true)) { return Doc.MakeCopy(doc); -- cgit v1.2.3-70-g09d2 From d2dfc0f9d35f0084a7c0dea73215f5d21055f2f3 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Thu, 20 Jun 2019 17:17:14 -0400 Subject: pdf page sizes loading error --- src/client/views/pdf/PDFViewer.tsx | 1 + src/client/views/pdf/Page.tsx | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 7000352e7..6adead626 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -203,6 +203,7 @@ class Viewer extends React.Component { this._isPage[page] = "page"; this._visibleElements[page] = ( ; name: string; numPages: number; @@ -36,8 +37,8 @@ interface IPageProps { @observer export default class Page extends React.Component { @observable private _state: string = "N/A"; - @observable private _width: number = 0; - @observable private _height: number = 0; + @observable private _width: number = this.props.size.width; + @observable private _height: number = this.props.size.height; @observable private _page: Opt; @observable private _currPage: number = this.props.page + 1; @observable private _marqueeX: number = 0; -- cgit v1.2.3-70-g09d2 From 1f172642d12c4669960b8526324e4bd034994be4 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 20 Jun 2019 17:44:24 -0400 Subject: Added arrange documents in grid command --- .../collectionFreeForm/CollectionFreeFormView.tsx | 32 ++++++++++++++++++++-- src/client/views/nodes/DocumentView.tsx | 2 +- 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 84841e469..f756fe625 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,6 @@ import { action, computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc, HeightSym, WidthSym } from "../../../../new_fields/Doc"; +import { Doc, HeightSym, WidthSym, DocListCastAsync } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { createSchema, makeInterface } from "../../../../new_fields/Schema"; @@ -26,6 +26,7 @@ import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); import PDFMenu from "../../pdf/PDFMenu"; +import { ContextMenu } from "../../ContextMenu"; export const panZoomSchema = createSchema({ panX: "number", @@ -339,6 +340,33 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } + onContextMenu = () => { + ContextMenu.Instance.addItem({ + description: "Arrange contents in grid", + event: async () => { + const docs = await DocListCastAsync(this.Document[this.props.fieldKey]); + if (docs) { + let startX = this.Document.panX || 0; + let x = startX; + let y = this.Document.panY || 0; + let i = 0; + const width = Math.max(...docs.map(doc => NumCast(doc.width))); + const height = Math.max(...docs.map(doc => NumCast(doc.height))); + for (const doc of docs) { + doc.x = x; + doc.y = y; + x += width + 20; + if (++i === 6) { + i = 0; + x = startX; + y += height + 20; + } + } + } + } + }); + } + private childViews = () => [ , ...this.views @@ -349,7 +377,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return (
    + onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onContextMenu={this.onContextMenu}> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 280804630..522c37989 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -237,7 +237,7 @@ export class DocumentView extends DocComponent(Docu static _undoBatch?: UndoManager.Batch = undefined; @action - public collapseTargetsToPoint = async (scrpt: number[], expandedDocs: Doc[] | undefined): Promise => { + public collapseTargetsToPoint = (scrpt: number[], expandedDocs: Doc[] | undefined): void => { SelectionManager.DeselectAll(); if (expandedDocs) { if (!DocumentView._undoBatch) { -- cgit v1.2.3-70-g09d2 From 0cab79a50719719e1dade40520a6967f7aa8f951 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 20 Jun 2019 18:35:45 -0400 Subject: Added debug and release modes to server and client --- .gitignore | 2 ++ package.json | 2 ++ src/client/util/ClientUtils.ts.temp | 3 ++ .../views/collections/CollectionStackingView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 16 +++++----- src/server/index.ts | 34 ++++++++++++++++++---- 6 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 src/client/util/ClientUtils.ts.temp (limited to 'src') diff --git a/.gitignore b/.gitignore index a499c39a3..5d3100dc6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules package-lock.json dist/ .DS_Store +.env +ClientUtils.ts \ No newline at end of file diff --git a/package.json b/package.json index 7fd6c4ba9..91d3a3853 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@types/cookie-parser": "^1.4.1", "@types/cookie-session": "^2.0.36", "@types/d3-format": "^1.3.1", + "@types/dotenv": "^6.1.1", "@types/express": "^4.16.1", "@types/express-flash": "0.0.0", "@types/express-session": "^1.15.12", @@ -110,6 +111,7 @@ "cookie-session": "^2.0.0-beta.3", "crypto-browserify": "^3.11.0", "d3-format": "^1.3.2", + "dotenv": "^8.0.0", "express": "^4.16.4", "express-flash": "0.0.2", "express-session": "^1.15.6", diff --git a/src/client/util/ClientUtils.ts.temp b/src/client/util/ClientUtils.ts.temp new file mode 100644 index 000000000..f9fad5ed9 --- /dev/null +++ b/src/client/util/ClientUtils.ts.temp @@ -0,0 +1,3 @@ +export namespace ClientUtils { + export const RELEASE = "mode"; +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 368e94a8c..521e8d616 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -101,7 +101,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let renderScale = this.columnWidth / NumCast(d.nativeWidth, this.columnWidth); let aspect = NumCast(d.nativeWidth) / NumCast(d.nativeHeight); let width = () => this.columnWidth; - let height = () => aspect ? width() / aspect : d[HeightSym]() + let height = () => aspect ? width() / aspect : d[HeightSym](); let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + this.gridGap)); let childFocus = (doc: Doc) => { doc.libraryBrush = true; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c51c16883..c7ed2eb38 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -72,7 +72,7 @@ class TreeView extends React.Component { @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight"); - onPointerDown = (e: React.PointerEvent) => e.stopPropagation() + onPointerDown = (e: React.PointerEvent) => e.stopPropagation(); onPointerEnter = (e: React.PointerEvent): void => { this.props.active() && (this.props.document.libraryBrush = true); if (e.buttons === 1 && SelectionManager.GetIsDragging()) { @@ -114,11 +114,11 @@ class TreeView extends React.Component { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); } @action - indent = () => this.props.addDocument(this.props.document) && this.delete(); + indent = () => this.props.addDocument(this.props.document) && this.delete() renderBullet() { - let docList = Cast(this.props.document["data"], listSpec(Doc)); - let doc = Cast(this.props.document["data"], Doc); + let docList = Cast(this.props.document.data, listSpec(Doc)); + let doc = Cast(this.props.document.data, Doc); let isDoc = doc instanceof Doc || docList; return
    this._collapsed = !this._collapsed)}> {} @@ -298,7 +298,7 @@ class TreeView extends React.Component { addDocTab={this.props.addDocTab} setPreviewScript={emptyFunction}> -
    +
    ; } } return
    @@ -337,14 +337,14 @@ class TreeView extends React.Component { TreeView.AddDocToList(docList[i - 1], fieldKey, child); remove(child); } - } + }; let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => { return add(doc, relativeTo ? relativeTo : docList[i], before !== undefined ? before : false); - } + }; let rowHeight = () => { let aspect = NumCast(child.nativeWidth, 0) / NumCast(child.nativeHeight, 0); return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym](); - } + }; return request.get(url).pipe(fs.createWriteStream(dest)); +const release = process.env.RELEASE === "true"; +if (process.env.RELEASE === "true") { + console.log("Running server in release mode"); +} else { + console.log("Running server in debug mode"); +} +console.log(process.env.PWD); +let clientUtils = fs.readFileSync("./src/client/util/ClientUtils.ts.temp", "utf8"); +clientUtils = `//AUTO-GENERATED FILE: DO NOT EDIT\n${clientUtils.replace('"mode"', String(release))}`; +fs.writeFileSync("./src/client/util/ClientUtils.ts", clientUtils, "utf8"); + const mongoUrl = 'mongodb://localhost:27017/Dash'; mongoose.connect(mongoUrl); mongoose.connection.on('connected', () => console.log("connected")); @@ -406,11 +418,21 @@ app.post(RouteStore.reset, postReset); app.use(RouteStore.corsProxy, (req, res) => req.pipe(request(req.url.substring(1))).pipe(res)); -app.get(RouteStore.delete, (req, res) => - deleteFields().then(() => res.redirect(RouteStore.home))); +app.get(RouteStore.delete, (req, res) => { + if (release) { + res.send("no"); + return; + } + deleteFields().then(() => res.redirect(RouteStore.home)); +}); -app.get(RouteStore.deleteAll, (req, res) => - deleteAll().then(() => res.redirect(RouteStore.home))); +app.get(RouteStore.deleteAll, (req, res) => { + if (release) { + res.send("no"); + return; + } + deleteAll().then(() => res.redirect(RouteStore.home)); +}); app.use(wdm(compiler, { publicPath: config.output.publicPath })); @@ -435,7 +457,9 @@ server.on("connection", function (socket: Socket) { Utils.AddServerHandler(socket, MessageStore.SetField, (args) => setField(socket, args)); Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField); Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields); - Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields); + if (!release) { + Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields); + } Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField); Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff)); -- cgit v1.2.3-70-g09d2 From a40e7bb5e9d1256002083d7e3f3c4db60cd8e9df Mon Sep 17 00:00:00 2001 From: Sam Wilkins <35748010+samwilkins333@users.noreply.github.com> Date: Thu, 20 Jun 2019 19:41:39 -0400 Subject: Fixed missed pointer up event --- src/client/views/collections/CollectionDockingView.tsx | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 69b9e77eb..de5c66c0b 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -259,6 +259,11 @@ export class CollectionDockingView extends React.Component { this._isPointerDown = true; + let onPointerUp = action(() => { + window.removeEventListener("pointerup", onPointerUp) + this._isPointerDown = false + }) + window.addEventListener("pointerup", onPointerUp); var className = (e.target as any).className; if (className === "messageCounter") { e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From ca5e29fdc7c238274eaf90682a8fa2ddc90e4e17 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 20 Jun 2019 22:22:57 -0400 Subject: fix to open on right, fix to image drag fro web, and layout fixes for stacking view multi-column --- .../views/collections/CollectionStackingView.scss | 13 +++++ .../views/collections/CollectionStackingView.tsx | 62 ++++++++-------------- src/client/views/collections/CollectionSubView.tsx | 7 ++- .../views/collections/CollectionTreeView.tsx | 2 +- 4 files changed, 42 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index af194aec9..485ecf1de 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -38,4 +38,17 @@ background: $dark-color; color: $light-color; } + + + .collectionStackingView-columnDoc, + .collectionStackingView-masonryDoc { + margin-left: auto; + margin-right: auto; + } + + .collectionStackingView-masonryDoc { + transform-origin: top left; + grid-column-end: span 1; + height: 100%; + } } \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 368e94a8c..c855cb43a 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,5 +1,5 @@ import React = require("react"); -import { action, computed, IReactionDisposer, reaction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; @@ -10,7 +10,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; import "./CollectionStackingView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { auto } from "async"; +import { Transform } from "../../util/Transform"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -67,18 +67,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let children = this.childDocs.filter(d => !d.isMinimized); return children.map((d, i) => { let dref = React.createRef(); - let script = undefined; - let colWidth = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; - let rowHeight = () => this.singleColDocHeight(d); let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]()); - return
    d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; + let height = () => this.singleColDocHeight(d); + return
    + style={{ width: width(), height: height() }} > doc) { whenActiveChanged={this.props.whenActiveChanged} addDocTab={this.props.addDocTab} setPreviewScript={emptyFunction} - previewScript={script}> + previewScript={undefined}>
    ; }); @@ -96,46 +95,31 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get children() { return this.childDocs.filter(d => !d.isMinimized).map((d, i) => { + let aspect = d.nativeHeight ? NumCast(d.nativeWidth) / NumCast(d.nativeHeight) : undefined; let dref = React.createRef(); let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]()); - let renderScale = this.columnWidth / NumCast(d.nativeWidth, this.columnWidth); - let aspect = NumCast(d.nativeWidth) / NumCast(d.nativeHeight); - let width = () => this.columnWidth; + let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => aspect ? width() / aspect : d[HeightSym]() let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + this.gridGap)); - let childFocus = (doc: Doc) => { - doc.libraryBrush = true; - this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered. - }; return (
    - + + setPreviewScript={emptyFunction} + previewScript={undefined}> +
    ); }); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e55cd9e37..699bddc7c 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -176,8 +176,11 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { return; } if (html && !html.startsWith(" 1 && tags[1].startsWith("img") ? tags[1] : ""; + if (img) { + let split = img.split("src=\"")[1].split("\"")[0]; let doc = Docs.ImageDocument(split, { ...options, width: 300 }); this.props.addDocument(doc, false); return; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c51c16883..e7a3c4022 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -70,7 +70,7 @@ class TreeView extends React.Component { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight"); + @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "onRight"); onPointerDown = (e: React.PointerEvent) => e.stopPropagation() onPointerEnter = (e: React.PointerEvent): void => { -- cgit v1.2.3-70-g09d2 From 6e5cd0e991e2e6d7ae8de1d73ff273ba0737355c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 23 Jun 2019 17:23:33 -0400 Subject: Fixed shift dragging with no open panes --- src/client/views/collections/CollectionDockingView.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index de5c66c0b..5f8862c43 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -135,10 +135,11 @@ export class CollectionDockingView extends React.Component Date: Mon, 24 Jun 2019 10:26:57 -0400 Subject: Changed how zooming works --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f756fe625..4b4e7465a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -217,7 +217,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } else { // if (modes[e.deltaMode] === 'pixels') coefficient = 50; // else if (modes[e.deltaMode] === 'lines') coefficient = 1000; // This should correspond to line-height?? - let deltaScale = (1 - (e.deltaY / coefficient)); + let deltaScale = e.deltaY > 0 ? (1 / 1.1) : 1.1; if (deltaScale * this.zoomScaling() < 1 && this.isAnnotationOverlay) { deltaScale = 1 / this.zoomScaling(); } -- cgit v1.2.3-70-g09d2 From 52051829373bc4acfe9d705b64c30e3fddebf439 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 24 Jun 2019 10:49:05 -0400 Subject: Fixed image size stuff --- package.json | 3 +- src/client/documents/Documents.ts | 2 +- src/client/util/request-image-size.js | 73 +++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/client/util/request-image-size.js (limited to 'src') diff --git a/package.json b/package.json index 91d3a3853..713c5d585 100644 --- a/package.json +++ b/package.json @@ -124,6 +124,7 @@ "html-to-image": "^0.1.0", "i": "^0.3.6", "image-data-uri": "^2.0.0", + "image-size": "^0.7.4", "imagesloaded": "^4.1.4", "jsonwebtoken": "^8.5.0", "jsx-to-string": "^1.4.0", @@ -175,13 +176,13 @@ "react-split-pane": "^0.1.85", "react-table": "^6.9.2", "request": "^2.88.0", - "request-image-size": "^2.1.0", "request-promise": "^4.2.4", "serializr": "^1.5.1", "sharp": "^0.22.1", "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", "solr-node": "^1.1.3", + "standard-http-error": "^2.0.1", "typescript-collections": "^1.3.2", "url-loader": "^1.1.2", "uuid": "^3.3.2", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index de6c5bc6a..b04fc401a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -34,7 +34,7 @@ import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; -var requestImageSize = require('request-image-size'); +var requestImageSize = require('../util/request-image-size'); var path = require('path'); export interface DocumentOptions { diff --git a/src/client/util/request-image-size.js b/src/client/util/request-image-size.js new file mode 100644 index 000000000..0f9328872 --- /dev/null +++ b/src/client/util/request-image-size.js @@ -0,0 +1,73 @@ +/** + * request-image-size: Detect image dimensions via request. + * Licensed under the MIT license. + * + * https://github.com/FdezRomero/request-image-size + * © 2017 Rodrigo Fernández Romero + * + * Based on the work of Johannes J. Schmidt + * https://github.com/jo/http-image-size + */ + +const request = require('request'); +const imageSize = require('image-size'); +const HttpError = require('standard-http-error'); + +module.exports = function requestImageSize(options) { + let opts = { + encoding: null + }; + + if (options && typeof options === 'object') { + opts = Object.assign(options, opts); + } else if (options && typeof options === 'string') { + opts = Object.assign({ uri: options }, opts); + } else { + return Promise.reject(new Error('You should provide an URI string or a "request" options object.')); + } + + opts.encoding = null; + + return new Promise((resolve, reject) => { + const req = request(opts); + + req.on('response', res => { + if (res.statusCode >= 400) { + return reject(new HttpError(res.statusCode, res.statusMessage)); + } + + let buffer = new Buffer([]); + let size; + let imageSizeError; + + res.on('data', chunk => { + buffer = Buffer.concat([buffer, chunk]); + + try { + size = imageSize(buffer); + } catch (err) { + imageSizeError = err; + return; + } + + if (size) { + resolve(size); + return req.abort(); + } + }); + + res.on('error', err => reject(err)); + + res.on('end', () => { + if (!size) { + return reject(imageSizeError); + } + + size.downloaded = buffer.length; + return resolve(size); + }); + }); + + req.on('error', err => reject(err)); + }); +}; -- cgit v1.2.3-70-g09d2 From c9f77d5aab98e6e7865cdcad957d5c937631775d Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 24 Jun 2019 13:41:39 -0400 Subject: Added ReadOnly mode for docs and changed computed values a bit --- src/client/util/Scripting.ts | 12 +++++++++++- src/client/views/nodes/KeyValueBox.tsx | 6 +++--- src/fields/ScriptField.ts | 9 +++++---- src/new_fields/Doc.ts | 11 ++++++++++- src/new_fields/Proxy.ts | 4 +--- src/new_fields/util.ts | 36 +++++++++++++++++++++++++++------- 6 files changed, 59 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 40e2ad6bb..a59d9f201 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -39,7 +39,6 @@ export interface CompileError { } export type CompileResult = CompiledScript | CompileError; - function Run(script: string | undefined, customParams: string[], diagnostics: any[], originalScript: string, options: ScriptOptions): CompileResult { const errors = diagnostics.some(diag => diag.category === ts.DiagnosticCategory.Error); if ((options.typecheck !== false && errors) || !script) { @@ -64,10 +63,20 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an } } let thisParam = args.this || capturedVariables.this; + let batch: { end(): void } | undefined = undefined; try { + if (!options.editable) { + batch = Doc.MakeReadOnly(); + } const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray); + if (batch) { + batch.end(); + } return { success: true, result }; } catch (error) { + if (batch) { + batch.end(); + } return { success: false, error }; } }; @@ -133,6 +142,7 @@ export interface ScriptOptions { params?: { [name: string]: string }; capturedVariables?: { [name: string]: Field }; typecheck?: boolean; + editable?: boolean; } export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 3d626eef0..a4c14ae38 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -38,10 +38,11 @@ export class KeyValueBox extends React.Component { } public static SetField(doc: Doc, key: string, value: string) { let eq = value.startsWith("="); + let target = eq ? doc : Doc.GetProto(doc); value = eq ? value.substr(1) : value; let dubEq = value.startsWith(":="); value = dubEq ? value.substr(2) : value; - let options: ScriptOptions = { addReturn: true }; + let options: ScriptOptions = { addReturn: true, params: { this: "Doc" } }; if (dubEq) options.typecheck = false; let script = CompileScript(value, options); if (!script.compiled) { @@ -49,12 +50,11 @@ export class KeyValueBox extends React.Component { } let field = new ComputedField(script); if (!dubEq) { - let res = script.run(); + let res = script.run({ this: target }); if (!res.success) return false; field = res.result; } if (Field.IsField(field, true)) { - let target = eq ? doc : Doc.GetProto(doc); target[key] = field; return true; } diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index ac46ccf90..dbca74720 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -3,7 +3,7 @@ import { CompiledScript, CompileScript } from "../client/util/Scripting"; import { Copy, ToScriptString, Parent, SelfProxy } from "../new_fields/FieldSymbols"; import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; import { Deserializable } from "../client/util/SerializationHelper"; -import { computed } from "mobx"; +import { Doc } from "../new_fields/Doc"; function optional(propSchema: PropSchema) { return custom(value => { @@ -23,6 +23,7 @@ const optionsSchema = createSimpleSchema({ requiredType: true, addReturn: true, typecheck: true, + readonly: true, params: optional(map(primitive())) }); @@ -86,9 +87,9 @@ export class ScriptField extends ObjectField { @Deserializable("computed", deserializeScript) export class ComputedField extends ScriptField { - @computed - get value() { - const val = this._script.run({ this: (this[Parent] as any)[SelfProxy] }); + //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(doc: Doc) { + const val = this._script.run({ this: doc }); if (val.success) { return val.result; } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 9bacf49ba..cce4fff5d 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -2,7 +2,7 @@ import { observable, action } from "mobx"; import { serializable, primitive, map, alias, list } from "serializr"; import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper"; import { DocServer } from "../client/DocServer"; -import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; +import { setter, getter, getField, updateFunction, deleteProperty, makeEditable, makeReadOnly } from "./util"; import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types"; import { listSpec } from "./Schema"; import { ObjectField } from "./ObjectField"; @@ -156,6 +156,15 @@ export namespace Doc { // return Cast(field, ctor); // }); // } + export function MakeReadOnly(): { end(): void } { + makeReadOnly(); + return { + end() { + makeEditable(); + } + }; + } + export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldResult { const self = doc[Self]; return getField(self, key, ignoreProto); diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index 130ec066e..38d874a68 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -48,9 +48,8 @@ export class ProxyField extends ObjectField { private failed = false; private promise?: Promise; - value(callback?: ((field: T | undefined) => void)): T | undefined | FieldWaiting { + value(): T | undefined | FieldWaiting { if (this.cache) { - callback && callback(this.cache); return this.cache; } if (this.failed) { @@ -64,7 +63,6 @@ export class ProxyField extends ObjectField { return field; })); } - callback && this.promise.then(callback); return this.promise; } } diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 8cb1db953..cc937c567 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -6,10 +6,13 @@ import { FieldValue } from "./Types"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action } from "mobx"; -import { Parent, OnUpdate, Update, Id, SelfProxy } from "./FieldSymbols"; +import { Parent, OnUpdate, Update, Id, SelfProxy, Self } from "./FieldSymbols"; import { ComputedField } from "../fields/ScriptField"; -export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { +function _readOnlySetter(): never { + throw new Error("Documents can't be modified in read-only mode"); +} +const _setterImpl = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { if (SerializationHelper.IsSerializing()) { target[prop] = value; return true; @@ -53,6 +56,20 @@ export const setter = action(function (target: any, prop: string | symbol | numb return true; }); +let _setter: (target: any, prop: string | symbol | number, value: any, receiver: any) => boolean = _setterImpl; + +export function makeReadOnly() { + _setter = _readOnlySetter; +} + +export function makeEditable() { + _setter = _setterImpl; +} + +export function setter(target: any, prop: string | symbol | number, value: any, receiver: any): boolean { + return _setter(target, prop, value, receiver); +} + export function getter(target: any, prop: string | symbol | number, receiver: any): any { if (typeof prop === "symbol") { return target.__fields[prop] || target[prop]; @@ -60,25 +77,30 @@ export function getter(target: any, prop: string | symbol | number, receiver: an if (SerializationHelper.IsSerializing()) { return target[prop]; } - return getField(target, prop); + return getFieldImpl(target, prop, receiver); } -export function getField(target: any, prop: string | number, ignoreProto: boolean = false): any { +function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreProto: boolean = false): any { + receiver = receiver || target[SelfProxy]; const field = target.__fields[prop]; if (field instanceof ProxyField) { return field.value(); } if (field instanceof ComputedField) { - return field.value; + return field.value(receiver); } if (field === undefined && !ignoreProto && prop !== "proto") { - const proto = getField(target, "proto", true); + const proto = getFieldImpl(target, "proto", receiver, true);//TODO tfs: instead of receiver we could use target[SelfProxy]... I don't which semantics we want or if it really matters if (proto instanceof Doc) { - return proto[prop]; + return getFieldImpl(proto[Self], prop, receiver, ignoreProto); } return undefined; } return field; + +} +export function getField(target: any, prop: string | number, ignoreProto: boolean = false): any { + return getFieldImpl(target, prop, undefined, ignoreProto); } export function deleteProperty(target: any, prop: string | number | symbol) { -- cgit v1.2.3-70-g09d2 From d475b19e9ba7bc8870ec7bc1e10b5cc88decea0b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 24 Jun 2019 15:56:42 -0400 Subject: fixed crash --- src/new_fields/util.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index cadd8f8d0..abb777adf 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -21,7 +21,9 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number target[prop] = value; return true; } - value = value[SelfProxy] || value; + if (value !== undefined) { + value = value[SelfProxy] || value; + } const curValue = target.__fields[prop]; if (curValue === value || (curValue instanceof ProxyField && value instanceof RefField && curValue.fieldId === value[Id])) { // TODO This kind of checks correctly in the case that curValue is a ProxyField and value is a RefField, but technically -- cgit v1.2.3-70-g09d2 From 219cabb3fe42ab199550efc3423b7aaed4e1ee93 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 24 Jun 2019 22:45:19 -0400 Subject: Switched shift drag of tabs to normal drag and added drag target for document drag --- src/client/util/DragManager.ts | 4 ++- .../views/collections/CollectionDockingView.tsx | 41 +++++++++++++++------- 2 files changed, 32 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c3c92daa5..b707dbe57 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -90,6 +90,8 @@ export namespace DragManager { handlers: DragHandlers; hideSource: boolean | (() => boolean); + + withoutShiftDrag?: boolean; } export interface DragDropDisposer { @@ -312,7 +314,7 @@ export namespace DragManager { if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined; } - if (e.shiftKey && CollectionDockingView.Instance) { + if (((options && !options.withoutShiftDrag) || !options) && e.shiftKey && CollectionDockingView.Instance) { AbortDrag(); CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 5f8862c43..f1473139c 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -24,6 +24,10 @@ import { SubCollectionViewProps } from "./CollectionSubView"; import { ParentDocSelector } from './ParentDocumentSelector'; import React = require("react"); import { MainView } from '../MainView'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faFile } from '@fortawesome/free-solid-svg-icons'; +library.add(faFile); @observer export class CollectionDockingView extends React.Component { @@ -261,9 +265,9 @@ export class CollectionDockingView extends React.Component { this._isPointerDown = true; let onPointerUp = action(() => { - window.removeEventListener("pointerup", onPointerUp) - this._isPointerDown = false - }) + window.removeEventListener("pointerup", onPointerUp); + this._isPointerDown = false; + }); window.addEventListener("pointerup", onPointerUp); var className = (e.target as any).className; if (className === "messageCounter") { @@ -276,7 +280,7 @@ export class CollectionDockingView extends React.Component) => (sourceDoc instanceof Doc) && DragLinksAsDocuments(tab, x, y, sourceDoc))); } else - if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) { + if ((className === "lm_title" || className === "lm_tab lm_active") && e.shiftKey) { e.stopPropagation(); e.preventDefault(); let x = e.clientX; @@ -294,7 +298,8 @@ export class CollectionDockingView extends React.Component { if (doc instanceof Doc) { - let counter: any = this.htmlToElement(`0
    `); - tab.element.append(counter); + let dragSpan = document.createElement("span"); + dragSpan.style.position = "relative"; + dragSpan.style.bottom = "6px"; + dragSpan.style.paddingLeft = "4px"; + dragSpan.style.paddingRight = "2px"; let upDiv = document.createElement("span"); const stack = tab.contentItem.parent; // shifts the focus to this tab when another tab is dragged over it @@ -354,15 +362,24 @@ export class CollectionDockingView extends React.Component CollectionDockingView.Instance.AddTab(stack, doc)} />, upDiv); - tab.reactComponents = [upDiv]; + ReactDOM.render( { + e.preventDefault(); + e.stopPropagation(); + DragManager.StartDocumentDrag([dragSpan], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY, { + handlers: { dragComplete: emptyFunction }, + hideSource: false + }); + }}>, dragSpan); + ReactDOM.render( CollectionDockingView.Instance.AddTab(stack, doc)} />, upDiv); + tab.reactComponents = [dragSpan, upDiv]; + tab.element.append(dragSpan); tab.element.append(upDiv); - counter.DashDocId = tab.contentItem.config.props.documentId; - tab.reactionDisposer = reaction(() => [doc.linkedFromDocs, doc.LinkedToDocs, doc.title], + tab.reactionDisposer = reaction(() => [doc.title], () => { - counter.innerHTML = DocListCast(doc.linkedFromDocs).length + DocListCast(doc.linkedToDocs).length; tab.titleElement[0].textContent = doc.title; }, { fireImmediately: true }); + //TODO why can't this just be doc instead of the id? tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId; } }); -- cgit v1.2.3-70-g09d2