aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/DocumentManager.ts60
-rw-r--r--src/client/util/DragManager.ts295
-rw-r--r--src/client/util/Scripting.ts10
-rw-r--r--src/client/util/SelectionManager.ts21
-rw-r--r--src/client/util/type_decls.d10
5 files changed, 270 insertions, 126 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 5b99b4ef8..bf59fbb43 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,8 +1,11 @@
import React = require('react')
import { observer } from 'mobx-react';
-import { observable, action } from 'mobx';
+import { observable, action, computed } from 'mobx';
import { Document } from "../../fields/Document"
import { DocumentView } from '../views/nodes/DocumentView';
+import { KeyStore } from '../../fields/KeyStore';
+import { FieldWaiting } from '../../fields/Field';
+import { ListField } from '../../fields/ListField';
export class DocumentManager {
@@ -24,6 +27,11 @@ export class DocumentManager {
// this.DocumentViews = new Array<DocumentView>();
}
+ public getAllDocumentViews(collection: Document) {
+ return this.DocumentViews.filter(dv =>
+ dv.props.ContainingCollectionView && dv.props.ContainingCollectionView.props.Document == collection);
+ }
+
public getDocumentView(toFind: Document): DocumentView | null {
let toReturn: DocumentView | null;
@@ -33,19 +41,59 @@ export class DocumentManager {
DocumentManager.Instance.DocumentViews.map(view => {
let doc = view.props.Document;
// if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
- // if (Object.is(doc, toFind)) {
- // toReturn = view;
- // return;
- // }
- // }
if (Object.is(doc, toFind)) {
toReturn = view;
return;
}
+ let docSrc = doc.GetT(KeyStore.Prototype, Document);
+ if (docSrc && docSrc != FieldWaiting && Object.is(docSrc, toFind)) {
+ toReturn = view;
+ }
+ })
+ return (toReturn);
+ }
+ public getDocumentViews(toFind: Document): DocumentView[] {
+
+ let toReturn: DocumentView[] = [];
+
+ //gets document view that is in a freeform canvas collection
+ DocumentManager.Instance.DocumentViews.map(view => {
+ let doc = view.props.Document;
+ // if (view.props.ContainingCollectionView instanceof CollectionFreeFormView) {
+
+ if (Object.is(doc, toFind)) {
+ toReturn.push(view);
+ } else {
+ let docSrc = doc.GetT(KeyStore.Prototype, Document);
+ if (docSrc && docSrc != FieldWaiting && Object.is(docSrc, toFind)) {
+ toReturn.push(view);
+ }
+ }
})
return (toReturn);
}
+
+ @computed
+ public get LinkedDocumentViews() {
+ return DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => {
+ let linksList = dv.props.Document.GetT(KeyStore.LinkedToDocs, ListField);
+ if (linksList && linksList != FieldWaiting && linksList.Data.length) {
+ pairs.push(...linksList.Data.reduce((pairs, link) => {
+ if (link instanceof Document) {
+ let linkToDoc = link.GetT(KeyStore.LinkedToDocs, Document);
+ if (linkToDoc && linkToDoc != FieldWaiting) {
+ DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
+ pairs.push({ a: dv, b: docView1, l: link })
+ })
+ }
+ }
+ return pairs;
+ }, [] as { a: DocumentView, b: DocumentView, l: Document }[]));
+ }
+ return pairs;
+ }, [] as { a: DocumentView, b: DocumentView, l: Document }[]);
+ }
} \ No newline at end of file
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 753115f76..e8f8cce7c 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,40 +1,48 @@
import { DocumentDecorations } from "../views/DocumentDecorations";
import { CollectionDockingView } from "../views/collections/CollectionDockingView";
-import { Document } from "../../fields/Document"
+import { Document } from "../../fields/Document";
import { action } from "mobx";
import { ImageField } from "../../fields/ImageField";
import { KeyStore } from "../../fields/KeyStore";
import { CollectionView } from "../views/collections/CollectionView";
import { DocumentView } from "../views/nodes/DocumentView";
-export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, removeFunc: (containingCollection: CollectionView) => void = () => { }) {
- let onRowMove = action((e: PointerEvent): void => {
- e.stopPropagation();
- e.preventDefault();
-
- document.removeEventListener("pointermove", onRowMove);
- document.removeEventListener('pointerup', onRowUp);
- var dragData = new DragManager.DocumentDragData(docFunc());
- dragData.removeDocument = removeFunc;
- DragManager.StartDocumentDrag(_reference.current!, dragData);
- });
- let onRowUp = action((e: PointerEvent): void => {
- document.removeEventListener("pointermove", onRowMove);
- document.removeEventListener('pointerup', onRowUp);
- });
+export function setupDrag(
+ _reference: React.RefObject<HTMLDivElement>,
+ docFunc: () => Document,
+ removeFunc: (containingCollection: CollectionView) => void = () => { }
+) {
+ let onRowMove = action(
+ (e: PointerEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ document.removeEventListener("pointermove", onRowMove);
+ document.removeEventListener("pointerup", onRowUp);
+ var dragData = new DragManager.DocumentDragData([docFunc()]);
+ dragData.removeDocument = removeFunc;
+ DragManager.StartDocumentDrag([_reference.current!], dragData);
+ }
+ );
+ let onRowUp = action(
+ (e: PointerEvent): void => {
+ document.removeEventListener("pointermove", onRowMove);
+ document.removeEventListener("pointerup", onRowUp);
+ }
+ );
let onItemDown = (e: React.PointerEvent) => {
// if (this.props.isSelected() || this.props.isTopMost) {
if (e.button == 0) {
e.stopPropagation();
if (e.shiftKey) {
- CollectionDockingView.Instance.StartOtherDrag(docFunc(), e);
+ CollectionDockingView.Instance.StartOtherDrag([docFunc()], e);
} else {
document.addEventListener("pointermove", onRowMove);
- document.addEventListener('pointerup', onRowUp);
+ document.addEventListener("pointerup", onRowUp);
}
}
//}
- }
+ };
return onItemDown;
}
@@ -50,7 +58,9 @@ export namespace DragManager {
let dragDiv: HTMLDivElement;
export enum DragButtons {
- Left = 1, Right = 2, Both = Left | Right
+ Left = 1,
+ Right = 2,
+ Both = Left | Right
}
interface DragOptions {
@@ -63,8 +73,7 @@ export namespace DragManager {
(): void;
}
- export class DragCompleteEvent {
- }
+ export class DragCompleteEvent { }
export interface DragHandlers {
dragComplete: (e: DragCompleteEvent) => void;
@@ -74,19 +83,25 @@ export namespace DragManager {
handlers: DropHandlers;
}
export class DropEvent {
- constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { }
+ constructor(
+ readonly x: number,
+ readonly y: number,
+ readonly data: { [id: string]: any }
+ ) { }
}
-
-
export interface DropHandlers {
drop: (e: Event, de: DropEvent) => void;
}
-
- export function MakeDropTarget(element: HTMLElement, options: DropOptions): DragDropDisposer {
+ export function MakeDropTarget(
+ element: HTMLElement,
+ options: DropOptions
+ ): DragDropDisposer {
if ("canDrop" in element.dataset) {
- throw new Error("Element is already droppable, can't make it droppable again");
+ throw new Error(
+ "Element is already droppable, can't make it droppable again"
+ );
}
element.dataset["canDrop"] = "true";
const handler = (e: Event) => {
@@ -96,78 +111,120 @@ export namespace DragManager {
element.addEventListener("dashOnDrop", handler);
return () => {
element.removeEventListener("dashOnDrop", handler);
- delete element.dataset["canDrop"]
+ delete element.dataset["canDrop"];
};
}
export class DocumentDragData {
- constructor(dragDoc: Document) {
- this.draggedDocument = dragDoc;
- this.droppedDocument = dragDoc;
+ constructor(dragDoc: Document[]) {
+ this.draggedDocuments = dragDoc;
+ this.droppedDocuments = dragDoc;
}
- draggedDocument: Document;
- droppedDocument: Document;
+ draggedDocuments: Document[];
+ droppedDocuments: Document[];
xOffset?: number;
yOffset?: number;
aliasOnDrop?: boolean;
removeDocument?: (collectionDrop: CollectionView) => void;
[id: string]: any;
}
- export function StartDocumentDrag(ele: HTMLElement, dragData: DocumentDragData, options?: DragOptions) {
- StartDrag(ele, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocument = dragData.aliasOnDrop ? dragData.draggedDocument.CreateAlias() : dragData.draggedDocument);
+
+ export function StartDocumentDrag(
+ eles: HTMLElement[],
+ dragData: DocumentDragData,
+ options?: DragOptions
+ ) {
+ StartDrag(
+ eles,
+ dragData,
+ options,
+ (dropData: { [id: string]: any }) =>
+ (dropData.droppedDocuments = dragData.aliasOnDrop
+ ? dragData.draggedDocuments.map(d => d.CreateAlias())
+ : dragData.draggedDocuments)
+ );
}
export class LinkDragData {
constructor(linkSourceDoc: DocumentView) {
this.linkSourceDocumentView = linkSourceDoc;
}
+ droppedDocuments: Document[] = [];
linkSourceDocumentView: DocumentView;
[id: string]: any;
}
- export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, options?: DragOptions) {
- StartDrag(ele, dragData, options);
+ export function StartLinkDrag(
+ ele: HTMLElement,
+ dragData: LinkDragData,
+ options?: DragOptions
+ ) {
+ StartDrag([ele], dragData, options);
}
- function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
+ function StartDrag(
+ eles: HTMLElement[],
+ dragData: { [id: string]: any },
+ options?: DragOptions,
+ finishDrag?: (dropData: { [id: string]: any }) => void
+ ) {
if (!dragDiv) {
dragDiv = document.createElement("div");
- dragDiv.className = "dragManager-dragDiv"
+ dragDiv.className = "dragManager-dragDiv";
DragManager.Root().appendChild(dragDiv);
}
- const w = ele.offsetWidth, h = ele.offsetHeight;
- const rect = ele.getBoundingClientRect();
- const scaleX = rect.width / w, scaleY = rect.height / h;
- let x = rect.left, y = rect.top;
- // const offsetX = e.x - rect.left, offsetY = e.y - rect.top;
-
- let dragElement = ele.cloneNode(true) as HTMLElement;
- dragElement.style.opacity = "0.7";
- dragElement.style.position = "absolute";
- dragElement.style.bottom = "";
- dragElement.style.left = "";
- dragElement.style.transformOrigin = "0 0";
- dragElement.style.zIndex = "1000";
- dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
- dragElement.style.width = `${rect.width / scaleX}px`;
- dragElement.style.height = `${rect.height / scaleY}px`;
-
- // bcz: PDFs don't show up if you clone them because they contain a canvas.
- // however, PDF's have a thumbnail field that contains an image of their canvas.
- // So we replace the pdf's canvas with the image thumbnail
- const doc: Document = dragData["draggedDocument"];
- if (doc) {
- var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
- let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField);
- if (pdfBox && pdfBox.childElementCount && thumbnail) {
- let img = new Image();
- img!.src = thumbnail.toString();
- img!.style.position = "absolute";
- img!.style.width = `${rect.width / scaleX}px`;
- img!.style.height = `${rect.height / scaleY}px`;
- pdfBox.replaceChild(img!, pdfBox.children[0])
+
+ let scaleXs: number[] = [];
+ let scaleYs: number[] = [];
+ let xs: number[] = [];
+ let ys: number[] = [];
+
+ const docs: Document[] =
+ dragData instanceof DocumentDragData ? dragData.draggedDocuments : [];
+ let dragElements = eles.map(ele => {
+ const w = ele.offsetWidth,
+ h = ele.offsetHeight;
+ const rect = ele.getBoundingClientRect();
+ const scaleX = rect.width / w,
+ scaleY = rect.height / h;
+ let x = rect.left,
+ y = rect.top;
+ xs.push(x);
+ ys.push(y);
+ scaleXs.push(scaleX);
+ scaleYs.push(scaleY);
+ let dragElement = ele.cloneNode(true) as HTMLElement;
+ dragElement.style.opacity = "0.7";
+ dragElement.style.position = "absolute";
+ dragElement.style.margin = "0";
+ dragElement.style.top = "0";
+ dragElement.style.bottom = "";
+ dragElement.style.left = "0";
+ dragElement.style.transformOrigin = "0 0";
+ dragElement.style.zIndex = "1000";
+ dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+ dragElement.style.width = `${rect.width / scaleX}px`;
+ dragElement.style.height = `${rect.height / scaleY}px`;
+
+ // bcz: PDFs don't show up if you clone them because they contain a canvas.
+ // however, PDF's have a thumbnail field that contains an image of their canvas.
+ // So we replace the pdf's canvas with the image thumbnail
+ if (docs.length) {
+ var pdfBox = dragElement.getElementsByClassName(
+ "pdfBox-cont"
+ )[0] as HTMLElement;
+ let thumbnail = docs[0].GetT(KeyStore.Thumbnail, ImageField);
+ if (pdfBox && pdfBox.childElementCount && thumbnail) {
+ let img = new Image();
+ img!.src = thumbnail.toString();
+ img!.style.position = "absolute";
+ img!.style.width = `${rect.width / scaleX}px`;
+ img!.style.height = `${rect.height / scaleY}px`;
+ pdfBox.replaceChild(img!, pdfBox.children[0]);
+ }
}
- }
- dragDiv.appendChild(dragElement);
+ dragDiv.appendChild(dragElement);
+ return dragElement;
+ });
let hideSource = false;
if (options) {
@@ -177,63 +234,81 @@ export namespace DragManager {
hideSource = options.hideSource();
}
}
- const wasHidden = ele.hidden;
- if (hideSource) {
- ele.hidden = true;
- }
+ eles.map(ele => (ele.hidden = hideSource));
+
const moveHandler = (e: PointerEvent) => {
e.stopPropagation();
e.preventDefault();
- x += e.movementX;
- y += e.movementY;
+ if (dragData instanceof DocumentDragData)
+ dragData.aliasOnDrop = e.ctrlKey || e.altKey;
if (e.shiftKey) {
abortDrag();
- CollectionDockingView.Instance.StartOtherDrag(doc, { pageX: e.pageX, pageY: e.pageY, preventDefault: () => { }, button: 0 });
+ CollectionDockingView.Instance.StartOtherDrag(docs, {
+ pageX: e.pageX,
+ pageY: e.pageY,
+ preventDefault: () => { },
+ button: 0
+ });
}
- dragElement.style.transform = `translate(${x}px, ${y}px) scale(${scaleX}, ${scaleY})`;
+ dragElements.map(
+ (dragElement, i) =>
+ (dragElement.style.transform = `translate(${(xs[i] +=
+ e.movementX)}px, ${(ys[i] += e.movementY)}px) scale(${
+ scaleXs[i]
+ }, ${scaleYs[i]})`)
+ );
};
const abortDrag = () => {
document.removeEventListener("pointermove", moveHandler, true);
document.removeEventListener("pointerup", upHandler);
- dragDiv.removeChild(dragElement);
- if (hideSource && !wasHidden) {
- ele.hidden = false;
- }
- }
+ dragElements.map(dragElement => dragDiv.removeChild(dragElement));
+ eles.map(ele => (ele.hidden = false));
+ };
const upHandler = (e: PointerEvent) => {
abortDrag();
- FinishDrag(ele, e, dragData, options, finishDrag);
+ FinishDrag(eles, e, dragData, options, finishDrag);
};
document.addEventListener("pointermove", moveHandler, true);
document.addEventListener("pointerup", upHandler);
}
- function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) {
- let parent = dragEle.parentElement;
- if (parent)
- parent.removeChild(dragEle);
+ function FinishDrag(
+ dragEles: HTMLElement[],
+ e: PointerEvent,
+ dragData: { [index: string]: any },
+ options?: DragOptions,
+ finishDrag?: (dragData: { [index: string]: any }) => void
+ ) {
+ let removed = dragEles.map(dragEle => {
+ let parent = dragEle.parentElement;
+ if (parent) parent.removeChild(dragEle);
+ return [dragEle, parent];
+ });
const target = document.elementFromPoint(e.x, e.y);
- if (parent)
- parent.appendChild(dragEle);
- if (!target) {
- return;
- }
- if (finishDrag)
- finishDrag(dragData);
-
- target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
- bubbles: true,
- detail: {
- x: e.x,
- y: e.y,
- data: dragData
- }
- }));
+ removed.map(r => {
+ let dragEle: HTMLElement = r[0]!;
+ let parent: HTMLElement | null = r[1];
+ if (parent) parent.appendChild(dragEle);
+ });
+ if (target) {
+ if (finishDrag) finishDrag(dragData);
- if (options) {
- options.handlers.dragComplete({});
+ target.dispatchEvent(
+ new CustomEvent<DropEvent>("dashOnDrop", {
+ bubbles: true,
+ detail: {
+ x: e.x,
+ y: e.y,
+ data: dragData
+ }
+ })
+ );
+
+ if (options) {
+ options.handlers.dragComplete({});
+ }
}
DocumentDecorations.Instance.Hidden = false;
}
-} \ No newline at end of file
+}
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 46bd1a206..4e97b9401 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -15,6 +15,8 @@ import { ListField } from "../../fields/ListField";
// @ts-ignore
import * as typescriptlib from '!!raw-loader!./type_decls.d'
+import { Documents } from "../documents/Documents";
+import { Key } from "../../fields/Key";
export interface ExecutableScript {
@@ -28,9 +30,9 @@ function Compile(script: string | undefined, diagnostics: Opt<any[]>, scope: { [
let func: () => Opt<Field>;
if (compiled && script) {
- let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField];
- let paramNames = ["KeyStore", ...fieldTypes.map(fn => fn.name)];
- let params: any[] = [KeyStore, ...fieldTypes]
+ let fieldTypes = [Document, NumberField, TextField, ImageField, RichTextField, ListField, Key];
+ let paramNames = ["KeyStore", "Documents", ...fieldTypes.map(fn => fn.name)];
+ let params: any[] = [KeyStore, Documents, ...fieldTypes]
for (let prop in scope) {
if (prop === "this") {
continue;
@@ -110,7 +112,7 @@ export function CompileScript(script: string, scope?: { [name: string]: any }, a
let host = new ScriptingCompilerHost;
let funcScript = `(function() {
${addReturn ? `return ${script};` : script}
- })()`
+ }).apply(this)`
host.writeFile("file.ts", funcScript);
host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
let program = ts.createProgram(["file.ts"], {}, host);
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 1a711ae64..958c14491 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -1,5 +1,6 @@
import { observable, action } from "mobx";
import { DocumentView } from "../views/nodes/DocumentView";
+import { Document } from "../../fields/Document";
export namespace SelectionManager {
class Manager {
@@ -14,26 +15,34 @@ export namespace SelectionManager {
}
if (manager.SelectedDocuments.indexOf(doc) === -1) {
- manager.SelectedDocuments.push(doc)
+ manager.SelectedDocuments.push(doc);
}
}
}
- const manager = new Manager;
+ const manager = new Manager();
export function SelectDoc(doc: DocumentView, ctrlPressed: boolean): void {
- manager.SelectDoc(doc, ctrlPressed)
+ manager.SelectDoc(doc, ctrlPressed);
}
export function IsSelected(doc: DocumentView): boolean {
return manager.SelectedDocuments.indexOf(doc) !== -1;
}
- export function DeselectAll(): void {
- manager.SelectedDocuments = []
+ export function DeselectAll(except?: Document): void {
+ let found: DocumentView | undefined = undefined;
+ if (except) {
+ for (let i = 0; i < manager.SelectedDocuments.length; i++) {
+ let view = manager.SelectedDocuments[i];
+ if (view.props.Document == except) found = view;
+ }
+ }
+ manager.SelectedDocuments.length = 0;
+ if (found) manager.SelectedDocuments.push(found);
}
export function SelectedDocuments(): Array<DocumentView> {
return manager.SelectedDocuments;
}
-} \ No newline at end of file
+}
diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d
index 679f73f42..4f69053b1 100644
--- a/src/client/util/type_decls.d
+++ b/src/client/util/type_decls.d
@@ -174,6 +174,7 @@ declare class ListField<T> extends BasicField<T[]>{
Copy(): Field;
}
declare class Key extends Field {
+ constructor(name:string);
Name: string;
TrySetValue(value: any): boolean;
GetValue(): any;
@@ -213,3 +214,12 @@ declare class Document extends Field {
GetAllPrototypes(): Document[];
MakeDelegate(): Document;
}
+
+declare const KeyStore: {
+ [name: string]: Key;
+}
+
+// @ts-ignore
+declare const console: any;
+
+declare const Documents: any;