aboutsummaryrefslogtreecommitdiff
path: root/src/client/documents/Documents.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r--src/client/documents/Documents.ts783
1 files changed, 460 insertions, 323 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index d1c9feb32..31e7eef2c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -25,7 +25,7 @@ import { OmitKeys } from "../../Utils";
import { ImageField, VideoField, AudioField, PdfField, WebField } from "../../new_fields/URLField";
import { HtmlField } from "../../new_fields/HtmlField";
import { List } from "../../new_fields/List";
-import { Cast, NumCast, StrCast } from "../../new_fields/Types";
+import { Cast, NumCast, StrCast, ToConstructor, InterfaceValue } from "../../new_fields/Types";
import { IconField } from "../../new_fields/IconField";
import { listSpec } from "../../new_fields/Schema";
import { DocServer } from "../DocServer";
@@ -34,6 +34,7 @@ import { dropActionType } from "../util/DragManager";
import { DateField } from "../../new_fields/DateField";
import { UndoManager } from "../util/UndoManager";
import { RouteStore } from "../../server/RouteStore";
+import { CollectionDockingView } from "../views/collections/CollectionDockingView";
import { LinkManager } from "../util/LinkManager";
import { DocumentManager } from "../util/DocumentManager";
import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox";
@@ -43,18 +44,42 @@ var path = require('path');
export enum DocTypes {
NONE = "none",
- IMG = "image",
- HIST = "histogram",
- ICON = "icon",
TEXT = "text",
- PDF = "pdf",
+ HIST = "histogram",
+ IMG = "image",
WEB = "web",
COL = "collection",
KVP = "kvp",
VID = "video",
AUDIO = "audio",
- LINK = "link",
- IMPORT = "import"
+ PDF = "pdf",
+ ICON = "icon",
+ IMPORT = "import",
+ LINK = "link"
+}
+
+export namespace DocTypeUtils {
+
+ export function values(includeNone: boolean = true): string[] {
+ let types = Object.values(DocTypes);
+ return includeNone ? types : types.filter(key => key !== DocTypes.NONE);
+ }
+
+ export function keys(includeNone: boolean = true): string[] {
+ let types = Object.keys(DocTypes);
+ return includeNone ? types : types.filter(key => key !== DocTypes.NONE);
+ }
+
+ export function toObject<T extends string>(o: Array<T>): { [K in T]: K } {
+ return o.reduce((res, key) => {
+ res[key] = key;
+ return res;
+ }, Object.create(null));
+ }
+
+ const Types = toObject(values());
+
+ export type All = keyof typeof Types;
}
export interface DocumentOptions {
@@ -84,362 +109,474 @@ export interface DocumentOptions {
dbDoc?: Doc;
// [key: string]: Opt<Field>;
}
-const delegateKeys = ["x", "y", "width", "height", "panX", "panY"];
-export namespace DocUtils {
- export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", tags: string = "Default") {
- if (LinkManager.Instance.doesLinkExist(source, target)) return;
- let sv = DocumentManager.Instance.getDocumentView(source);
- if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return;
- if (target === CurrentUserUtils.UserDocument) return;
+export namespace Docs {
- UndoManager.RunInBatch(() => {
- let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: "100%" });
- linkDoc.type = DocTypes.LINK;
- let linkDocProto = Doc.GetProto(linkDoc);
+ export namespace Prototypes {
- linkDocProto.context = targetContext;
- linkDocProto.title = title === "" ? source.title + " to " + target.title : title;
- linkDocProto.linkDescription = description;
- linkDocProto.linkTags = tags;
- linkDocProto.type = DocTypes.LINK;
+ type PrototypeTemplate = { options?: Partial<DocumentOptions>, primary: string, background?: string };
+ type TemplateMap = Map<DocTypeUtils.All, PrototypeTemplate>;
+ type PrototypeMap = Map<DocTypeUtils.All, Doc>;
- linkDocProto.anchor1 = source;
- linkDocProto.anchor1Page = source.curPage;
- linkDocProto.anchor1Groups = new List<Doc>([]);
- linkDocProto.anchor2 = target;
- linkDocProto.anchor2Page = target.curPage;
- linkDocProto.anchor2Groups = new List<Doc>([]);
+ const LayoutMap: TemplateMap = new Map([
+ [DocTypes.TEXT, {
+ options: { height: 150, backgroundColor: "#f1efeb" },
+ primary: FormattedTextBox.LayoutString()
+ }],
+ [DocTypes.HIST, {
+ options: { nativeWidth: 600, curPage: 0 },
+ primary: CollectionView.LayoutString("annotations"),
+ background: HistogramBox.LayoutString()
+ }],
+ [DocTypes.IMG, {
+ options: { height: 300, backgroundColor: "black" },
+ primary: CollectionView.LayoutString("annotations"),
+ background: ImageBox.LayoutString()
+ }],
+ [DocTypes.WEB, {
+ options: { height: 300 },
+ primary: WebBox.LayoutString()
+ }],
+ [DocTypes.COL, {
+ options: { panX: 0, panY: 0, scale: 1, width: 500, height: 500 },
+ primary: CollectionView.LayoutString()
+ }],
+ [DocTypes.KVP, {
+ options: { height: 150 },
+ primary: KeyValueBox.LayoutString()
+ }],
+ [DocTypes.VID, {
+ options: { nativeWidth: 600, curPage: 0 },
+ primary: CollectionVideoView.LayoutString("annotations"),
+ background: VideoBox.LayoutString()
+ }],
+ [DocTypes.AUDIO, {
+ options: { height: 150 },
+ primary: AudioBox.LayoutString()
+ }],
+ [DocTypes.PDF, {
+ options: { nativeWidth: 1200, curPage: 1 },
+ primary: CollectionPDFView.LayoutString("annotations"),
+ background: PDFBox.LayoutString()
+ }],
+ [DocTypes.ICON, {
+ options: { width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE) },
+ primary: IconBox.LayoutString()
+ }],
+ [DocTypes.IMPORT, {
+ options: { height: 150 },
+ primary: DirectoryImportBox.LayoutString()
+ }]
+ ]);
- LinkManager.Instance.addLink(linkDoc);
+ const PrototypeMap: PrototypeMap = new Map();
- return linkDoc;
- }, "make link");
- }
-}
+ /**
+ * This function loads or initializes the prototype for each docment type.
+ *
+ * This is an asynchronous function because it has to attempt
+ * to fetch the prototype documents from the server.
+ *
+ * Once we have this object that maps the prototype ids to a potentially
+ * undefined document, we either initialize our private prototype
+ * variables with the document returned from the server or, if prototypes
+ * haven't been initialized, the newly initialized prototype document.
+ */
+ export async function initialize(): Promise<void> {
+ // non-guid string ids for each document prototype
+ let prototypeIds: string[] = DocTypeUtils.values(false).map(type => type + "Proto");
-export namespace Docs {
- let textProto: Doc;
- let histoProto: Doc;
- let imageProto: Doc;
- let webProto: Doc;
- let collProto: Doc;
- let kvpProto: Doc;
- let videoProto: Doc;
- let audioProto: Doc;
- let pdfProto: Doc;
- let iconProto: Doc;
- let importProto: Doc;
- // let linkProto: Doc;
- const textProtoId = "textProto";
- const histoProtoId = "histoProto";
- const pdfProtoId = "pdfProto";
- const imageProtoId = "imageProto";
- const webProtoId = "webProto";
- const collProtoId = "collectionProto";
- const kvpProtoId = "kvpProto";
- const videoProtoId = "videoProto";
- const audioProtoId = "audioProto";
- const iconProtoId = "iconProto";
- const importProtoId = "importProto";
- // const linkProtoId = "linkProto";
-
- export function initProtos(): Promise<void> {
- return DocServer.GetRefFields([textProtoId, histoProtoId, collProtoId, imageProtoId, webProtoId, kvpProtoId, videoProtoId, audioProtoId, pdfProtoId, iconProtoId]).then(fields => {
- textProto = fields[textProtoId] as Doc || CreateTextPrototype();
- histoProto = fields[histoProtoId] as Doc || CreateHistogramPrototype();
- collProto = fields[collProtoId] as Doc || CreateCollectionPrototype();
- imageProto = fields[imageProtoId] as Doc || CreateImagePrototype();
- webProto = fields[webProtoId] as Doc || CreateWebPrototype();
- kvpProto = fields[kvpProtoId] as Doc || CreateKVPPrototype();
- videoProto = fields[videoProtoId] as Doc || CreateVideoPrototype();
- audioProto = fields[audioProtoId] as Doc || CreateAudioPrototype();
- pdfProto = fields[pdfProtoId] as Doc || CreatePdfPrototype();
- iconProto = fields[iconProtoId] as Doc || CreateIconPrototype();
- importProto = fields[importProtoId] as Doc || CreateImportPrototype();
- });
- }
+ let defaultOptions: DocumentOptions = {
+ x: 0,
+ y: 0,
+ width: 300
+ };
- function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Doc {
- return Doc.assign(new Doc(protoId, true), { ...options, title: title, layout: layout });
- }
- function SetInstanceOptions<U extends Field>(doc: Doc, options: DocumentOptions, value: U) {
- const deleg = Doc.MakeDelegate(doc);
- deleg.data = value;
- return Doc.assign(deleg, options);
- }
- function SetDelegateOptions(doc: Doc, options: DocumentOptions, id?: string) {
- const deleg = Doc.MakeDelegate(doc, id);
- return Doc.assign(deleg, options);
- }
+ // fetch the actual prototype documents from the server
+ let actualProtos = await DocServer.GetRefFields(prototypeIds);
+ // initialize prototype documents
+ prototypeIds.map(id => {
+ let existing = actualProtos[id] as Doc;
+ if (existing) {
+ PrototypeMap.set(id, existing);
+ } else {
+ let template = LayoutMap.get(id.replace("Proto", ""));
+ if (template) {
+ PrototypeMap.set(id, buildPrototype(template, id, defaultOptions));
+ }
+ }
+ });
+ }
- function CreateImagePrototype(): Doc {
- let imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("annotations"),
- { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: ImageBox.LayoutString(), curPage: 0, type: DocTypes.IMG });
- return imageProto;
- }
+ export function get(type: string) {
+ return PrototypeMap.get(type)!;
+ }
- function CreateImportPrototype(): Doc {
- let importProto = setupPrototypeOptions(importProtoId, "IMPORT_PROTO", DirectoryImportBox.LayoutString(), { x: 0, y: 0, width: 600, height: 600, type: DocTypes.IMPORT });
- return importProto;
- }
+ /**
+ * This is a convenience method that is used to initialize
+ * prototype documents for the first time.
+ *
+ * @param protoId the id of the prototype, indicating the specific prototype
+ * to initialize (see the *protoId list at the top of the namespace)
+ * @param title the prototype document's title, follows *-PROTO
+ * @param layout the layout key for this prototype and thus the
+ * layout key that all delegates will inherit
+ * @param options any value specified in the DocumentOptions object likewise
+ * becomes the default value for that key for all delegates
+ */
+ function buildPrototype(template: PrototypeTemplate, prototypeId: string, defaultOptions: DocumentOptions): Doc {
+ let primary = template.primary;
+ let background = template.background;
+ let options = { ...defaultOptions, ...(template.options || {}), title: prototypeId.toUpperCase().replace("PROTO", "_PROTO") };
+ background && (options = { ...options, backgroundLayout: background, });
+ return Doc.assign(new Doc(prototypeId, true), { ...options, layout: primary, baseLayout: primary });
+ }
- function CreateHistogramPrototype(): Doc {
- let histoProto = setupPrototypeOptions(histoProtoId, "HISTO PROTO", CollectionView.LayoutString("annotations"),
- { x: 0, y: 0, width: 300, height: 300, backgroundColor: "black", backgroundLayout: HistogramBox.LayoutString(), type: DocTypes.HIST });
- return histoProto;
- }
- function CreateIconPrototype(): Doc {
- let iconProto = setupPrototypeOptions(iconProtoId, "ICON_PROTO", IconBox.LayoutString(),
- { x: 0, y: 0, width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE), type: DocTypes.ICON });
- return iconProto;
- }
- function CreateTextPrototype(): Doc {
- let textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
- { x: 0, y: 0, width: 300, backgroundColor: "#f1efeb", type: DocTypes.TEXT });
- return textProto;
- }
- function CreatePdfPrototype(): Doc {
- let pdfProto = setupPrototypeOptions(pdfProtoId, "PDF_PROTO", CollectionPDFView.LayoutString("annotations"),
- { x: 0, y: 0, width: 300, height: 300, backgroundLayout: PDFBox.LayoutString(), curPage: 1, type: DocTypes.PDF });
- return pdfProto;
- }
- function CreateWebPrototype(): Doc {
- let webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 300, type: DocTypes.WEB });
- return webProto;
- }
- function CreateCollectionPrototype(): Doc {
- let collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("data"),
- { panX: 0, panY: 0, scale: 1, width: 500, height: 500, type: DocTypes.COL });
- return collProto;
}
- function CreateKVPPrototype(): Doc {
- let kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150, type: DocTypes.KVP });
- return kvpProto;
- }
- function CreateVideoPrototype(): Doc {
- let videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("annotations"),
- { x: 0, y: 0, nativeWidth: 600, width: 300, backgroundLayout: VideoBox.LayoutString(), curPage: 0, type: DocTypes.VID });
- return videoProto;
- }
- function CreateAudioPrototype(): Doc {
- let audioProto = setupPrototypeOptions(audioProtoId, "AUDIO_PROTO", AudioBox.LayoutString(),
- { x: 0, y: 0, width: 300, height: 150, type: DocTypes.AUDIO });
- return audioProto;
- }
+ /**
+ * Encapsulates the factory used to create new document instances
+ * delegated from top-level prototypes
+ */
+ export namespace Create {
+
+ const delegateKeys = ["x", "y", "width", "height", "panX", "panY"];
+
+ /**
+ * This function receives the relevant document prototype and uses
+ * it to create a new of that base-level prototype, or the
+ * underlying data document, which it then delegates again
+ * to create the view document.
+ *
+ * It also takes the opportunity to register the user
+ * that created the document and the time of creation.
+ *
+ * @param proto the specific document prototype off of which to model
+ * this new instance (textProto, imageProto, etc.)
+ * @param data the Field to store at this new instance's data key
+ * @param options any initial values to provide for this new instance
+ * @param delegId if applicable, an existing document id. If undefined, Doc's
+ * constructor just generates a new GUID. This is currently used
+ * only when creating a DockDocument from the current user's already existing
+ * main document.
+ */
+ export function InstanceFromProto(proto: Doc, data: Field, options: DocumentOptions, delegId?: string) {
+ const { omit: protoProps, extract: delegateProps } = OmitKeys(options, delegateKeys);
- export function CreateInstance(proto: Doc, data: Field, options: DocumentOptions, delegId?: string) {
- const { omit: protoProps, extract: delegateProps } = OmitKeys(options, delegateKeys);
- if (!("author" in protoProps)) {
- protoProps.author = CurrentUserUtils.email;
+ if (!("author" in protoProps)) {
+ protoProps.author = CurrentUserUtils.email;
+ }
+
+ if (!("creationDate" in protoProps)) {
+ protoProps.creationDate = new DateField;
+ }
+
+ protoProps.isPrototype = true;
+
+ let dataDoc = MakeDataDelegate(proto, protoProps, data);
+ let viewDoc = Doc.MakeDelegate(dataDoc, delegId);
+
+ return Doc.assign(viewDoc, delegateProps);
}
- if (!("creationDate" in protoProps)) {
- protoProps.creationDate = new DateField;
+
+ /**
+ * This function receives the relevant top level document prototype
+ * and models a new instance by delegating from it.
+ *
+ * Note that it stores the data it recieves at the delegate's data key,
+ * and applies any document options to this new delegate / instance.
+ * @param proto the prototype from which to model this new delegate
+ * @param options initial values to apply to this new delegate
+ * @param value the data to store in this new delegate
+ */
+ function MakeDataDelegate<D extends Field>(proto: Doc, options: DocumentOptions, value: D) {
+ const deleg = Doc.MakeDelegate(proto);
+ deleg.data = value;
+ return Doc.assign(deleg, options);
}
- protoProps.isPrototype = true;
- return SetDelegateOptions(SetInstanceOptions(proto, protoProps, data), delegateProps, delegId);
- }
+ export function ImageDocument(url: string, options: DocumentOptions = {}) {
+ let inst = InstanceFromProto(Prototypes.get(DocTypes.IMG), new ImageField(new URL(url)), { title: path.basename(url), ...options });
+ requestImageSize(window.origin + RouteStore.corsProxy + "/" + url)
+ .then((size: any) => {
+ let aspect = size.height / size.width;
+ if (!inst.proto!.nativeWidth) {
+ inst.proto!.nativeWidth = size.width;
+ }
+ inst.proto!.nativeHeight = Number(inst.proto!.nativeWidth!) * aspect;
+ inst.proto!.height = NumCast(inst.proto!.width) * aspect;
+ })
+ .catch((err: any) => console.log(err));
+ return inst;
+ }
- export function ImageDocument(url: string, options: DocumentOptions = {}) {
- let inst = CreateInstance(imageProto, new ImageField(new URL(url)), { title: path.basename(url), ...options });
- requestImageSize(window.origin + RouteStore.corsProxy + "/" + url)
- .then((size: any) => {
- let aspect = size.height / size.width;
- if (!inst.proto!.nativeWidth) {
- inst.proto!.nativeWidth = size.width;
- }
- inst.proto!.nativeHeight = Number(inst.proto!.nativeWidth!) * aspect;
- inst.height = NumCast(inst.width) * aspect;
- })
- .catch((err: any) => console.log(err));
- return inst;
- // let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
- // [new URL(url), ImageField]);
- // doc.SetText(KeyStore.Caption, "my caption...");
- // doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
- // doc.SetText(KeyStore.OverlayLayout, FixedCaption());
- // return doc;
- }
- export function VideoDocument(url: string, options: DocumentOptions = {}) {
- return CreateInstance(videoProto, new VideoField(new URL(url)), options);
- }
- export function AudioDocument(url: string, options: DocumentOptions = {}) {
- return CreateInstance(audioProto, new AudioField(new URL(url)), options);
- }
+ export function VideoDocument(url: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.VID), new VideoField(new URL(url)), options);
+ }
- export function DirectoryImportDocument(options: DocumentOptions = {}) {
- return CreateInstance(importProto, new List<Doc>(), options);
- }
+ export function AudioDocument(url: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.AUDIO), new AudioField(new URL(url)), options);
+ }
- export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}) {
- return CreateInstance(histoProto, new HistogramField(histoOp), options);
- }
- export function TextDocument(options: DocumentOptions = {}) {
- return CreateInstance(textProto, "", options);
- }
- export function IconDocument(icon: string, options: DocumentOptions = {}) {
- return CreateInstance(iconProto, new IconField(icon), options);
- }
+ export function HistogramDocument(histoOp: HistogramOperation, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.HIST), new HistogramField(histoOp), options);
+ }
- export function PdfDocument(url: string, options: DocumentOptions = {}) {
- return CreateInstance(pdfProto, new PdfField(new URL(url)), options);
- }
+ export function TextDocument(options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.TEXT), "", options);
+ }
+
+ export function IconDocument(icon: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.ICON), new IconField(icon), options);
+ }
- export async function DBDocument(url: string, options: DocumentOptions = {}, columnOptions: DocumentOptions = {}) {
- let schemaName = options.title ? options.title : "-no schema-";
- let ctlog = await Gateway.Instance.GetSchema(url, schemaName);
- if (ctlog && ctlog.schemas) {
- let schema = ctlog.schemas[0];
- let schemaDoc = Docs.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! });
- let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []);
- if (!schemaDocuments) {
- return;
+ export function PdfDocument(url: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.PDF), new PdfField(new URL(url)), options);
+ }
+
+ export async function DBDocument(url: string, options: DocumentOptions = {}, columnOptions: DocumentOptions = {}) {
+ let schemaName = options.title ? options.title : "-no schema-";
+ let ctlog = await Gateway.Instance.GetSchema(url, schemaName);
+ if (ctlog && ctlog.schemas) {
+ let schema = ctlog.schemas[0];
+ let schemaDoc = Docs.Create.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! });
+ let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []);
+ if (!schemaDocuments) {
+ return;
+ }
+ CurrentUserUtils.AddNorthstarSchema(schema, schemaDoc);
+ const docs = schemaDocuments;
+ CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
+ DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+ if (field instanceof Doc) {
+ docs.push(field);
+ } else {
+ var atmod = new ColumnAttributeModel(attr);
+ let histoOp = new HistogramOperation(schema.displayName!,
+ new AttributeTransformationModel(atmod, AggregateFunction.None),
+ new AttributeTransformationModel(atmod, AggregateFunction.Count),
+ new AttributeTransformationModel(atmod, AggregateFunction.Count));
+ docs.push(Docs.Create.HistogramDocument(histoOp, { ...columnOptions, width: 200, height: 200, title: attr.displayName! }));
+ }
+ }));
+ });
+ return schemaDoc;
}
- CurrentUserUtils.AddNorthstarSchema(schema, schemaDoc);
- const docs = schemaDocuments;
- CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
- DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
- if (field instanceof Doc) {
- docs.push(field);
- } else {
- var atmod = new ColumnAttributeModel(attr);
- let histoOp = new HistogramOperation(schema.displayName!,
- new AttributeTransformationModel(atmod, AggregateFunction.None),
- new AttributeTransformationModel(atmod, AggregateFunction.Count),
- new AttributeTransformationModel(atmod, AggregateFunction.Count));
- docs.push(Docs.HistogramDocument(histoOp, { ...columnOptions, width: 200, height: 200, title: attr.displayName! }));
- }
- }));
- });
- return schemaDoc;
+ return Docs.Create.TreeDocument([], { width: 50, height: 100, title: schemaName });
}
- return Docs.TreeDocument([], { width: 50, height: 100, title: schemaName });
- }
- export function WebDocument(url: string, options: DocumentOptions = {}) {
- return CreateInstance(webProto, new WebField(new URL(url)), options);
- }
- export function HtmlDocument(html: string, options: DocumentOptions = {}) {
- return CreateInstance(webProto, new HtmlField(html), options);
- }
- export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
- return CreateInstance(kvpProto, document, { title: document.title + ".kvp", ...options });
- }
- export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, makePrototype: boolean = true) {
- if (!makePrototype) {
- return SetInstanceOptions(collProto, { ...options, viewType: CollectionViewType.Freeform }, new List(documents));
+
+ export function WebDocument(url: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.WEB), new WebField(new URL(url)), options);
}
- return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform });
- }
- export function SchemaDocument(schemaColumns: string[], documents: Array<Doc>, options: DocumentOptions) {
- return CreateInstance(collProto, new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema });
- }
- export function TreeDocument(documents: Array<Doc>, options: DocumentOptions) {
- return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree });
- }
- export function StackingDocument(documents: Array<Doc>, options: DocumentOptions) {
- return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking });
- }
- export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
- return CreateInstance(collProto, new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id);
- }
- export async function getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise<Opt<Doc>> {
- let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise<Doc | undefined>)) | undefined = undefined;
- if (type.indexOf("image") !== -1) {
- ctor = Docs.ImageDocument;
+ export function HtmlDocument(html: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.WEB), new HtmlField(html), options);
}
- if (type.indexOf("video") !== -1) {
- ctor = Docs.VideoDocument;
+
+ export function KVPDocument(document: Doc, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.KVP), document, { title: document.title + ".kvp", ...options });
}
- if (type.indexOf("audio") !== -1) {
- ctor = Docs.AudioDocument;
+
+ export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, makePrototype: boolean = true) {
+ if (!makePrototype) {
+ return MakeDataDelegate(Prototypes.get(DocTypes.COL), { ...options, viewType: CollectionViewType.Freeform }, new List(documents));
+ }
+ return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform });
}
- if (type.indexOf("pdf") !== -1) {
- ctor = Docs.PdfDocument;
- options.nativeWidth = 1200;
+
+ export function SchemaDocument(schemaColumns: string[], documents: Array<Doc>, options: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema });
}
- if (type.indexOf("excel") !== -1) {
- ctor = Docs.DBDocument;
- options.dropAction = "copy";
+
+ export function TreeDocument(documents: Array<Doc>, options: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree });
+ }
+
+ export function StackingDocument(documents: Array<Doc>, options: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking });
}
- if (type.indexOf("html") !== -1) {
- if (path.includes(window.location.hostname)) {
- let s = path.split('/');
- let id = s[s.length - 1];
- return DocServer.GetRefField(id).then(field => {
- if (field instanceof Doc) {
- let alias = Doc.MakeAlias(field);
- alias.x = options.x || 0;
- alias.y = options.y || 0;
- alias.width = options.width || 300;
- alias.height = options.height || options.width || 300;
- return alias;
+
+ export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
+ return InstanceFromProto(Prototypes.get(DocTypes.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id);
+ }
+
+ export function DirectoryImportDocument(options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocTypes.COL), new List<Doc>(), options);
+ }
+
+ export type DocConfig = {
+ doc: Doc,
+ initialWidth?: number
+ };
+
+ export function StandardCollectionDockingDocument(configs: Array<DocConfig>, options: DocumentOptions, id?: string, type: string = "row") {
+ let layoutConfig = {
+ content: [
+ {
+ type: type,
+ content: [
+ ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth))
+ ]
}
- return undefined;
- });
- }
- ctor = Docs.WebDocument;
- options = { height: options.width, ...options, title: path, nativeWidth: undefined };
+ ]
+ };
+ return DockDocument(configs.map(c => c.doc), JSON.stringify(layoutConfig), options, id);
}
- return ctor ? ctor(path, options) : undefined;
}
- export function CaptionDocument(doc: Doc) {
- const captionDoc = Doc.MakeAlias(doc);
- captionDoc.overlayLayout = FixedCaption();
- captionDoc.width = Cast(doc.width, "number", 0);
- captionDoc.height = Cast(doc.height, "number", 0);
- return captionDoc;
- }
+ export namespace Get {
- // example of custom display string for an image that shows a caption.
- function EmbeddedCaption() {
- return `<div style="height:100%">
- <div style="position:relative; margin:auto; height:85%; width:85%;" >`
- + ImageBox.LayoutString() +
- `</div>
- <div style="position:relative; height:15%; text-align:center; ">`
- + FormattedTextBox.LayoutString("caption") +
- `</div>
- </div>`;
- }
- export function FixedCaption(fieldName: string = "caption") {
- return `<div style="position:absolute; height:30px; bottom:0; width:100%">
- <div style="position:absolute; width:100%; height:100%; text-align:center;bottom:0;">`
- + FormattedTextBox.LayoutString(fieldName) +
- `</div>
- </div>`;
- }
+ export async function DocumentFromType(type: string, path: string, options: DocumentOptions): Promise<Opt<Doc>> {
+ let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise<Doc | undefined>)) | undefined = undefined;
+ if (type.indexOf("image") !== -1) {
+ ctor = Docs.Create.ImageDocument;
+ }
+ if (type.indexOf("video") !== -1) {
+ ctor = Docs.Create.VideoDocument;
+ }
+ if (type.indexOf("audio") !== -1) {
+ ctor = Docs.Create.AudioDocument;
+ }
+ if (type.indexOf("pdf") !== -1) {
+ ctor = Docs.Create.PdfDocument;
+ options.nativeWidth = 1200;
+ }
+ if (type.indexOf("excel") !== -1) {
+ ctor = Docs.Create.DBDocument;
+ options.dropAction = "copy";
+ }
+ if (type.indexOf("html") !== -1) {
+ if (path.includes(window.location.hostname)) {
+ let s = path.split('/');
+ let id = s[s.length - 1];
+ return DocServer.GetRefField(id).then(field => {
+ if (field instanceof Doc) {
+ let alias = Doc.MakeAlias(field);
+ alias.x = options.x || 0;
+ alias.y = options.y || 0;
+ alias.width = options.width || 300;
+ alias.height = options.height || options.width || 300;
+ return alias;
+ }
+ return undefined;
+ });
+ }
+ ctor = Docs.Create.WebDocument;
+ options = { height: options.width, ...options, title: path, nativeWidth: undefined };
+ }
+ return ctor ? ctor(path, options) : undefined;
+ }
- function OuterCaption() {
- return (`
-<div>
- <div style="margin:auto; height:calc(100%); width:100%;">
- {layout}
- </div>
- <div style="height:(100% + 25px); width:100%; position:absolute">
- <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} renderDepth={renderDepth}/>
- </div>
-</div>
- `);
}
- function InnerCaption() {
- return (`
- <div>
- <div style="margin:auto; height:calc(100% - 25px); width:100%;">
- {layout}
- </div>
- <div style="height:25px; width:100%; position:absolute">
- <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={"caption"} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} renderDepth={renderDepth}/>
- </div>
- </div>
+
+ export namespace Templating {
+
+ export function CaptionDocument(doc: Doc) {
+ const captionDoc = Doc.MakeAlias(doc);
+ captionDoc.overlayLayout = FixedCaption();
+ captionDoc.width = Cast(doc.width, "number", 0);
+ captionDoc.height = Cast(doc.height, "number", 0);
+ return captionDoc;
+ }
+
+ /**
+ * An example of custom display string for an image that shows a caption.
+ */
+ export function EmbeddedCaption() {
+ return (
+ `<div style="height:100%">
+ <div style="position:relative; margin:auto; height:85%; width:85%;" >${ImageBox.LayoutString()}</div>
+ <div style="position:relative; height:15%; text-align:center; ">${FormattedTextBox.LayoutString("caption")}</div>
+ </div>`
+ );
+ }
+
+ export function FixedCaption(fieldName: string = "caption") {
+ return (
+ `<div style="position:absolute; height:30px; bottom:0; width:100%">
+ <div style="position:absolute; width:100%; height:100%; text-align:center;bottom:0;">${FormattedTextBox.LayoutString(fieldName)}</div>
+ </div>`
+ );
+ }
+
+ export function OuterCaption() {
+ return (`
+ <div>
+ <div style="margin:auto; height:calc(100%); width:100%;">
+ {layout}
+ </div>
+ <div style="height:(100% + 25px); width:100%; position:absolute">
+ <FormattedTextBox
+ doc={Document}
+ DocumentViewForField={DocumentView}
+ bindings={bindings}
+ fieldKey={"caption"}
+ isSelected={isSelected}
+ select={select}
+ selectOnLoad={SelectOnLoad}
+ renderDepth={renderDepth
+ />
+ </div>
+ </div>
+ `);
+ }
+
+ export function InnerCaption() {
+ return (`
+ <div>
+ <div style="margin:auto; height:calc(100% - 25px); width:100%;">
+ {layout}
+ </div>
+ <div style="height:25px; width:100%; position:absolute">
+ <FormattedTextBox
+ doc={Document}
+ DocumentViewForField={DocumentView}
+ bindings={bindings}
+ fieldKey={"caption"}
+ isSelected={isSelected}
+ select={select}
+ selectOnLoad={SelectOnLoad}
+ renderDepth={renderDepth
+ />
+ </div>
+ </div>
`);
+ }
+ }
+}
+
+export namespace DocUtils {
+
+ export function MakeLink(source: Doc, target: Doc, targetContext?: Doc, title: string = "", description: string = "", tags: string = "Default") {
+ if (LinkManager.Instance.doesLinkExist(source, target)) return;
+ let sv = DocumentManager.Instance.getDocumentView(source);
+ if (sv && sv.props.ContainingCollectionView && sv.props.ContainingCollectionView.props.Document === target) return;
+ if (target === CurrentUserUtils.UserDocument) return;
+
+ UndoManager.RunInBatch(() => {
+ let linkDoc = Docs.Create.TextDocument({ width: 100, height: 30, borderRounding: "100%" });
+ linkDoc.type = DocTypes.LINK;
+ let linkDocProto = Doc.GetProto(linkDoc);
+
+ linkDocProto.context = targetContext;
+ linkDocProto.title = title === "" ? source.title + " to " + target.title : title;
+ linkDocProto.linkDescription = description;
+ linkDocProto.linkTags = tags;
+ linkDocProto.type = DocTypes.LINK;
+
+ linkDocProto.anchor1 = source;
+ linkDocProto.anchor1Page = source.curPage;
+ linkDocProto.anchor1Groups = new List<Doc>([]);
+ linkDocProto.anchor2 = target;
+ linkDocProto.anchor2Page = target.curPage;
+ linkDocProto.anchor2Groups = new List<Doc>([]);
+
+ LinkManager.Instance.addLink(linkDoc);
+
+ return linkDoc;
+ }, "make link");
}
}
-Scripting.addGlobal("Docs", Docs); \ No newline at end of file
+Scripting.addGlobal("Docs", Docs);