diff options
| author | bob <bcz@cs.brown.edu> | 2019-06-11 10:53:36 -0400 |
|---|---|---|
| committer | bob <bcz@cs.brown.edu> | 2019-06-11 10:53:36 -0400 |
| commit | 95674ee7f68782d1ce85858120efea956825bcb9 (patch) | |
| tree | 0d2ddc9838b45278d6533099f7030a9713d6413f /src/client/util | |
| parent | 4dacd1220e6a0ef73167f187f52f3b4c222c2586 (diff) | |
| parent | 06d5bb5c65da6f4a115ebf8118989115420bccef (diff) | |
merged embedded linking with master
Diffstat (limited to 'src/client/util')
| -rw-r--r-- | src/client/util/DocumentManager.ts | 78 | ||||
| -rw-r--r-- | src/client/util/DragManager.ts | 38 | ||||
| -rw-r--r-- | src/client/util/History.ts | 4 | ||||
| -rw-r--r-- | src/client/util/RichTextSchema.tsx | 16 | ||||
| -rw-r--r-- | src/client/util/Scripting.ts | 10 | ||||
| -rw-r--r-- | src/client/util/SearchUtil.ts | 5 | ||||
| -rw-r--r-- | src/client/util/SelectionManager.ts | 51 | ||||
| -rw-r--r-- | src/client/util/SerializationHelper.ts | 14 | ||||
| -rw-r--r-- | src/client/util/TooltipTextMenu.tsx | 8 | ||||
| -rw-r--r-- | src/client/util/type_decls.d | 161 |
10 files changed, 206 insertions, 179 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 51f5fbe9f..ff0c1560b 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,11 +1,14 @@ import { computed, observable } from 'mobx'; import { DocumentView } from '../views/nodes/DocumentView'; -import { Doc, DocListCast } from '../../new_fields/Doc'; +import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; import { undoBatch } from './UndoManager'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { Id } from '../../new_fields/RefField'; +import { CollectionView } from '../views/collections/CollectionView'; +import { CollectionPDFView } from '../views/collections/CollectionPDFView'; +import { CollectionVideoView } from '../views/collections/CollectionVideoView'; +import { Id } from '../../new_fields/FieldSymbols'; export class DocumentManager { @@ -27,31 +30,33 @@ export class DocumentManager { // this.DocumentViews = new Array<DocumentView>(); } - public getDocumentViewById(id: string): DocumentView | null { + public getDocumentViewById(id: string, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null { let toReturn: DocumentView | null = null; + let passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - //gets document view that is in a freeform canvas collection - DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id) { - toReturn = view; - return; - } - }); - if (!toReturn) { + for (let i = 0; i < passes.length; i++) { DocumentManager.Instance.DocumentViews.map(view => { - let doc = view.props.Document.proto; - if (doc && doc[Id] === id) { + if (view.props.Document[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; + return; } }); + if (!toReturn) { + DocumentManager.Instance.DocumentViews.map(view => { + let doc = view.props.Document.proto; + if (doc && doc[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { + toReturn = view; + } + }); + } } return toReturn; } - public getDocumentView(toFind: Doc): DocumentView | null { - return this.getDocumentViewById(toFind[Id]); + public getDocumentView(toFind: Doc, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null { + return this.getDocumentViewById(toFind[Id], preferredCollection); } public getDocumentViews(toFind: Doc): DocumentView[] { @@ -110,26 +115,51 @@ export class DocumentManager { } @undoBatch - public jumpToDocument = async (doc: Doc): Promise<void> => { - const page = NumCast(doc.page, undefined); + public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number, docContext?: Doc): Promise<void> => { + let doc = Doc.GetProto(docDelegate); const contextDoc = await Cast(doc.annotationOn, Doc); if (contextDoc) { + const page = NumCast(doc.page, linkPage || 0); const curPage = NumCast(contextDoc.curPage, page); if (page !== curPage) contextDoc.curPage = page; } - let docView = DocumentManager.Instance.getDocumentView(doc); - if (docView) { + + let docView: DocumentView | null; + // using forceDockFunc as a flag for splitting linked to doc to the right...can change later if needed + if (!forceDockFunc && (docView = DocumentManager.Instance.getDocumentView(doc))) { + docView.props.Document.libraryBrush = true; + if (linkPage !== undefined) docView.props.Document.curPage = linkPage; docView.props.focus(docView.props.Document); } else { if (!contextDoc) { - CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(doc)); + if (docContext) { + let targetContextView: DocumentView | null; + if (!forceDockFunc && docContext && (targetContextView = DocumentManager.Instance.getDocumentView(docContext))) { + docContext.panTransformType = "Ease"; + targetContextView.props.focus(docDelegate); + } else { + (dockFunc || CollectionDockingView.Instance.AddRightSplit)(docContext); + setTimeout(() => { + this.jumpToDocument(docDelegate, forceDockFunc, dockFunc, linkPage); + }, 10); + } + } else { + const actualDoc = Doc.MakeAlias(docDelegate); + actualDoc.libraryBrush = true; + if (linkPage !== undefined) actualDoc.curPage = linkPage; + (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); + } } else { - let contextView = DocumentManager.Instance.getDocumentView(contextDoc); - if (contextView) { + let contextView: DocumentView | null; + docDelegate.libraryBrush = true; + if (!forceDockFunc && (contextView = DocumentManager.Instance.getDocumentView(contextDoc))) { contextDoc.panTransformType = "Ease"; - contextView.props.focus(contextDoc); + contextView.props.focus(docDelegate); } else { - CollectionDockingView.Instance.AddRightSplit(contextDoc); + (dockFunc || CollectionDockingView.Instance.AddRightSplit)(contextDoc); + setTimeout(() => { + this.jumpToDocument(docDelegate, forceDockFunc, dockFunc, linkPage); + }, 10); } } } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 29f0bc557..ab00fabe1 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,13 +1,14 @@ -import { action, runInAction } from "mobx"; +import { action, runInAction, observable } from "mobx"; import { Doc, DocListCastAsync } from "../../new_fields/Doc"; import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; import { URLField } from "../../new_fields/URLField"; +import { SelectionManager } from "./SelectionManager"; export type dropActionType = "alias" | "copy" | undefined; -export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () => Doc | Promise<Doc>, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { +export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () => Doc | Promise<Doc>, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { let onRowMove = async (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -17,6 +18,8 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () var dragData = new DragManager.DocumentDragData([await docFunc()]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; + dragData.options = options; + dragData.dontHideOnDrop = dontHideOnDrop; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); }; let onRowUp = (): void => { @@ -27,7 +30,7 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () // if (this.props.isSelected() || this.props.isTopMost) { if (e.button === 0) { e.stopPropagation(); - if (e.shiftKey) { + if (e.shiftKey && CollectionDockingView.Instance) { CollectionDockingView.Instance.StartOtherDrag([await docFunc()], e); } else { document.addEventListener("pointermove", onRowMove); @@ -42,7 +45,7 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: () export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; - let draggedFromDocs: Doc[] = [] + let draggedFromDocs: Doc[] = []; if (srcTarg) { let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); @@ -182,10 +185,10 @@ export namespace DragManager { export class EmbedDragData { constructor(embeddableSourceDoc: Doc) { this.embeddableSourceDoc = embeddableSourceDoc; - this.urlField = Cast(embeddableSourceDoc.data, URLField)!; + this.urlField = embeddableSourceDoc.data instanceof URLField ? embeddableSourceDoc.data : undefined; } embeddableSourceDoc: Doc; - urlField: URLField; + urlField?: URLField; [id: string]: any; } @@ -200,13 +203,14 @@ export namespace DragManager { export let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { + eles = eles.filter(e => e); if (!dragDiv) { dragDiv = document.createElement("div"); dragDiv.className = "dragManager-dragDiv"; dragDiv.style.pointerEvents = "none"; DragManager.Root().appendChild(dragDiv); } - + SelectionManager.SetIsDragging(true); let scaleXs: number[] = []; let scaleYs: number[] = []; let xs: number[] = []; @@ -256,6 +260,13 @@ export namespace DragManager { // pdfBox.replaceChild(img, pdfBox.children[0]) // } // } + let set = dragElement.getElementsByTagName('*'); + for (let i = 0; i < set.length; i++) + if (set[i].hasAttribute("style")) { + let s = set[i]; + (s as any).style.pointerEvents = "none"; + } + dragDiv.appendChild(dragElement); return dragElement; @@ -274,12 +285,11 @@ export namespace DragManager { let lastX = downX; let lastY = downY; const moveHandler = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); + e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined; } - if (e.shiftKey) { + if (e.shiftKey && CollectionDockingView.Instance) { AbortDrag(); CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, @@ -294,12 +304,12 @@ export namespace DragManager { lastX = e.pageX; lastY = e.pageY; dragElements.map((dragElement, i) => (dragElement.style.transform = - `translate(${(xs[i] += moveX)}px, ${(ys[i] += moveY)}px) - scale(${scaleXs[i]}, ${scaleYs[i]})`) + `translate(${(xs[i] += moveX)}px, ${(ys[i] += moveY)}px) scale(${scaleXs[i]}, ${scaleYs[i]})`) ); }; let hideDragElements = () => { + SelectionManager.SetIsDragging(false); dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); eles.map(ele => (ele.hidden = false)); }; @@ -325,7 +335,7 @@ export namespace DragManager { } function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { - let removed = dragEles.map(dragEle => { + let removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { // let parent = dragEle.parentElement; // if (parent) parent.removeChild(dragEle); let ret = [dragEle, dragEle.style.width, dragEle.style.height]; @@ -351,7 +361,7 @@ export namespace DragManager { x: e.x, y: e.y, data: dragData, - mods: e.ctrlKey ? "Control" : "" + mods: e.altKey ? "AltKey" : "" } }) ); diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 92d2b2b44..545ea8629 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,7 +1,7 @@ import { Doc, Opt, Field } from "../../new_fields/Doc"; import { DocServer } from "../DocServer"; -import { Main } from "../views/Main"; import { RouteStore } from "../../server/RouteStore"; +import { MainView } from "../views/MainView"; export namespace HistoryUtil { export interface DocInitializerList { @@ -114,7 +114,7 @@ export namespace HistoryUtil { const field = await DocServer.GetRefField(url.docId); await Promise.all(Object.keys(url.initializers).map(id => initDoc(id, url.initializers[id]))); if (field instanceof Doc) { - Main.Instance.openWorkspace(field, true); + MainView.Instance.openWorkspace(field, true); } } diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 742ac5434..2b82a09a2 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -97,13 +97,13 @@ export const nodes: { [index: string]: NodeSpec } = { title: dom.getAttribute("title"), alt: dom.getAttribute("alt"), width: Math.min(100, Number(dom.getAttribute("width"))), - } + }; } }], // TODO if we don't define toDom, something weird happens: dragging the image will not move it but clone it. Why? toDOM(node) { - const attrs = { style: `width: ${node.attrs.width}` } - return ["img", { ...node.attrs, ...attrs }] + const attrs = { style: `width: ${node.attrs.width}` }; + return ["img", { ...node.attrs, ...attrs }]; } }, @@ -401,7 +401,7 @@ export class ImageResizeView { const currentX = e.pageX; const diffInPx = currentX - startX; self._outer.style.width = `${startWidth + diffInPx}`; - } + }; const onpointerup = () => { document.removeEventListener("pointermove", onpointermove); @@ -410,11 +410,11 @@ export class ImageResizeView { view.state.tr.setNodeMarkup(getPos(), null, { src: node.attrs.src, width: self._outer.style.width }) .setSelection(view.state.selection)); - } + }; - document.addEventListener("pointermove", onpointermove) - document.addEventListener("pointerup", onpointerup) - } + document.addEventListener("pointermove", onpointermove); + document.addEventListener("pointerup", onpointerup); + }; this._outer.appendChild(this._handle); this._outer.appendChild(this._img); diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index e45f61c11..40e2ad6bb 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -12,6 +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'; export interface ScriptSucccess { success: true; @@ -41,11 +42,11 @@ 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 (errors || !script) { + if ((options.typecheck !== false && errors) || !script) { return { compiled: false, errors: diagnostics }; } - let fieldTypes = [Doc, ImageField, PdfField, VideoField, AudioField, List, RichTextField]; + 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}`); @@ -131,10 +132,11 @@ export interface ScriptOptions { addReturn?: boolean; params?: { [name: string]: string }; capturedVariables?: { [name: string]: Field }; + typecheck?: boolean; } export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult { - const { requiredType = "", addReturn = false, params = {}, capturedVariables = {} } = options; + const { requiredType = "", addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options; let host = new ScriptingCompilerHost; let paramNames: string[] = []; if ("this" in params || "this" in capturedVariables) { @@ -158,7 +160,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp ${addReturn ? `return ${script};` : script} })`; host.writeFile("file.ts", funcScript); - host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); + if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); let program = ts.createProgram(["file.ts"], {}, host); let testResult = program.emit(); let outputText = host.readFile("file.js"); diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 4ccff0d1b..28ec8ca14 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -1,7 +1,7 @@ import * as rp from 'request-promise'; import { DocServer } from '../DocServer'; import { Doc } from '../../new_fields/Doc'; -import { Id } from '../../new_fields/RefField'; +import { Id } from '../../new_fields/FieldSymbols'; export namespace SearchUtil { export function Search(query: string, returnDocs: true): Promise<Doc[]>; @@ -20,6 +20,7 @@ export namespace SearchUtil { export async function GetAliasesOfDocument(doc: Doc): Promise<Doc[]> { const proto = await Doc.GetT(doc, "proto", Doc, true); const protoId = (proto || doc)[Id]; - return Search(`{!join from=id to=proto_i}id:${protoId}`, true); + return Search(`proto_i:"${protoId}"`, true); + // return Search(`{!join from=id to=proto_i}id:${protoId}`, true); } }
\ No newline at end of file diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 8c92c2023..b26032b04 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,4 +1,4 @@ -import { observable, action } from "mobx"; +import { observable, action, runInAction } from "mobx"; import { Doc } from "../../new_fields/Doc"; import { DocumentView } from "../views/nodes/DocumentView"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; @@ -6,44 +6,44 @@ import { NumCast } from "../../new_fields/Types"; export namespace SelectionManager { class Manager { - @observable - SelectedDocuments: Array<DocumentView> = []; + @observable IsDragging: boolean = false; + @observable SelectedDocuments: Array<DocumentView> = []; @action - SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { + SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { // if doc is not in SelectedDocuments, add it if (!ctrlPressed) { this.DeselectAll(); } - if (manager.SelectedDocuments.indexOf(doc) === -1) { - manager.SelectedDocuments.push(doc); - doc.props.whenActiveChanged(true); + if (manager.SelectedDocuments.indexOf(docView) === -1) { + manager.SelectedDocuments.push(docView); + docView.props.whenActiveChanged(true); + } + } + @action + DeselectDoc(docView: DocumentView): void { + let ind = manager.SelectedDocuments.indexOf(docView); + if (ind !== -1) { + manager.SelectedDocuments.splice(ind, 1); + docView.props.whenActiveChanged(false); } } - @action DeselectAll(): void { manager.SelectedDocuments.map(dv => dv.props.whenActiveChanged(false)); manager.SelectedDocuments = []; FormattedTextBox.InputBoxOverlay = undefined; } - @action - ReselectAll() { - let sdocs = manager.SelectedDocuments.map(d => d); - manager.SelectedDocuments = []; - return sdocs; - } - @action - ReselectAll2(sdocs: DocumentView[]) { - sdocs.map(s => SelectionManager.SelectDoc(s, true)); - } } const manager = new Manager(); - export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { - manager.SelectDoc(doc, ctrlPressed); + export function DeselectDoc(docView: DocumentView): void { + manager.DeselectDoc(docView); + } + export function SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { + manager.SelectDoc(docView, ctrlPressed); } export function IsSelected(doc: DocumentView): boolean { @@ -62,14 +62,13 @@ export namespace SelectionManager { if (found) manager.SelectDoc(found, false); } - export function ReselectAll() { - let sdocs = manager.ReselectAll(); - setTimeout(() => manager.ReselectAll2(sdocs), 0); - } + export function SetIsDragging(dragging: boolean) { runInAction(() => manager.IsDragging = dragging); } + export function GetIsDragging() { return manager.IsDragging; } + export function SelectedDocuments(): Array<DocumentView> { return manager.SelectedDocuments; } - export function ViewsSortedVertically(): DocumentView[] { + export function ViewsSortedHorizontally(): DocumentView[] { let sorted = SelectionManager.SelectedDocuments().slice().sort((doc1, doc2) => { if (NumCast(doc1.props.Document.x) > NumCast(doc2.props.Document.x)) return 1; if (NumCast(doc1.props.Document.x) < NumCast(doc2.props.Document.x)) return -1; @@ -77,7 +76,7 @@ export namespace SelectionManager { }); return sorted; } - export function ViewsSortedHorizontally(): DocumentView[] { + export function ViewsSortedVertically(): DocumentView[] { let sorted = SelectionManager.SelectedDocuments().slice().sort((doc1, doc2) => { if (NumCast(doc1.props.Document.y) > NumCast(doc2.props.Document.y)) return 1; if (NumCast(doc1.props.Document.y) < NumCast(doc2.props.Document.y)) return -1; diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index 7ded85e43..a7246d7c4 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -45,13 +45,17 @@ export namespace SerializationHelper { throw Error(`type '${obj.__type}' not registered. Make sure you register it using a @Deserializable decorator`); } - const value = deserialize(serializationTypes[obj.__type], obj); + const type = serializationTypes[obj.__type]; + const value = deserialize(type.ctor, obj); + if (type.afterDeserialize) { + type.afterDeserialize(value); + } serializing -= 1; return value; } } -let serializationTypes: { [name: string]: any } = {}; +let serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void } } = {}; let reverseMap: { [ctor: string]: string } = {}; export interface DeserializableOpts { @@ -59,9 +63,9 @@ export interface DeserializableOpts { withFields(fields: string[]): Function; } -export function Deserializable(name: string): DeserializableOpts; +export function Deserializable(name: string, afterDeserialize?: (obj: any) => void): DeserializableOpts; export function Deserializable(constructor: { new(...args: any[]): any }): void; -export function Deserializable(constructor: { new(...args: any[]): any } | string): DeserializableOpts | void { +export function Deserializable(constructor: { new(...args: any[]): any } | string, afterDeserialize?: (obj: any) => void): DeserializableOpts | void { function addToMap(name: string, ctor: { new(...args: any[]): any }) { const schema = getDefaultModelSchema(ctor) as any; if (schema.targetClass !== ctor) { @@ -69,7 +73,7 @@ export function Deserializable(constructor: { new(...args: any[]): any } | strin setDefaultModelSchema(ctor, newSchema); } if (!(name in serializationTypes)) { - serializationTypes[name] = ctor; + serializationTypes[name] = { ctor, afterDeserialize }; reverseMap[ctor.name] = name; } else { throw new Error(`Name ${name} has already been registered as deserializable`); diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index b860f6758..ab6cd246a 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -23,12 +23,12 @@ const { openPrompt, TextField } = require("./ProsemirrorCopy/prompt.js"); import { View } from "@react-pdf/renderer"; import { DragManager } from "./DragManager"; import { Doc, Opt, Field } from "../../new_fields/Doc"; -import { Id } from "../../new_fields/RefField"; import { Utils } from "../northstar/utils/Utils"; import { DocServer } from "../DocServer"; import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { DocumentManager } from "./DocumentManager"; +import { Id } from "../../new_fields/FieldSymbols"; const SVG = "http://www.w3.org/2000/svg"; @@ -196,7 +196,6 @@ export class TooltipTextMenu { let node = this.view.state.selection.$from.nodeAfter; let link = node && node.marks.find(m => m.type.name === "link"); if (link) { - console.log("Link to : " + link.attrs.href); let href: string = link.attrs.href; if (href.indexOf(DocServer.prepend("/doc/")) === 0) { let docid = href.replace(DocServer.prepend("/doc/"), ""); @@ -205,10 +204,11 @@ export class TooltipTextMenu { if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); } - else CollectionDockingView.Instance.AddRightSplit(f); + else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f); } })); } + // TODO This should have an else to handle external links e.stopPropagation(); e.preventDefault(); } @@ -227,7 +227,7 @@ export class TooltipTextMenu { { handlers: { dragComplete: action(() => { - let m = dragData.droppedDocuments as Doc[]; + let m = dragData.droppedDocuments; this.makeLink(DocServer.prepend("/doc/" + m[0][Id])); }), }, diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d index 47c3481b2..2cbe1dd40 100644 --- a/src/client/util/type_decls.d +++ b/src/client/util/type_decls.d @@ -119,107 +119,88 @@ interface URL { username: string; toJSON(): string; } - -declare type FieldId = string; - -declare abstract class Field { - Id: FieldId; - abstract ToScriptString(): string; - abstract TrySetValue(value: any): boolean; - abstract GetValue(): any; - abstract Copy(): Field; +interface PromiseLike<T> { + then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>; } - -declare abstract class BasicField<T> extends Field { - constructor(data: T); - Data: T; - TrySetValue(value: any): boolean; - GetValue(): any; +interface Promise<T> { + then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>; + catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>; } -declare class TextField extends BasicField<string>{ - constructor(); - constructor(data: string); - ToScriptString(): string; - Copy(): Field; -} -declare class ImageField extends BasicField<URL>{ +declare const Update: unique symbol; +declare const Self: unique symbol; +declare const SelfProxy: unique symbol; +declare const HandleUpdate: unique symbol; +declare const Id: unique symbol; +declare const OnUpdate: unique symbol; +declare const Parent: unique symbol; +declare const Copy: unique symbol; +declare const ToScriptString: unique symbol; + +declare abstract class RefField { + readonly [Id]: FieldId; + constructor(); - constructor(data: URL); - ToScriptString(): string; - Copy(): Field; } -declare class HtmlField extends BasicField<string>{ - constructor(); - constructor(data: string); - ToScriptString(): string; - Copy(): Field; + +declare type FieldId = string; + +declare abstract class ObjectField { + abstract [Copy](): ObjectField; } -declare class NumberField extends BasicField<number>{ - constructor(); - constructor(data: number); - ToScriptString(): string; - Copy(): Field; + +declare abstract class URLField extends ObjectField { + readonly url: URL; + + constructor(url: string); + constructor(url: URL); } -declare class WebField extends BasicField<URL>{ + +declare class AudioField extends URLField { [Copy](): ObjectField; } +declare class VideoField extends URLField { [Copy](): ObjectField; } +declare class ImageField extends URLField { [Copy](): ObjectField; } +declare class WebField extends URLField { [Copy](): ObjectField; } +declare class PdfField extends URLField { [Copy](): ObjectField; } + +declare const ComputedField: any; +declare const CompileScript: any; + +// @ts-ignore +declare type Extract<T, U> = T extends U ? T : never; +declare type Field = number | string | boolean | ObjectField | RefField; +declare type FieldWaiting<T extends RefField = RefField> = T extends undefined ? never : Promise<T | undefined>; +declare type FieldResult<T extends Field = Field> = Opt<T> | FieldWaiting<Extract<T, RefField>>; + +declare type Opt<T> = T | undefined; +declare class Doc extends RefField { constructor(); - constructor(data: URL); - ToScriptString(): string; - Copy(): Field; + + [key: string]: FieldResult; + // [ToScriptString](): string; } -declare class ListField<T> extends BasicField<T[]>{ - constructor(); - constructor(data: T[]); - ToScriptString(): string; - Copy(): Field; -} -declare class Key extends Field { - constructor(name:string); - Name: string; - TrySetValue(value: any): boolean; - GetValue(): any; - Copy(): Field; - ToScriptString(): string; -} -declare type FIELD_WAITING = null; -declare type Opt<T> = T | undefined; -declare type FieldValue<T> = Opt<T> | FIELD_WAITING; -// @ts-ignore -declare class Document extends Field { - TrySetValue(value: any): boolean; - GetValue(): any; - Copy(): Field; - ToScriptString(): string; - - Width(): number; - Height(): number; - Scale(): number; - Title: string; - - Get(key: Key): FieldValue<Field>; - GetAsync(key: Key, callback: (field: Field) => void): boolean; - GetOrCreateAsync<T extends Field>(key: Key, ctor: { new(): T }, callback: (field: T) => void): void; - GetT<T extends Field>(key: Key, ctor: { new(): T }): FieldValue<T>; - GetOrCreate<T extends Field>(key: Key, ctor: { new(): T }): T; - GetData<T, U extends Field & { Data: T }>(key: Key, ctor: { new(): U }, defaultVal: T): T; - GetHtml(key: Key, defaultVal: string): string; - GetNumber(key: Key, defaultVal: number): number; - GetText(key: Key, defaultVal: string): string; - GetList<T extends Field>(key: Key, defaultVal: T[]): T[]; - Set(key: Key, field: Field | undefined): void; - SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }): void; - SetText(key: Key, value: string): void; - SetNumber(key: Key, value: number): void; - GetPrototype(): FieldValue<Document>; - GetAllPrototypes(): Document[]; - MakeDelegate(): Document; -} - -declare const KeyStore: { - [name: string]: Key; + +declare class ListImpl<T extends Field> extends ObjectField { + constructor(fields?: T[]); + [index: number]: T | (T extends RefField ? Promise<T> : never); + [Copy](): ObjectField; } // @ts-ignore declare const console: any; -declare const Documents: any; +interface DocumentOptions { } + +declare const Docs: { + ImageDocument(url: string, options?: DocumentOptions): Doc; + VideoDocument(url: string, options?: DocumentOptions): Doc; + // HistogramDocument(url:string, options?:DocumentOptions); + TextDocument(options?: DocumentOptions): Doc; + PdfDocument(url: string, options?: DocumentOptions): Doc; + WebDocument(url: string, options?: DocumentOptions): Doc; + HtmlDocument(html: string, options?: DocumentOptions): Doc; + KVPDocument(document: Doc, options?: DocumentOptions): Doc; + FreeformDocument(documents: Doc[], options?: DocumentOptions): Doc; + SchemaDocument(columns: string[], documents: Doc[], options?: DocumentOptions): Doc; + TreeDocument(documents: Doc[], options?: DocumentOptions): Doc; + StackingDocument(documents: Doc[], options?: DocumentOptions): Doc; +}; |
