From c619bad0281ea6f248c48b8d418f324f67f530dd Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 3 Jul 2019 12:00:59 -0400 Subject: added to fitToBox to treeviews. fixed some fitToBox issues. moved notifications button to library tree view. --- src/new_fields/Doc.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/new_fields') diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 734a90731..29d35e19f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -249,6 +249,18 @@ export namespace Doc { return true; } + export function ComputeContentBounds(doc: Doc) { + let bounds = DocListCast(doc.data).reduce((bounds, doc) => { + var [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)]; + let [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()]; + return { + x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), + r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) + }; + }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); + return bounds; + } + // // Resolves a reference to a field by returning 'doc' if o field extension is specified, // otherwise, it returns the extension document stored in doc._ext. -- cgit v1.2.3-70-g09d2 From 25fdbe3b9159473a9249246f6c208b6e1220dbbb Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 3 Jul 2019 14:46:44 -0400 Subject: Changed how scripting works --- src/client/documents/Documents.ts | 25 +++------------------- src/client/util/Scripting.ts | 45 +++++++++++++++++++++++++++++++-------- src/new_fields/Doc.ts | 2 ++ src/new_fields/List.ts | 5 ++++- src/new_fields/RichTextField.ts | 2 ++ src/new_fields/ScriptField.ts | 4 +++- src/new_fields/URLField.ts | 11 +++++----- 7 files changed, 56 insertions(+), 38 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7d7a1f02a..7a976e7d7 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -36,6 +36,7 @@ import { UndoManager } from "../util/UndoManager"; import { RouteStore } from "../../server/RouteStore"; import { LinkManager } from "../util/LinkManager"; import { DocumentManager } from "../util/DocumentManager"; +import { Scripting } from "../util/Scripting"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -385,26 +386,6 @@ export namespace Docs { `); } - /* - - this template requires an additional style setting on the collectionView-cont to make the layout relative - -.collectionView-cont { - position: relative; - width: 100%; - height: 100%; } - */ - function Percentaption() { - return (` -
-
- {layout} -
-
- -
-
- `); - } -} \ No newline at end of file + +Scripting.addGlobal("Docs", Docs); \ No newline at end of file diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 30a05154a..3156c4f43 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -7,12 +7,7 @@ let ts = (window as any).ts; // @ts-ignore import * as typescriptlib from '!!raw-loader!./type_decls.d'; -import { Docs } from "../documents/Documents"; 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 '../../new_fields/ScriptField'; export interface ScriptSucccess { success: true; @@ -38,6 +33,34 @@ export interface CompileError { errors: any[]; } +export namespace Scripting { + export function addGlobal(global: { name: string }): void; + export function addGlobal(name: string, global: any): void; + export function addGlobal(nameOrGlobal: any, global?: any) { + let n: string; + let obj: any; + if (global !== undefined && typeof nameOrGlobal === "string") { + n = nameOrGlobal; + obj = global; + } else if (nameOrGlobal && typeof nameOrGlobal.name === "string") { + n = nameOrGlobal.name; + obj = nameOrGlobal; + } else { + throw new Error("Must either register an object with a name, or give a name and an object"); + } + if (scriptingGlobals.hasOwnProperty(n)) { + throw new Error(`Global with name ${n} is already registered, choose another name`); + } + scriptingGlobals[n] = obj; + } +} + +export function scriptingGlobal(constructor: { new(...args: any[]): any }) { + Scripting.addGlobal(constructor); +} + +const scriptingGlobals: { [name: string]: any } = {}; + 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); @@ -45,9 +68,11 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an return { compiled: false, errors: diagnostics }; } - let fieldTypes = [Doc, ImageField, PdfField, VideoField, AudioField, List, RichTextField, ScriptField, ComputedField, CompileScript]; - let paramNames = ["Docs", ...fieldTypes.map(fn => fn.name)]; - let params: any[] = [Docs, ...fieldTypes]; + let paramNames = Object.keys(scriptingGlobals); + let params = paramNames.map(key => scriptingGlobals[key]); + // let fieldTypes = [Doc, ImageField, PdfField, VideoField, AudioField, List, RichTextField, ScriptField, ComputedField, CompileScript]; + // let paramNames = ["Docs", ...fieldTypes.map(fn => fn.name)]; + // let params: any[] = [Docs, ...fieldTypes]; let compiledFunction = new Function(...paramNames, `return ${script}`); let { capturedVariables = {} } = options; let run = (args: { [name: string]: any } = {}): ScriptResult => { @@ -178,4 +203,6 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp let diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics); return Run(outputText, paramNames, diagnostics, script, options); -} \ No newline at end of file +} + +Scripting.addGlobal(CompileScript); \ No newline at end of file diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 29d35e19f..c361e3032 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -8,6 +8,7 @@ import { listSpec } from "./Schema"; import { ObjectField } from "./ObjectField"; import { RefField, FieldId } from "./RefField"; import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; +import { scriptingGlobal } from "../client/util/Scripting"; export namespace Field { export function toScriptString(field: Field): string { @@ -55,6 +56,7 @@ export function DocListCast(field: FieldResult): Doc[] { export const WidthSym = Symbol("Width"); export const HeightSym = Symbol("Height"); +@scriptingGlobal @Deserializable("doc").withFields(["id"]) export class Doc extends RefField { constructor(id?: FieldId, forceSave?: boolean) { diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index f1e4c4721..a2133a990 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -7,6 +7,7 @@ import { ObjectField } from "./ObjectField"; import { RefField } from "./RefField"; import { ProxyField } from "./Proxy"; import { Self, Update, Parent, OnUpdate, SelfProxy, ToScriptString, Copy } from "./FieldSymbols"; +import { Scripting } from "../client/util/Scripting"; const listHandlers: any = { /// Mutator methods @@ -294,4 +295,6 @@ class ListImpl extends ObjectField { } } export type List = ListImpl & (T | (T extends RefField ? Promise : never))[]; -export const List: { new (fields?: T[]): List } = ListImpl as any; \ No newline at end of file +export const List: { new (fields?: T[]): List } = ListImpl as any; + +Scripting.addGlobal("List", List); \ No newline at end of file diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index 89d077a47..78a3a4067 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -2,7 +2,9 @@ import { ObjectField } from "./ObjectField"; import { serializable } from "serializr"; import { Deserializable } from "../client/util/SerializationHelper"; import { Copy, ToScriptString } from "./FieldSymbols"; +import { scriptingGlobal } from "../client/util/Scripting"; +@scriptingGlobal @Deserializable("RichTextField") export class RichTextField extends ObjectField { @serializable(true) diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 3d56e9374..e2994ed70 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -1,5 +1,5 @@ import { ObjectField } from "./ObjectField"; -import { CompiledScript, CompileScript } from "../client/util/Scripting"; +import { CompiledScript, CompileScript, scriptingGlobal } 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"; @@ -40,6 +40,7 @@ function deserializeScript(script: ScriptField) { (script as any).script = comp; } +@scriptingGlobal @Deserializable("script", deserializeScript) export class ScriptField extends ObjectField { @serializable(object(scriptSchema)) @@ -81,6 +82,7 @@ export class ScriptField extends ObjectField { } } +@scriptingGlobal @Deserializable("computed", deserializeScript) export class ComputedField extends ScriptField { //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 diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts index 4a2841fb6..d935a61af 100644 --- a/src/new_fields/URLField.ts +++ b/src/new_fields/URLField.ts @@ -2,6 +2,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, custom } from "serializr"; import { ObjectField } from "./ObjectField"; import { ToScriptString, Copy } from "./FieldSymbols"; +import { Scripting, scriptingGlobal } from "../client/util/Scripting"; function url() { return custom( @@ -37,8 +38,8 @@ export abstract class URLField extends ObjectField { } } -@Deserializable("audio") export class AudioField extends URLField { } -@Deserializable("image") export class ImageField extends URLField { } -@Deserializable("video") export class VideoField extends URLField { } -@Deserializable("pdf") export class PdfField extends URLField { } -@Deserializable("web") export class WebField extends URLField { } \ No newline at end of file +@scriptingGlobal @Deserializable("audio") export class AudioField extends URLField { } +@scriptingGlobal @Deserializable("image") export class ImageField extends URLField { } +@scriptingGlobal @Deserializable("video") export class VideoField extends URLField { } +@scriptingGlobal @Deserializable("pdf") export class PdfField extends URLField { } +@scriptingGlobal @Deserializable("web") export class WebField extends URLField { } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 8b9fa667816378cc6cae2977f1c2d80c204b28d0 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 5 Jul 2019 14:45:15 -0400 Subject: added more options to sidebar --- src/client/views/Main.scss | 18 ++++++++++++++ src/client/views/MainView.tsx | 28 ++++++++++++++++++---- .../views/collections/CollectionDockingView.tsx | 4 ++++ .../views/collections/CollectionTreeView.tsx | 7 ++++-- src/new_fields/Doc.ts | 11 +++++---- .../authentication/models/current_user_utils.ts | 10 ++++++++ 6 files changed, 67 insertions(+), 11 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index b85a8040a..f52e3b658 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -230,6 +230,8 @@ ul#add-options-list { .mainView-libraryFlyout { height: 100%; position: absolute; + display: flex; + flex-direction:column; } .mainView-libraryHandle { @@ -241,4 +243,20 @@ ul#add-options-list { position: absolute; z-index: 1; background: gray; +} + +.mainView-workspace { + height:200px; + position:relative; + display:flex; +} +.mainView-library { + height:75%; + position:relative; + display:flex; +} +.mainView-recentlyClosed { + height:25%; + position:relative; + display:flex; } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 61ccf4c1d..92468e3fd 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -8,12 +8,12 @@ import * as React from 'react'; import { SketchPicker } from 'react-color'; import Measure from 'react-measure'; import * as request from 'request'; -import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; +import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; import { List } from '../../new_fields/List'; import { listSpec } from '../../new_fields/Schema'; -import { Cast, FieldValue } from '../../new_fields/Types'; +import { Cast, FieldValue, NumCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnOne, returnTrue } from '../../Utils'; @@ -163,7 +163,9 @@ export class MainView extends React.Component { @action createNewWorkspace = async (id?: string) => { - const list = Cast(CurrentUserUtils.UserDocument.data, listSpec(Doc)); + let workspaces = Cast(CurrentUserUtils.UserDocument.workspaces, Doc); + if (!(workspaces instanceof Doc)) return; + const list = Cast((CurrentUserUtils.UserDocument.workspaces as Doc).data, listSpec(Doc)); if (list) { let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, width: this.pwidth * .7, height: this.pheight, title: `WS collection ${list.length + 1}` }); var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc, freeformDoc, 600)] }] }; @@ -285,8 +287,24 @@ export class MainView extends React.Component { }; @computed get flyout() { + let sidebar = CurrentUserUtils.UserDocument.sidebar; + let workspaces = CurrentUserUtils.UserDocument.workspaces; + let recent = CurrentUserUtils.UserDocument.recentlyClosed; + if (!(sidebar instanceof Doc)) return (null); + if (!(recent instanceof Doc)) return (null); + if (!(workspaces instanceof Doc)) return (null); + let workspacesDoc = workspaces as Doc; + let sidebarDoc = sidebar as Doc; + let recentDoc = recent as Doc; + let library = CurrentUserUtils.UserDocument; + let gridGap = NumCast(sidebar.gridGap, 10); + let yMargin = NumCast(sidebar.yMargin, 2 * gridGap); + let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym]() - 2 * gridGap - 2 * yMargin; + if (library[HeightSym]() != libraryHeight) { + setTimeout(() => CurrentUserUtils.UserDocument.height = libraryHeight, 0); + } return - ; + } @computed get mainContent() { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index c5f8fb728..e0270fab3 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -27,6 +27,7 @@ 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'; +import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; library.add(faFile); @observer @@ -416,6 +417,9 @@ export class CollectionDockingView extends React.Component { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout - if (!e.isPropagationStopped() && this.props.Document.excludeFromLibrary) { // excludeFromLibrary means this is the user document + if (!e.isPropagationStopped() && this.props.Document.workspaceLibrary) { // excludeFromLibrary means this is the user document ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()) }); ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) }); + e.stopPropagation(); + e.preventDefault(); + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); } } @@ -531,7 +534,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { TreeView.loadId = doc[Id]; Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true); }} /> - {this.props.Document.excludeFromLibrary ? this.notifsButton : (null)} + {this.props.Document.workspaceLibrary ? this.notifsButton : (null)}
    { TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.props.DataDoc, this.props.fieldKey, addDoc, this.remove, diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index c361e3032..092205f52 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -241,12 +241,15 @@ export namespace Doc { return Array.from(results); } - export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean) { + export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean, first?: 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); + if (first) list.splice(0, 0, doc); + else { + let ind = relativeTo ? list.indexOf(relativeTo) : -1; + if (ind === -1) list.push(doc); + else list.splice(before ? ind : ind + 1, 0, doc); + } } return true; } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 816c5f269..3134ecaff 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -31,6 +31,16 @@ export class CurrentUserUtils { doc.viewType = CollectionViewType.Tree; doc.dropAction = "alias"; doc.layout = CollectionView.LayoutString(); + doc.workspaces = Docs.TreeDocument([], { title: "Workspaces", height: 100 }); + (doc.workspaces as Doc).excludeFromLibrary = true; + (doc.workspaces as Doc).workspaceLibrary = true; + doc.recentlyClosed = Docs.TreeDocument([], { title: "Recently Closed", height: 75 }); + (doc.workspaces as Doc).excludeFromLibrary = true; + doc.sidebar = Docs.StackingDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); + (doc.sidebar as Doc).excludeFromLibrary = true; + (doc.sidebar as Doc).gridGap = 5; + (doc.sidebar as Doc).xMargin = 5; + (doc.sidebar as Doc).yMargin = 5; doc.title = this.email; doc.data = new List(); doc.excludeFromLibrary = true; -- cgit v1.2.3-70-g09d2 From 8780f8652ce2cfdf37dd89be050123da3dc4eac4 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 6 Jul 2019 00:30:52 -0400 Subject: don't understand what could be happening.. --- src/client/views/DocumentDecorations.tsx | 6 ++-- src/client/views/MainView.tsx | 39 ++++++++++++++++------ .../views/collections/CollectionStackingView.tsx | 8 ++--- src/client/views/nodes/DocumentView.tsx | 4 +-- src/new_fields/util.ts | 2 +- .../authentication/models/current_user_utils.ts | 10 +++++- 6 files changed, 48 insertions(+), 21 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index c7990647a..e565566c7 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -536,8 +536,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let scale = element.props.ScreenToLocalTransform().Scale * element.props.ContentScaling(); let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); - doc.x = (doc.x || 0) + dX * (actualdW - width); - doc.y = (doc.y || 0) + dY * (actualdH - height); + // doc.x = (doc.x || 0) + dX * (actualdW - width); + // doc.y = (doc.y || 0) + dY * (actualdH - height); let proto = Doc.GetProto(element.props.Document); let fixedAspect = e.ctrlKey || (!BoolCast(proto.ignoreAspect, false) && nwidth && nheight); if (fixedAspect && (!nwidth || !nheight)) { @@ -567,7 +567,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { dW && (doc.width = actualdW); dH && (doc.height = actualdH); - Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); + //Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); } } }); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 82b17f142..f9a5b2bb7 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,7 +1,7 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; import { faArrowDown, faArrowUp, faBell, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, configure, observable, runInAction } from 'mobx'; +import { action, computed, configure, observable, runInAction, reaction } from 'mobx'; import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; @@ -72,6 +72,31 @@ export class MainView extends React.Component { window.removeEventListener("pointerup", this.pointerUp); window.addEventListener("pointerup", this.pointerUp); + + reaction(() => { + let workspaces = CurrentUserUtils.UserDocument.workspaces; + let recent = CurrentUserUtils.UserDocument.recentlyClosed; + let fakeLibrary = CurrentUserUtils.UserDocument.fakeLibrary; + if (!(recent instanceof Doc)) return 0; + if (!(workspaces instanceof Doc)) return 0; + if (!(fakeLibrary instanceof Doc)) return 0; + let workspacesDoc = workspaces; + let recentDoc = recent; + let fakeLibraryDoc = fakeLibrary; + // console.log("pheight = " + this.getPHeight() + " " + workspacesDoc[HeightSym]() + " " + recentDoc[HeightSym]()); + let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym](); + return libraryHeight; + }, (libraryHeight: number) => { + let fakeLibrary = CurrentUserUtils.UserDocument.fakeLibrary; + let cuser: Doc = fakeLibrary as Doc;//CurrentUserUtils.UserDocument; + console.log("BEFORE:" + cuser.title + ".height =" + cuser[HeightSym]() + "& .plight = " + cuser.plight); + if (libraryHeight && Math.abs(cuser[HeightSym]() - libraryHeight) > 5) { + console.log("ASSIGN to height & plight:" + libraryHeight); + cuser.height = libraryHeight; + cuser.plight = libraryHeight; + } + console.log("AFTER:" + cuser.title + ".height =" + cuser[HeightSym]() + "& .plight= " + cuser.plight); + }, { fireImmediately: true }); } pointerDown = (e: PointerEvent) => this.isPointerDown = true; @@ -285,24 +310,18 @@ export class MainView extends React.Component { CollectionDockingView.Instance.AddRightSplit(doc, undefined); } }; + computing = false; @computed get flyout() { let sidebar = CurrentUserUtils.UserDocument.sidebar; let workspaces = CurrentUserUtils.UserDocument.workspaces; let recent = CurrentUserUtils.UserDocument.recentlyClosed; + let fakeLibrary = CurrentUserUtils.UserDocument.fakeLibrary; if (!(sidebar instanceof Doc)) return (null); if (!(recent instanceof Doc)) return (null); if (!(workspaces instanceof Doc)) return (null); - let workspacesDoc = workspaces; + if (!(fakeLibrary instanceof Doc)) return (null); let sidebarDoc = sidebar; - let recentDoc = recent; - let library = CurrentUserUtils.UserDocument; - let gridGap = NumCast(sidebar.gridGap, 10); - let yMargin = NumCast(sidebar.yMargin, 2 * gridGap); - let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym]() - 2 * gridGap - 2 * yMargin; - if (Math.abs(library[HeightSym]() - libraryHeight) > 25) { - setTimeout(() => CurrentUserUtils.UserDocument.height = libraryHeight, 0); - } return doc) { () => { if (this.singleColumn) { let children = this.childDocs.filter(d => !d.isMinimized); - this.props.Document.height = children.reduce((height, d, i) => - height + this.singleColDocHeight(d) + (i === children.length - 1 ? this.yMargin : this.gridGap) - , this.yMargin); + let hgtbefore = this.props.Document.height; + // this.props.Document.height = children.reduce((height, d, i) => + // height + this.singleColDocHeight(d) + (i === children.length - 1 ? this.yMargin : this.gridGap) + // , this.yMargin); } }, { fireImmediately: true }); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a84cac37f..8ecc77946 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -564,8 +564,8 @@ export class DocumentView extends DocComponent(Docu }); } - onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; - onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; + onPointerEnter = (e: React.PointerEvent): void => { }//this.props.Document.libraryBrush = true; }; + onPointerLeave = (e: React.PointerEvent): void => { }//this.props.Document.libraryBrush = false; }; isSelected = () => SelectionManager.IsSelected(this); @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index abb777adf..c7bcdca34 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -2,7 +2,6 @@ import { UndoManager } from "../client/util/UndoManager"; import { Doc, Field } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField } from "./Proxy"; -import { FieldValue } from "./Types"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action } from "mobx"; @@ -13,6 +12,7 @@ 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 { + console.log("-set " + target[SelfProxy].title + "(" + target[SelfProxy][prop] + ")." + prop.toString() + " = " + value); if (SerializationHelper.IsSerializing()) { target[prop] = value; return true; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 30a6f108a..3e7b407a8 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -34,6 +34,9 @@ export class CurrentUserUtils { doc.title = this.email; this.updateUserDocument(doc); doc.data = new List(); + doc.gridGap = 5; + doc.xMargin = 5; + doc.yMargin = 5; doc.excludeFromLibrary = true; doc.optionalRightCollection = Docs.StackingDocument([], { title: "New mobile uploads" }); // doc.library = Docs.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` }); @@ -53,8 +56,13 @@ export class CurrentUserUtils { recentlyClosed.excludeFromLibrary = true; doc.recentlyClosed = recentlyClosed; } + if (doc.fakeLibrary === undefined) { + const recentlyClosed = Docs.TreeDocument([], { title: "Fake Library", height: 200 }); + recentlyClosed.excludeFromLibrary = true; + doc.fakeLibrary = recentlyClosed; + } if (doc.sidebar === undefined) { - const sidebar = Docs.StackingDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); + const sidebar = Docs.StackingDocument([doc.workspaces as Doc, doc.fakeLibrary as Doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); sidebar.excludeFromLibrary = true; sidebar.gridGap = 5; sidebar.xMargin = 5; -- cgit v1.2.3-70-g09d2 From d07b56aec1b1698d8a49283aade3c12c82ae1d0b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 6 Jul 2019 02:36:54 -0400 Subject: fixed sidebar problems with doc decorations. --- src/client/views/DocumentDecorations.tsx | 6 +++--- src/client/views/MainView.tsx | 25 ++++------------------ .../views/collections/CollectionStackingView.tsx | 21 +++++++++--------- src/client/views/nodes/DocumentView.tsx | 4 ++-- src/new_fields/util.ts | 2 +- .../authentication/models/current_user_utils.ts | 7 +----- 6 files changed, 21 insertions(+), 44 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index e565566c7..c7990647a 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -536,8 +536,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let scale = element.props.ScreenToLocalTransform().Scale * element.props.ContentScaling(); let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); - // doc.x = (doc.x || 0) + dX * (actualdW - width); - // doc.y = (doc.y || 0) + dY * (actualdH - height); + doc.x = (doc.x || 0) + dX * (actualdW - width); + doc.y = (doc.y || 0) + dY * (actualdH - height); let proto = Doc.GetProto(element.props.Document); let fixedAspect = e.ctrlKey || (!BoolCast(proto.ignoreAspect, false) && nwidth && nheight); if (fixedAspect && (!nwidth || !nheight)) { @@ -567,7 +567,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { dW && (doc.width = actualdW); dH && (doc.height = actualdH); - //Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); + Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); } } }); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f9a5b2bb7..8e5bb3615 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,7 +1,7 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; import { faArrowDown, faArrowUp, faBell, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, configure, observable, runInAction, reaction } from 'mobx'; +import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; @@ -76,26 +76,16 @@ export class MainView extends React.Component { reaction(() => { let workspaces = CurrentUserUtils.UserDocument.workspaces; let recent = CurrentUserUtils.UserDocument.recentlyClosed; - let fakeLibrary = CurrentUserUtils.UserDocument.fakeLibrary; if (!(recent instanceof Doc)) return 0; if (!(workspaces instanceof Doc)) return 0; - if (!(fakeLibrary instanceof Doc)) return 0; let workspacesDoc = workspaces; let recentDoc = recent; - let fakeLibraryDoc = fakeLibrary; - // console.log("pheight = " + this.getPHeight() + " " + workspacesDoc[HeightSym]() + " " + recentDoc[HeightSym]()); - let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym](); + let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym]() + CurrentUserUtils.UserDocument[HeightSym]() * 0.00001; return libraryHeight; }, (libraryHeight: number) => { - let fakeLibrary = CurrentUserUtils.UserDocument.fakeLibrary; - let cuser: Doc = fakeLibrary as Doc;//CurrentUserUtils.UserDocument; - console.log("BEFORE:" + cuser.title + ".height =" + cuser[HeightSym]() + "& .plight = " + cuser.plight); - if (libraryHeight && Math.abs(cuser[HeightSym]() - libraryHeight) > 5) { - console.log("ASSIGN to height & plight:" + libraryHeight); - cuser.height = libraryHeight; - cuser.plight = libraryHeight; + if (libraryHeight && Math.abs(CurrentUserUtils.UserDocument[HeightSym]() - libraryHeight) > 5) { + CurrentUserUtils.UserDocument.height = libraryHeight; } - console.log("AFTER:" + cuser.title + ".height =" + cuser[HeightSym]() + "& .plight= " + cuser.plight); }, { fireImmediately: true }); } @@ -310,17 +300,10 @@ export class MainView extends React.Component { CollectionDockingView.Instance.AddRightSplit(doc, undefined); } }; - computing = false; @computed get flyout() { let sidebar = CurrentUserUtils.UserDocument.sidebar; - let workspaces = CurrentUserUtils.UserDocument.workspaces; - let recent = CurrentUserUtils.UserDocument.recentlyClosed; - let fakeLibrary = CurrentUserUtils.UserDocument.fakeLibrary; if (!(sidebar instanceof Doc)) return (null); - if (!(recent instanceof Doc)) return (null); - if (!(workspaces instanceof Doc)) return (null); - if (!(fakeLibrary instanceof Doc)) return (null); let sidebarDoc = sidebar; return doc) { () => { if (this.singleColumn) { let children = this.childDocs.filter(d => !d.isMinimized); - let hgtbefore = this.props.Document.height; - // this.props.Document.height = children.reduce((height, d, i) => - // height + this.singleColDocHeight(d) + (i === children.length - 1 ? this.yMargin : this.gridGap) - // , this.yMargin); + this.props.Document.height = children.reduce((height, d, i) => + height + this.singleColDocHeight(d) + (i === children.length - 1 ? this.yMargin : this.gridGap) + , this.yMargin); } }, { fireImmediately: true }); } @@ -54,10 +53,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { addDocument(doc); return true; } - getDocTransform(doc: Doc, dref: HTMLDivElement) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); + getDocTransform(doc: Doc, ind: number, width: number) { + let localY = this.childDocs.filter(d => !d.isMinimized).reduce((height, d, i) => + height + (i < ind ? this.singleColDocHeight(d) + this.gridGap : 0), this.yMargin); + let translate = this.props.ScreenToLocalTransform().inverse().transformPoint((this.props.PanelWidth() - width) / 2, localY); let outerXf = Utils.GetScreenTransform(this._masonryGridRef!); - let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); + let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translate[0], outerXf.translateY - translate[1]); return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.columnWidth); } createRef = (ele: HTMLDivElement | null) => { @@ -70,13 +71,11 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let children = this.childDocs.filter(d => !d.isMinimized); return children.map((d, i) => { let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc); - let dref = React.createRef(); - let dxf = () => this.getDocTransform(layoutDoc, dref.current!).scale(this.columnWidth / d[WidthSym]()); let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => this.singleColDocHeight(layoutDoc); + let dxf = () => this.getDocTransform(layoutDoc, i, width()).scale(this.columnWidth / d[WidthSym]()); return
    (Docu }); } - onPointerEnter = (e: React.PointerEvent): void => { }//this.props.Document.libraryBrush = true; }; - onPointerLeave = (e: React.PointerEvent): void => { }//this.props.Document.libraryBrush = false; }; + onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; + onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; isSelected = () => SelectionManager.IsSelected(this); @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index c7bcdca34..b5e50d501 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -12,7 +12,7 @@ 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 { - console.log("-set " + target[SelfProxy].title + "(" + target[SelfProxy][prop] + ")." + prop.toString() + " = " + value); + //console.log("-set " + target[SelfProxy].title + "(" + target[SelfProxy][prop] + ")." + prop.toString() + " = " + value); if (SerializationHelper.IsSerializing()) { target[prop] = value; return true; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 3e7b407a8..e328d6e5c 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -56,13 +56,8 @@ export class CurrentUserUtils { recentlyClosed.excludeFromLibrary = true; doc.recentlyClosed = recentlyClosed; } - if (doc.fakeLibrary === undefined) { - const recentlyClosed = Docs.TreeDocument([], { title: "Fake Library", height: 200 }); - recentlyClosed.excludeFromLibrary = true; - doc.fakeLibrary = recentlyClosed; - } if (doc.sidebar === undefined) { - const sidebar = Docs.StackingDocument([doc.workspaces as Doc, doc.fakeLibrary as Doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); + const sidebar = Docs.StackingDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); sidebar.excludeFromLibrary = true; sidebar.gridGap = 5; sidebar.xMargin = 5; -- cgit v1.2.3-70-g09d2 From b51ec1c32c4bcf30d4f83744944df889a89da70b Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 8 Jul 2019 13:26:45 -0400 Subject: added clearing of recently used docs. --- src/client/views/MainView.tsx | 3 ++- src/client/views/collections/CollectionTreeView.tsx | 15 ++++++++++++++- src/new_fields/Doc.ts | 12 +++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d7674c26e..fe59f52c8 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faArrowUp, faBell, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; +import { faArrowDown, faArrowUp, faCheck, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, reaction, trace } from 'mobx'; import { observer } from 'mobx-react'; @@ -86,6 +86,7 @@ export class MainView extends React.Component { if (libraryHeight && Math.abs(CurrentUserUtils.UserDocument[HeightSym]() - libraryHeight) > 5) { CurrentUserUtils.UserDocument.height = libraryHeight; } + (Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc) as Doc)!.allowClear = true; }, { fireImmediately: true }); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index c83a2d2c6..d7725f444 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faAngleRight, faCamera, faExpand, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; +import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; @@ -51,6 +51,7 @@ export interface TreeViewProps { library.add(faTrashAlt); library.add(faAngleRight); library.add(faBell); +library.add(faTrash); library.add(faCamera); library.add(faExpand); library.add(faCaretDown); @@ -509,6 +510,17 @@ export class CollectionTreeView extends CollectionSubView(Document) {
    ; } + @computed get clearButton() { + return
    +
    + +
    +
    ; + } + render() { let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; @@ -535,6 +547,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true); }} /> {this.props.Document.workspaceLibrary ? this.notifsButton : (null)} + {this.props.Document.allowClear ? this.clearButton : (null)}
      { TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.Document, this.props.DataDoc, this.props.fieldKey, addDoc, this.remove, diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 092205f52..aa13b1d7a 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -9,6 +9,7 @@ import { ObjectField } from "./ObjectField"; import { RefField, FieldId } from "./RefField"; import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; +import { List } from "./List"; export namespace Field { export function toScriptString(field: Field): string { @@ -241,9 +242,18 @@ export namespace Doc { return Array.from(results); } - export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean) { + export function AddDocToList(target: Doc, key: string, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean) { + if (target[key] === undefined) { + Doc.GetProto(target)[key] = new List(); + } let list = Cast(target[key], listSpec(Doc)); if (list) { + if (allowDuplicates !== true) { + let pind = list.reduce((l, d, i) => d instanceof Doc && Doc.AreProtosEqual(d, doc) ? i : l, -1); + if (pind !== -1) { + list.splice(pind, 1); + } + } if (first) list.splice(0, 0, doc); else { let ind = relativeTo ? list.indexOf(relativeTo) : -1; -- cgit v1.2.3-70-g09d2 From 5642ee106ac37982a84192cc2e7a694da3b4fc3f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 8 Jul 2019 13:40:09 -0400 Subject: Hopefully got rid of new Docs being created too frequently --- src/client/util/LinkManager.ts | 38 ++++++++++++++++++--------------- src/client/views/nodes/LinkEditor.tsx | 5 +++-- src/client/views/nodes/LinkMenuItem.tsx | 12 ++++++----- src/client/views/search/SearchItem.tsx | 16 +++++++------- src/new_fields/Types.ts | 3 ++- 5 files changed, 41 insertions(+), 33 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index f2f3e51dd..944bc532f 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -68,8 +68,8 @@ export class LinkManager { // finds all links that contain the given anchor public getAllRelatedLinks(anchor: Doc): Doc[] {//List { let related = LinkManager.Instance.getAllLinks().filter(link => { - let protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)); - let protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, new Doc)); + let protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null)); + let protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null)); return protomatch1 || protomatch2; }); return related; @@ -100,9 +100,11 @@ export class LinkManager { if (index > -1) groupTypes.splice(index, 1); LinkManager.Instance.LinkManagerDoc.allGroupTypes = new List(groupTypes); LinkManager.Instance.LinkManagerDoc[groupType] = undefined; - LinkManager.Instance.getAllLinks().forEach(linkDoc => { - LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType); - LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc), groupType); + LinkManager.Instance.getAllLinks().forEach(async linkDoc => { + const anchor1 = await Cast(linkDoc.anchor1, Doc); + const anchor2 = await Cast(linkDoc.anchor2, Doc); + anchor1 && LinkManager.Instance.removeGroupFromAnchor(linkDoc, anchor1, groupType); + anchor2 && LinkManager.Instance.removeGroupFromAnchor(linkDoc, anchor2, groupType); }); } return true; @@ -122,8 +124,8 @@ export class LinkManager { } // gets the groups associates with an anchor in a link - public getAnchorGroups(linkDoc: Doc, anchor: Doc): Array { - if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { + public getAnchorGroups(linkDoc: Doc, anchor?: Doc): Array { + if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) { return DocListCast(linkDoc.anchor1Groups); } else { return DocListCast(linkDoc.anchor2Groups); @@ -132,7 +134,7 @@ export class LinkManager { // sets the groups of the given anchor in the given link public setAnchorGroups(linkDoc: Doc, anchor: Doc, groups: Doc[]) { - if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { + if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) { linkDoc.anchor1Groups = new List(groups); } else { linkDoc.anchor2Groups = new List(groups); @@ -209,10 +211,10 @@ export class LinkManager { let md: Doc[] = []; let allLinks = LinkManager.Instance.getAllLinks(); allLinks.forEach(linkDoc => { - let anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc)); - let anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc)); - anchor1Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) md.push(Cast(groupDoc.metadata, Doc, new Doc)); }); - anchor2Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) md.push(Cast(groupDoc.metadata, Doc, new Doc)); }); + let anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, null)); + let anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, null)); + anchor1Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) { const meta = Cast(groupDoc.metadata, Doc, null); meta && md.push(meta); } }); + anchor2Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) { const meta = Cast(groupDoc.metadata, Doc, null); meta && md.push(meta); } }); }); return md; } @@ -221,18 +223,20 @@ export class LinkManager { public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean { let allLinks = LinkManager.Instance.getAllLinks(); let index = allLinks.findIndex(linkDoc => { - return (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, new Doc), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, new Doc), anchor2)) || - (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, new Doc), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, new Doc), anchor1)); + return (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2)) || + (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1)); }); return index !== -1; } // finds the opposite anchor of a given anchor in a link + //TODO This should probably return undefined if there isn't an opposite anchor + //TODO This should also await the return value of the anchor so we don't filter out promises public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc { - if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) { - return Cast(linkDoc.anchor2, Doc, new Doc); + if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, null))) { + return Cast(linkDoc.anchor2, Doc, null)!; } else { - return Cast(linkDoc.anchor1, Doc, new Doc); + return Cast(linkDoc.anchor1, Doc, null)!; } } } \ No newline at end of file diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx index e6cc50620..a97ec8831 100644 --- a/src/client/views/nodes/LinkEditor.tsx +++ b/src/client/views/nodes/LinkEditor.tsx @@ -177,9 +177,10 @@ export class LinkGroupEditor extends React.Component { LinkManager.Instance.deleteGroupType(groupType); } - copyGroup = (groupType: string): void => { + copyGroup = async (groupType: string): Promise => { let sourceGroupDoc = this.props.groupDoc; - let sourceMdDoc = Cast(sourceGroupDoc.metadata, Doc, new Doc); + const sourceMdDoc = await Cast(sourceGroupDoc.metadata, Doc); + if (!sourceMdDoc) return; let destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc); diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index 4dee6741f..9728671c0 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -56,11 +56,13 @@ export class LinkMenuItem extends React.Component { let mdRows: Array = []; if (groupDoc) { - let mdDoc = Cast(groupDoc.metadata, Doc, new Doc); - let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); - mdRows = keys.map(key => { - return (
      {key}: {StrCast(mdDoc[key])}
      ); - }); + let mdDoc = Cast(groupDoc.metadata, Doc, null); + if (mdDoc) { + let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + mdRows = keys.map(key => { + return (
      {key}: {StrCast(mdDoc[key])}
      ); + }); + } } return (
      {mdRows}
      ); diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index 6cedc7cfb..99701471d 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -187,10 +187,10 @@ export class SearchItem extends React.Component { if (this.props.doc.type === DocTypes.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { - let doc1 = Cast(this.props.doc.anchor1, Doc, new Doc()); - let doc2 = Cast(this.props.doc.anchor2, Doc, new Doc()); - doc1.libraryBrush = true; - doc2.libraryBrush = true; + let doc1 = Cast(this.props.doc.anchor1, Doc, null); + let doc2 = Cast(this.props.doc.anchor2, Doc, null); + doc1 && (doc1.libraryBrush = true); + doc2 && (doc2.libraryBrush = true); } } else { let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); @@ -204,10 +204,10 @@ export class SearchItem extends React.Component { if (this.props.doc.type === DocTypes.LINK) { if (this.props.doc.anchor1 && this.props.doc.anchor2) { - let doc1 = Cast(this.props.doc.anchor1, Doc, new Doc()); - let doc2 = Cast(this.props.doc.anchor2, Doc, new Doc()); - doc1.libraryBrush = false; - doc2.libraryBrush = false; + let doc1 = Cast(this.props.doc.anchor1, Doc, null); + let doc2 = Cast(this.props.doc.anchor2, Doc, null); + doc1 && (doc1.libraryBrush = false); + doc2 && (doc2.libraryBrush = false); } } else { let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc); diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 8dd893aa4..39d384d64 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -45,9 +45,10 @@ export interface Interface { [key: string]: InterfaceValue; // [key: string]: ToConstructor | ListSpec; } +export type WithoutRefField = T extends RefField ? never : T; export function Cast | ListSpec>(field: FieldResult, ctor: T): FieldResult>; -export function Cast | ListSpec>(field: FieldResult, ctor: T, defaultVal: WithoutList> | null): WithoutList>; +export function Cast | ListSpec>(field: FieldResult, ctor: T, defaultVal: WithoutList>> | null): WithoutList>; export function Cast | ListSpec>(field: FieldResult, ctor: T, defaultVal?: ToType | null): FieldResult> | undefined { if (field instanceof Promise) { return defaultVal === undefined ? field.then(f => Cast(f, ctor) as any) as any : defaultVal === null ? undefined : defaultVal; -- cgit v1.2.3-70-g09d2 From 1d00e2e05acabe938ee496b6bf4bea55e82056e7 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 9 Jul 2019 14:18:12 -0400 Subject: fixed ink marqueeing. fixed link following on clicks. commented out link displays. --- src/client/documents/Documents.ts | 1 - .../collections/collectionFreeForm/MarqueeView.tsx | 26 +++++++++++----- src/client/views/nodes/DocumentView.tsx | 36 ++++++++-------------- src/new_fields/Doc.ts | 2 +- 4 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2bddf053a..109afeeb0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -59,7 +59,6 @@ export interface DocumentOptions { x?: number; y?: number; type?: string; - ink?: InkField; width?: number; height?: number; nativeWidth?: number; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index c83e1e3f5..8a619bfae 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,7 +1,7 @@ import * as htmlToImage from "html-to-image"; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../../new_fields/Doc"; +import { Doc, FieldResult } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; @@ -224,6 +224,18 @@ export class MarqueeView extends React.Component return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) }; } + get ink() { + let container = this.props.container.Document; + let containerKey = this.props.container.props.fieldKey; + return Cast(container[containerKey + "_ink"], InkField); + } + + set ink(value: InkField | undefined) { + let container = Doc.GetProto(this.props.container.Document); + let containerKey = this.props.container.props.fieldKey; + container[containerKey + "_ink"] = value; + } + @undoBatch @action marqueeCommand = async (e: KeyboardEvent) => { @@ -235,9 +247,8 @@ export class MarqueeView extends React.Component e.stopPropagation(); (e as any).propagationIsStopped = true; this.marqueeSelect().map(d => this.props.removeDocument(d)); - let ink = Cast(this.props.container.props.Document.ink, InkField); - if (ink) { - this.marqueeInkDelete(ink.inkData); + if (this.ink) { + this.marqueeInkDelete(this.ink.inkData); } SelectionManager.DeselectAll(); this.cleanupInteractions(false); @@ -259,8 +270,7 @@ export class MarqueeView extends React.Component return d; }); } - let ink = Cast(this.props.container.props.Document.ink, InkField); - let inkData = ink ? ink.inkData : undefined; + let inkData = this.ink ? this.ink.inkData : undefined; let newCollection = Docs.FreeformDocument(selected, { x: bounds.left, y: bounds.top, @@ -269,9 +279,9 @@ export class MarqueeView extends React.Component backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white", width: bounds.width, height: bounds.height, - ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined, title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection", }); + newCollection.data_ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined; this.marqueeInkDelete(inkData); if (e.key === "s") { @@ -348,7 +358,7 @@ export class MarqueeView extends React.Component let idata = new Map(); ink.forEach((value: StrokeData, key: string, map: any) => !InkingCanvas.IntersectStrokeRect(value, this.Bounds) && idata.set(key, value)); - Doc.SetOnPrototype(this.props.container.props.Document, "ink", new InkField(idata)); + this.ink = new InkField(idata); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 47ec3b5a1..430409ee3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -339,30 +339,18 @@ export class DocumentView extends DocComponent(Docu } } else if (linkedDocs.length) { - let linkedDoc = linkedDocs.length ? linkedDocs[0] : expandedDocs[0]; - let linkedPages = [linkedDocs.length ? NumCast(linkedDocs[0].anchor1Page, undefined) : NumCast(linkedDocs[0].anchor2Page, undefined), - linkedDocs.length ? NumCast(linkedDocs[0].anchor2Page, undefined) : NumCast(linkedDocs[0].anchor1Page, undefined)]; - let maxLocation = StrCast(linkedDoc.maximizeLocation, "inTab"); - DocumentManager.Instance.jumpToDocument(linkedDoc, ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedPages[altKey ? 1 : 0]); - - // else if (linkedToDocs.length || linkedFromDocs.length) { - // let linkedFwdDocs = [ - // linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : expandedDocs[0], - // linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : expandedDocs[0]]; - - // let linkedFwdContextDocs = [ - // linkedToDocs.length ? await (linkedToDocs[0].linkedToContext) as Doc : linkedFromDocs.length ? await PromiseValue(linkedFromDocs[0].linkedFromContext) as Doc : undefined, - // linkedFromDocs.length ? await (linkedFromDocs[0].linkedFromContext) as Doc : linkedToDocs.length ? await PromiseValue(linkedToDocs[0].linkedToContext) as Doc : undefined]; - - // let linkedFwdPage = [ - // linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : undefined, - // linkedFromDocs.length ? NumCast(linkedFromDocs[0].linkedFromPage, undefined) : linkedToDocs.length ? NumCast(linkedToDocs[0].linkedToPage, undefined) : undefined]; - - // if (!linkedFwdDocs.some(l => l instanceof Promise)) { - // let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 0].maximizeLocation, "inTab"); - // let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; - // DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext); - // } + let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document)); + let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]]; + + let linkedFwdContextDocs = [first.length ? await (first[0].context) as Doc : undefined, undefined]; + + let linkedFwdPage = [first.length ? NumCast(first[0].linkedToPage, undefined) : undefined, undefined]; + + if (!linkedFwdDocs.some(l => l instanceof Promise)) { + let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab"); + let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => this.props.addDocTab(document, undefined, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext); + } } } } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index aa13b1d7a..a07f56ca4 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -277,7 +277,7 @@ export namespace Doc { } // - // Resolves a reference to a field by returning 'doc' if o field extension is specified, + // Resolves a reference to a field by returning 'doc' if field extension is specified, // otherwise, it returns the extension document stored in doc._ext. // This mechanism allows any fields to be extended with an extension document that can // be used to capture field-specific metadata. For example, an image field can be extended -- cgit v1.2.3-70-g09d2