aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
authorStanley <syip0810@gmail.com>2019-05-19 14:10:53 -0700
committerStanley <syip0810@gmail.com>2019-05-19 14:10:53 -0700
commiteec769b586d4a1c6e73c4ce4ae78b4b8f2d4762b (patch)
tree7218f2df63e028391e40a084d41bce72fd43e00c /src/client/util
parent2cc62cd88688ccdec8275fcaaba939d448f9baf5 (diff)
parent01a223f2e6685506cc1e5db69e9062d5ff0d3246 (diff)
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into pdf_impl
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/DocumentManager.ts52
-rw-r--r--src/client/util/DragManager.ts8
-rw-r--r--src/client/util/History.ts122
-rw-r--r--src/client/util/RichTextSchema.tsx16
-rw-r--r--src/client/util/SearchUtil.ts25
-rw-r--r--src/client/util/TooltipTextMenu.tsx14
6 files changed, 199 insertions, 38 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 9a7a94228..d06af6dd5 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,10 +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';
export class DocumentManager {
@@ -26,28 +30,35 @@ export class DocumentManager {
// this.DocumentViews = new Array<DocumentView>();
}
- public getDocumentView(toFind: Doc): 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 === toFind) {
- 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 && Object.is(doc, toFind)) {
+ 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, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null {
+ return this.getDocumentViewById(toFind[Id], preferredCollection);
+ }
+
public getDocumentViews(toFind: Doc): DocumentView[] {
let toReturn: DocumentView[] = [];
@@ -104,20 +115,21 @@ export class DocumentManager {
}
@undoBatch
- public jumpToDocument = async (doc: Doc): Promise<void> => {
+ public jumpToDocument = async (docDelegate: Doc, makeCopy: boolean = true): Promise<void> => {
+ let doc = docDelegate.proto ? docDelegate.proto : docDelegate;
+ const page = NumCast(doc.page, undefined);
+ const contextDoc = await Cast(doc.annotationOn, Doc);
+ if (contextDoc) {
+ const curPage = NumCast(contextDoc.curPage, page);
+ if (page !== curPage) contextDoc.curPage = page;
+ }
let docView = DocumentManager.Instance.getDocumentView(doc);
if (docView) {
docView.props.focus(docView.props.Document);
} else {
- const contextDoc = await Cast(doc.annotationOn, Doc);
if (!contextDoc) {
- CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(doc));
+ CollectionDockingView.Instance.AddRightSplit(docDelegate ? (makeCopy ? Doc.MakeCopy(docDelegate) : docDelegate) : Doc.MakeDelegate(doc));
} else {
- const page = NumCast(doc.page, undefined);
- const curPage = NumCast(contextDoc.curPage, undefined);
- if (page !== curPage) {
- contextDoc.curPage = page;
- }
let contextView = DocumentManager.Instance.getDocumentView(contextDoc);
if (contextView) {
contextDoc.panTransformType = "Ease";
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2da0d5b51..7f75a95f0 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -41,7 +41,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);
@@ -105,7 +105,8 @@ export namespace DragManager {
constructor(
readonly x: number,
readonly y: number,
- readonly data: { [id: string]: any }
+ readonly data: { [id: string]: any },
+ readonly mods: string
) { }
}
@@ -334,7 +335,8 @@ export namespace DragManager {
detail: {
x: e.x,
y: e.y,
- data: dragData
+ data: dragData,
+ mods: e.altKey ? "AltKey" : ""
}
})
);
diff --git a/src/client/util/History.ts b/src/client/util/History.ts
new file mode 100644
index 000000000..545ea8629
--- /dev/null
+++ b/src/client/util/History.ts
@@ -0,0 +1,122 @@
+import { Doc, Opt, Field } from "../../new_fields/Doc";
+import { DocServer } from "../DocServer";
+import { RouteStore } from "../../server/RouteStore";
+import { MainView } from "../views/MainView";
+
+export namespace HistoryUtil {
+ export interface DocInitializerList {
+ [key: string]: string | number;
+ }
+
+ export interface DocUrl {
+ type: "doc";
+ docId: string;
+ initializers: {
+ [docId: string]: DocInitializerList;
+ };
+ }
+
+ export type ParsedUrl = DocUrl;
+
+ // const handlers: ((state: ParsedUrl | null) => void)[] = [];
+ function onHistory(e: PopStateEvent) {
+ if (window.location.pathname !== RouteStore.home) {
+ const url = e.state as ParsedUrl || parseUrl(window.location.pathname);
+ if (url) {
+ switch (url.type) {
+ case "doc":
+ onDocUrl(url);
+ break;
+ }
+ }
+ }
+ // for (const handler of handlers) {
+ // handler(e.state);
+ // }
+ }
+
+ export function pushState(state: ParsedUrl) {
+ history.pushState(state, "", createUrl(state));
+ }
+
+ export function replaceState(state: ParsedUrl) {
+ history.replaceState(state, "", createUrl(state));
+ }
+
+ function copyState(state: ParsedUrl): ParsedUrl {
+ return JSON.parse(JSON.stringify(state));
+ }
+
+ export function getState(): ParsedUrl {
+ return copyState(history.state);
+ }
+
+ // export function addHandler(handler: (state: ParsedUrl | null) => void) {
+ // handlers.push(handler);
+ // }
+
+ // export function removeHandler(handler: (state: ParsedUrl | null) => void) {
+ // const index = handlers.indexOf(handler);
+ // if (index !== -1) {
+ // handlers.splice(index, 1);
+ // }
+ // }
+
+ export function parseUrl(pathname: string): ParsedUrl | undefined {
+ let pathnameSplit = pathname.split("/");
+ if (pathnameSplit.length !== 2) {
+ return undefined;
+ }
+ const type = pathnameSplit[0];
+ const data = pathnameSplit[1];
+
+ if (type === "doc") {
+ const s = data.split("?");
+ if (s.length < 1 || s.length > 2) {
+ return undefined;
+ }
+ const docId = s[0];
+ const initializers = s.length === 2 ? JSON.parse(decodeURIComponent(s[1])) : {};
+ return {
+ type: "doc",
+ docId,
+ initializers
+ };
+ }
+
+ return undefined;
+ }
+
+ export function createUrl(params: ParsedUrl): string {
+ let baseUrl = DocServer.prepend(`/${params.type}`);
+ switch (params.type) {
+ case "doc":
+ const initializers = encodeURIComponent(JSON.stringify(params.initializers));
+ const id = params.docId;
+ let url = baseUrl + `/${id}`;
+ if (Object.keys(params.initializers).length) {
+ url += `?${initializers}`;
+ }
+ return url;
+ }
+ return "";
+ }
+
+ export async function initDoc(id: string, initializer: DocInitializerList) {
+ const doc = await DocServer.GetRefField(id);
+ if (!(doc instanceof Doc)) {
+ return;
+ }
+ Doc.assign(doc, initializer);
+ }
+
+ async function onDocUrl(url: DocUrl) {
+ 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) {
+ MainView.Instance.openWorkspace(field, true);
+ }
+ }
+
+ window.onpopstate = onHistory;
+}
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index c0e6f7899..3e3e98206 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 }];
}
},
@@ -375,7 +375,7 @@ export class ImageResizeView {
const currentX = e.pageX;
const diffInPx = currentX - startX;
self._outer.style.width = `${startWidth + diffInPx}`;
- }
+ };
const onpointerup = () => {
document.removeEventListener("pointermove", onpointermove);
@@ -384,11 +384,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/SearchUtil.ts b/src/client/util/SearchUtil.ts
new file mode 100644
index 000000000..4ccff0d1b
--- /dev/null
+++ b/src/client/util/SearchUtil.ts
@@ -0,0 +1,25 @@
+import * as rp from 'request-promise';
+import { DocServer } from '../DocServer';
+import { Doc } from '../../new_fields/Doc';
+import { Id } from '../../new_fields/RefField';
+
+export namespace SearchUtil {
+ export function Search(query: string, returnDocs: true): Promise<Doc[]>;
+ export function Search(query: string, returnDocs: false): Promise<string[]>;
+ export async function Search(query: string, returnDocs: boolean) {
+ const ids = JSON.parse(await rp.get(DocServer.prepend("/search"), {
+ qs: { query }
+ }));
+ if (!returnDocs) {
+ return ids;
+ }
+ const docMap = await DocServer.GetRefFields(ids);
+ return ids.map((id: string) => docMap[id]).filter((doc: any) => doc instanceof Doc);
+ }
+
+ 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);
+ }
+} \ No newline at end of file
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 6eb654319..4d40d09b2 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -175,7 +175,7 @@ export class TooltipTextMenu {
this.linkText.style.width = "150px";
this.linkText.style.overflow = "hidden";
this.linkText.style.color = "white";
- this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); }
+ this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); };
let linkBtn = document.createElement("div");
linkBtn.textContent = ">>";
linkBtn.style.width = "20px";
@@ -186,14 +186,14 @@ 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/"), "");
DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
if (f instanceof Doc) {
- if (DocumentManager.Instance.getDocumentView(f))
+ if (DocumentManager.Instance.getDocumentView(f)) {
DocumentManager.Instance.getDocumentView(f)!.props.focus(f);
+ }
else CollectionDockingView.Instance.AddRightSplit(f);
}
}));
@@ -201,7 +201,7 @@ export class TooltipTextMenu {
e.stopPropagation();
e.preventDefault();
}
- }
+ };
this.linkDrag = document.createElement("img");
this.linkDrag.src = "https://seogurusnyc.com/wp-content/uploads/2016/12/link-1.png";
this.linkDrag.style.width = "20px";
@@ -216,12 +216,12 @@ export class TooltipTextMenu {
{
handlers: {
dragComplete: action(() => {
- let m = dragData.droppedDocuments as Doc[];
+ let m = dragData.droppedDocuments;
this.makeLink(DocServer.prepend("/doc/" + m[0][Id]));
}),
},
hideSource: false
- })
+ });
};
this.linkEditor.appendChild(this.linkDrag);
this.linkEditor.appendChild(this.linkText);
@@ -239,7 +239,7 @@ export class TooltipTextMenu {
e.stopPropagation();
e.preventDefault();
}
- }
+ };
this.tooltip.appendChild(this.linkEditor);
}