From ef0e1ecc441d300531a09a2b5b0746b04eb25c11 Mon Sep 17 00:00:00 2001 From: ab Date: Mon, 18 Mar 2019 19:44:41 -0400 Subject: can delete keys. obv get errors if you delete layout keys --- src/client/views/nodes/KeyValuePair.scss | 12 ++++++++++++ src/client/views/nodes/KeyValuePair.tsx | 14 +++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/client/views/nodes/KeyValuePair.scss (limited to 'src') diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss new file mode 100644 index 000000000..64e871e1c --- /dev/null +++ b/src/client/views/nodes/KeyValuePair.scss @@ -0,0 +1,12 @@ +@import "../global_variables"; + +.container{ + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; +} + +.delete{ + color: red; +} \ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 111f85a05..7ed5ee272 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,5 +1,6 @@ import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app import "./KeyValueBox.scss"; +import "./KeyValuePair.scss"; import React = require("react") import { FieldViewProps, FieldView } from './FieldView'; import { Opt, Field } from '../../../fields/Field'; @@ -55,7 +56,18 @@ export class KeyValuePair extends React.Component { ); return ( - {this.key.Name} + {/* */} + +
+
{this.key.Name}
+ +
+ { let field = props.doc.Get(props.fieldKey); if (field && field instanceof Field) { -- cgit v1.2.3-70-g09d2 From 6cee1e69703463cd6410d24a96c1f9eb33e996a5 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 19 Mar 2019 20:29:51 -0400 Subject: Refactored undo stuff --- src/client/util/UndoManager.ts | 56 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 46ad558f3..3cbb994b7 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -1,4 +1,13 @@ import { observable, action } from "mobx"; +import 'source-map-support/register' + +function getBatchName(target: any, key: string | symbol): string { + let keyName = key.toString(); + if (target && target.constructor && target.constructor.name) { + return `${target.constructor.name}.${keyName}`; + } + return keyName; +} function propertyDecorator(target: any, key: string | symbol) { Object.defineProperty(target, key, { @@ -13,11 +22,11 @@ function propertyDecorator(target: any, key: string | symbol) { writable: true, configurable: true, value: function (...args: any[]) { + let batch = UndoManager.StartBatch(getBatchName(target, key)); try { - UndoManager.StartBatch(); return value.apply(this, args); } finally { - UndoManager.EndBatch(); + batch.end(); } } }) @@ -32,11 +41,11 @@ export function undoBatch(target: any, key: string | symbol, descriptor?: TypedP const oldFunction = descriptor.value; descriptor.value = function (...args: any[]) { + let batch = UndoManager.StartBatch(getBatchName(target, key)); try { - UndoManager.StartBatch() return oldFunction.apply(this, args) } finally { - UndoManager.EndBatch() + batch.end(); } } @@ -70,26 +79,53 @@ export namespace UndoManager { return redoStack.length > 0; } - export function StartBatch(): void { + let openBatches: Batch[] = []; + export function GetOpenBatches(): { batchName: string, cancel: () => void }[] { + return openBatches; + } + export class Batch { + private disposed: boolean = false; + + constructor(readonly batchName: string) { + openBatches.push(this); + } + + private dispose = (cancel: boolean) => { + if (this.disposed) { + throw new Error("Cannot dispose an already disposed batch"); + } + this.disposed = true; + openBatches.splice(openBatches.indexOf(this)); + EndBatch(cancel); + } + + end = () => { this.dispose(false); } + cancel = () => { this.dispose(true); } + } + + export function StartBatch(batchName: string): Batch { batchCounter++; if (batchCounter > 0) { currentBatch = []; } + return new Batch(batchName); } - export const EndBatch = action(() => { + const EndBatch = action((cancel: boolean = false) => { batchCounter--; if (batchCounter === 0 && currentBatch && currentBatch.length) { - undoStack.push(currentBatch); + if (!cancel) { + undoStack.push(currentBatch); + } redoStack.length = 0; currentBatch = undefined; } }) - export function RunInBatch(fn: () => void) { - StartBatch(); + export function RunInBatch(fn: () => void, batchName: string) { + let batch = StartBatch(batchName); fn(); - EndBatch(); + batch.end(); } export const Undo = action(() => { -- cgit v1.2.3-70-g09d2 From a80314af20b220b9fae56fb29b92199efb0645ca Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 20 Mar 2019 00:20:28 -0400 Subject: basically just set collectionfreeformview-overlay to position:relative --- .../views/collections/CollectionFreeFormView.scss | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss index 0e0570397..bdc597a25 100644 --- a/src/client/views/collections/CollectionFreeFormView.scss +++ b/src/client/views/collections/CollectionFreeFormView.scss @@ -7,6 +7,9 @@ width: 100%; } + .inking-canvas { + transform-origin: 50000px 50000px; + } //nested freeform views // .collectionfreeformview-container { // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px), @@ -14,22 +17,25 @@ // background-size: 30px 30px; // } + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; border: 0px solid $light-color-secondary; border-radius: $border-radius; box-sizing: border-box; position: relative; + overflow: hidden; top: 0; left: 0; width: 100%; height: 100%; - overflow: hidden; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; .collectionfreeformview { position: absolute; top: 0; left: 0; width: 100%; height: 100%; + .inking-canvas { + transform-origin: 50000px 50000px; + } } } .collectionfreeformview-overlay { @@ -41,33 +47,32 @@ background: $light-color-secondary; } + .inking-canvas { + transform-origin: 50000px 50000px; + } + opacity: 0.99; - position:absolute; border: 0px solid transparent; border-radius: $border-radius; - overflow: hidden; box-sizing: border-box; + position:relative; + overflow: hidden; top: 0; left: 0; width: 100%; height: 100%; .collectionfreeformview { - .collectionfreeformview > .jsx-parser{ - position:absolute; - height: 100%; - } - .formattedTextBox-cont { - background:yellow; - } - - // overflow: hidden; - // border-style: solid; - // box-sizing: border-box; position: absolute; top: 0; left: 0; width: 100%; height: 100%; + .inking-canvas { + transform-origin: 50000px 50000px; + } + .formattedTextBox-cont { + background:yellow; + } } } -- cgit v1.2.3-70-g09d2 From e418b10b4e515c6ebbe0b9be64e7bfd451ddd11f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 20 Mar 2019 05:01:42 -0400 Subject: Small tweak to UndoManager --- src/Utils.ts | 4 +++- src/client/util/UndoManager.ts | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Utils.ts b/src/Utils.ts index d4b7da52c..a4db94809 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -52,4 +52,6 @@ export class Utils { public static AddServerHandlerCallback(socket: Socket, message: Message, handler: (args: [T, (res: any) => any]) => any) { socket.on(message.Message, (arg: T, fn: (res: any) => any) => handler([arg, fn])); } -} \ No newline at end of file +} + +export type Without = Pick>; \ No newline at end of file diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 3cbb994b7..6d1b2f1b8 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -1,5 +1,6 @@ import { observable, action } from "mobx"; import 'source-map-support/register' +import { Without } from "../../Utils"; function getBatchName(target: any, key: string | symbol): string { let keyName = key.toString(); @@ -80,7 +81,7 @@ export namespace UndoManager { } let openBatches: Batch[] = []; - export function GetOpenBatches(): { batchName: string, cancel: () => void }[] { + export function GetOpenBatches(): Without[] { return openBatches; } export class Batch { -- cgit v1.2.3-70-g09d2 From b639d1fdfc8dfe9b1ea300665b4b4d74929f8af7 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 20 Mar 2019 20:21:12 -0400 Subject: added drag from tree view --- .../views/collections/CollectionTreeView.tsx | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f9da759fd..19dd44c97 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -10,7 +10,7 @@ import "./CollectionTreeView.scss"; import { EditableView } from "../EditableView"; import { setupDrag } from "../../util/DragManager"; import { FieldWaiting } from "../../../fields/Field"; -import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -70,16 +70,12 @@ class TreeView extends React.Component { * Renders the EditableView title element for placement into the tree. */ renderTitle() { + let reference = React.createRef(); + let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document)); let title = this.props.document.GetT(KeyStore.Title, TextField); - - // if the title hasn't loaded, immediately return the div - if (!title || title === "") { - return
; - } - - return
( { let title = this.props.document.GetT(KeyStore.Title, TextField); if (title && title !== "") @@ -88,9 +84,12 @@ class TreeView extends React.Component { }} SetValue={(value: string) => { this.props.document.SetData(KeyStore.Title, value, TextField); return true; - }} /> -
-
+ }} />); + return ( +
+ {(!title || title === "") ? (null) : editableView(title.Data)} +
+
) } render() { -- cgit v1.2.3-70-g09d2 From d882d4013dc2df03a55c3f4afc954b7d9a38b4e4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 20 Mar 2019 22:08:32 -0400 Subject: tree view cleanup --- src/client/Server.ts | 2 +- src/client/views/EditableView.tsx | 4 +- src/client/views/InkingCanvas.tsx | 2 +- .../views/collections/CollectionFreeFormView.tsx | 4 +- .../views/collections/CollectionTreeView.scss | 5 +- .../views/collections/CollectionTreeView.tsx | 143 ++++++++------------- src/client/views/collections/CollectionView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 4 +- 8 files changed, 66 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/client/Server.ts b/src/client/Server.ts index bbdc27397..7d882c76d 100644 --- a/src/client/Server.ts +++ b/src/client/Server.ts @@ -39,7 +39,7 @@ export class Server { reaction(() => { return this.ClientFieldsCached.get(fieldid); }, (field, reaction) => { - if (field !== "") { + if (field !== FieldWaiting) { reaction.dispose() callback(field) } diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 98a6ed1ba..579d6e6ad 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -1,6 +1,6 @@ import React = require('react') import { observer } from 'mobx-react'; -import { observable, action } from 'mobx'; +import { observable, action, trace } from 'mobx'; import "./EditableView.scss" export interface EditableProps { @@ -52,7 +52,7 @@ export class EditableView extends React.Component { } else { return (
this.editing = true)}> + onClick={action(() => this.editing = true)} > {this.props.contents}
) diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 8d0121035..36a8834a0 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -137,7 +137,7 @@ export class InkingCanvas extends React.Component { // get data from server // let inkField = this.props.Document.GetT(KeyStore.Ink, InkField); - // if (!inkField || inkField == "") { + // if (!inkField || inkField == FieldWaiting) { // return (
// diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 8bf4a7539..da9f7b392 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -219,13 +219,13 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get backgroundLayout(): string | undefined { let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField); - if (field && field !== "") { + if (field && field !== FieldWaiting) { return field.Data; } } @computed get overlayLayout(): string | undefined { let field = this.props.Document.GetT(KeyStore.OverlayLayout, TextField); - if (field && field !== "") { + if (field && field !== FieldWaiting) { return field.Data; } } diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index fa0f1c761..5a14aa54d 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -1,6 +1,8 @@ @import "../global_variables"; #body { padding: 20px; + padding-left: 10px; + padding-right: 0px; background: $light-color-secondary; font-size: 13px; overflow: scroll; @@ -49,6 +51,7 @@ li { .docContainer:hover { .delete-button { display: inline; + width: auto; } } @@ -57,5 +60,5 @@ li { float: right; margin-left: 15px; margin-top: 3px; - display: none; + display: inline; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 19dd44c97..6edd90215 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,20 +1,19 @@ +import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; +import { faCaretDown, faCaretRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, observable } from "mobx"; import { observer } from "mobx-react"; -import { CollectionViewBase } from "./CollectionViewBase"; import { Document } from "../../../fields/Document"; +import { FieldWaiting } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; -import React = require("react") -import { TextField } from "../../../fields/TextField"; -import { observable, action } from "mobx"; -import "./CollectionTreeView.scss"; -import { EditableView } from "../EditableView"; import { setupDrag } from "../../util/DragManager"; -import { FieldWaiting } from "../../../fields/Field"; -import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView"; +import { EditableView } from "../EditableView"; +import "./CollectionTreeView.scss"; +import { CollectionView, COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { CollectionViewBase } from "./CollectionViewBase"; +import React = require("react") -import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faTrashAlt, faCaretRight, faCaretDown } from '@fortawesome/free-solid-svg-icons'; export interface TreeViewProps { document: Document; @@ -37,13 +36,9 @@ library.add(faCaretRight); */ class TreeView extends React.Component { - @observable - collapsed: boolean = false; - - delete = () => { - this.props.deleteDoc(this.props.document); - } + @observable _collapsed: boolean = true; + delete = () => this.props.deleteDoc(this.props.document); @action remove = (document: Document) => { @@ -54,16 +49,13 @@ class TreeView extends React.Component { } renderBullet(type: BulletType) { - let onClicked = action(() => this.collapsed = !this.collapsed); - + let onClicked = action(() => this._collapsed = !this._collapsed); + let bullet: IconProp | undefined = undefined; switch (type) { - case BulletType.Collapsed: - return
- case BulletType.Collapsible: - return
- case BulletType.List: - return
+ case BulletType.Collapsed: bullet = "caret-right"; break; + case BulletType.Collapsible: bullet = "caret-down"; break; } + return
{bullet ? : ""}
} /** @@ -72,74 +64,48 @@ class TreeView extends React.Component { renderTitle() { let reference = React.createRef(); let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document)); - let title = this.props.document.GetT(KeyStore.Title, TextField); - let editableView = (titleString: string) => ( { - let title = this.props.document.GetT(KeyStore.Title, TextField); - if (title && title !== "") - return title.Data; - return ""; - }} SetValue={(value: string) => { - this.props.document.SetData(KeyStore.Title, value, TextField); - return true; - }} />); + let editableView = (titleString: string) => + ( this.props.document.Title} + SetValue={(value: string) => { + this.props.document.SetText(KeyStore.Title, value); + return true; + }} + />); return (
- {(!title || title === "") ? (null) : editableView(title.Data)} + {editableView(this.props.document.Title)}
) } render() { - var children = this.props.document.GetT>(KeyStore.Data, ListField); - - let reference = React.createRef(); - let onItemDown = setupDrag(reference, () => this.props.document); - let titleElement = this.renderTitle(); + let bulletType = BulletType.List; + let childElements: JSX.Element | undefined = undefined; - // check if this document is a collection - if (children && children !== FieldWaiting) { - let subView; - - // if uncollapsed, then add the children elements - if (!this.collapsed) { - // render all children elements - let childrenElement = (children.Data.map(value => - ) - ) - subView = -
  • - {this.renderBullet(BulletType.Collapsible)} - {titleElement} -
      - {childrenElement} -
    -
  • - } else { - subView =
  • - {this.renderBullet(BulletType.Collapsed)} - {titleElement} -
  • + var children = this.props.document.GetT>(KeyStore.Data, ListField); + if (children && children !== FieldWaiting) { // add children for a collection + if (!this._collapsed) { + bulletType = BulletType.Collapsible; + childElements =
      + {children.Data.map(value => )} +
    } - - return
    - {subView} -
    - } - - // otherwise this is a normal leaf node - else { - return
  • - {this.renderBullet(BulletType.List)} - {titleElement} -
  • ; + else bulletType = BulletType.Collapsed; } + return
    +
  • + {this.renderBullet(bulletType)} + {this.renderTitle()} + {childElements ? childElements : (null)} +
  • +
    } } - @observer export class CollectionTreeView extends CollectionViewBase { @@ -152,12 +118,6 @@ export class CollectionTreeView extends CollectionViewBase { } render() { - let titleStr = ""; - let title = this.props.Document.GetT(KeyStore.Title, TextField); - if (title && title !== FieldWaiting) { - titleStr = title.Data; - } - var children = this.props.Document.GetT>(KeyStore.Data, ListField); let childrenElement = !children || children === FieldWaiting ? (null) : (children.Data.map(value => @@ -167,12 +127,13 @@ export class CollectionTreeView extends CollectionViewBase { return (
    this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
    - { - return this.props.Document.Title; - }} SetValue={(value: string) => { - this.props.Document.SetData(KeyStore.Title, value, TextField); + height={72} + GetValue={() => this.props.Document.Title} + SetValue={(value: string) => { + this.props.Document.SetText(KeyStore.Title, value); return true; }} />
    diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index d4afc69cf..7e1d31018 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -12,7 +12,7 @@ import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionViewProps } from "./CollectionViewBase"; import { CollectionTreeView } from "./CollectionTreeView"; -import { Field, FieldId } from "../../../fields/Field"; +import { Field, FieldId, FieldWaiting } from "../../../fields/Field"; import { Main } from "../Main"; export enum CollectionViewType { @@ -86,7 +86,7 @@ export class CollectionView extends React.Component { get collectionViewType(): CollectionViewType { let Document = this.props.Document; let viewField = Document.GetT(KeyStore.ViewType, NumberField); - if (viewField === "") { + if (viewField === FieldWaiting) { return CollectionViewType.Invalid; } else if (viewField) { return viewField.Data; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9e34b2b60..fec451b09 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,7 +1,7 @@ import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { Field, Opt } from "../../../fields/Field"; +import { Field, Opt, FieldWaiting } from "../../../fields/Field"; import { Key } from "../../../fields/Key"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; @@ -315,7 +315,7 @@ export class DocumentView extends React.Component { return (null); } let lkeys = this.props.Document.GetT(KeyStore.LayoutKeys, ListField); - if (!lkeys || lkeys === "") { + if (!lkeys || lkeys === FieldWaiting) { return

    Error loading layout keys

    ; } var scaling = this.props.ContentScaling(); -- cgit v1.2.3-70-g09d2