aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/ApiManagers/UtilManager.ts13
-rw-r--r--src/server/DashUploadUtils.ts64
-rw-r--r--src/server/Message.ts2
-rw-r--r--src/server/RouteManager.ts1
-rw-r--r--src/server/Websocket/Websocket.ts3
-rw-r--r--src/server/authentication/models/current_user_utils.ts147
-rw-r--r--src/server/database.ts2
-rw-r--r--src/server/index.ts2
-rw-r--r--src/server/server_Initialization.ts1
-rw-r--r--src/server/updateProtos.ts3
10 files changed, 113 insertions, 125 deletions
diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts
index ad8119bf4..aec523cd0 100644
--- a/src/server/ApiManagers/UtilManager.ts
+++ b/src/server/ApiManagers/UtilManager.ts
@@ -14,19 +14,6 @@ export default class UtilManager extends ApiManager {
protected initialize(register: Registration): void {
- register({
- method: Method.GET,
- subscription: new RouteSubscriber("environment").add("key"),
- secureHandler: ({ req, res }) => {
- const { key } = req.params;
- const value = process.env[key];
- if (!value) {
- console.log(red(`process.env.${key} is not defined.`));
- }
- return res.send(value);
- }
- });
-
// register({
// method: Method.POST,
// subscription: "/IBMAnalysis",
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 2af816df8..9b518749c 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -1,4 +1,4 @@
-import { unlinkSync, createWriteStream, readFileSync, rename, writeFile } from 'fs';
+import { unlinkSync, createWriteStream, readFileSync, rename, writeFile, existsSync } from 'fs';
import { Utils } from '../Utils';
import * as path from 'path';
import * as sharp from 'sharp';
@@ -6,7 +6,7 @@ import request = require('request-promise');
import { ExifImage } from 'exif';
import { Opt } from '../new_fields/Doc';
import { AcceptibleMedia, Upload } from './SharedMediaTypes';
-import { filesDirectory } from '.';
+import { filesDirectory, publicDirectory } from '.';
import { File } from 'formidable';
import { basename } from "path";
import { createIfNotExists } from './ActionUtilities';
@@ -136,6 +136,16 @@ export namespace DashUploadUtils {
};
export async function buildFileDirectories() {
+ if (!existsSync(publicDirectory)) {
+ console.error("\nPlease ensure that the following directory exists...\n");
+ console.log(publicDirectory);
+ process.exit(0);
+ }
+ if (!existsSync(filesDirectory)) {
+ console.error("\nPlease ensure that the following directory exists...\n");
+ console.log(filesDirectory);
+ process.exit(0);
+ }
const pending = Object.keys(Directory).map(sub => createIfNotExists(`${filesDirectory}/${sub}`));
return Promise.all(pending);
}
@@ -160,6 +170,11 @@ export namespace DashUploadUtils {
export const InspectImage = async (source: string): Promise<Upload.InspectionResults | Error> => {
let rawMatches: RegExpExecArray | null;
let filename: string | undefined;
+ /**
+ * Just more edge case handling: this if clause handles the case where an image onto the canvas that
+ * is represented by a base64 encoded data uri, rather than a proper file. We manually write it out
+ * to the server and then carry on as if it had been put there by the Formidable form / file parser.
+ */
if ((rawMatches = /^data:image\/([a-z]+);base64,(.*)/.exec(source)) !== null) {
const [ext, data] = rawMatches.slice(1, 3);
const resolved = filename = `upload_${Utils.GenerateGuid()}.${ext}`;
@@ -172,21 +187,35 @@ export namespace DashUploadUtils {
source = `http://localhost:1050${clientPathToFile(Directory.images, resolved)}`;
}
let resolvedUrl: string;
+ /**
+ * At this point, we want to take whatever url we have and make sure it's requestable.
+ * Anything that's hosted by some other website already is, but if the url is a local file url
+ * (locates the file on this server machine), we have to resolve the client side url by cutting out the
+ * basename subtree (i.e. /images/<some_guid>.<ext>) and put it on the end of the server's url.
+ *
+ * This can always be localhost, regardless of whether this is on the server or not, since we (the server, not the client)
+ * will be the ones making the request, and from the perspective of dash-release or dash-web, localhost:1050 refers to the same thing
+ * as the full dash-release.eastus.cloudapp.azure.com:1050.
+ */
const matches = isLocal().exec(source);
if (matches === null) {
resolvedUrl = source;
} else {
resolvedUrl = `http://localhost:1050/${matches[1].split("\\").join("/")}`;
}
+ // See header comments: not all image files have exif data (I believe only JPG is the only format that can have it)
const exifData = await parseExifData(resolvedUrl);
const results = {
exifData,
requestable: resolvedUrl
};
+ // Use the request library to parse out file level image information in the headers
const { headers } = (await new Promise<any>((resolve, reject) => {
request.head(resolvedUrl, (error, res) => error ? reject(error) : resolve(res));
}).catch(error => console.error(error)));
+ // Compute the native width and height ofthe image with an npm module
const { width: nativeWidth, height: nativeHeight }: RequestedImageSize = await requestImageSize(resolvedUrl);
+ // Bundle up the information into an object
return {
source,
contentSize: parseInt(headers[size]),
@@ -198,6 +227,16 @@ export namespace DashUploadUtils {
};
};
+ /**
+ * Basically just a wrapper around rename, which 'deletes'
+ * the file at the old path and 'moves' it to the new one. For simplicity, the
+ * caller just has to pass in the name of the target directory, and this function
+ * will resolve the actual target path from that.
+ * @param file The file to move
+ * @param destination One of the specific media asset directories into which to move it
+ * @param suffix If the file doesn't have a suffix and you want to provide it one
+ * to appear in the new location
+ */
export async function MoveParsedFile(file: File, destination: Directory, suffix: string | undefined = undefined): Promise<Upload.FileResponse> {
const { path: sourcePath } = file;
let name = path.basename(sourcePath);
@@ -211,10 +250,8 @@ export namespace DashUploadUtils {
accessPaths: {
agnostic: getAccessPaths(destination, name)
}
-
}
- }
- );
+ });
});
});
}
@@ -246,9 +283,22 @@ export namespace DashUploadUtils {
return information;
};
+ const bufferConverterRec = (layer: any) => {
+ for (const key of Object.keys(layer)) {
+ const val: any = layer[key];
+ if (val instanceof Buffer) {
+ layer[key] = val.toString();
+ } else if (Array.isArray(val) && typeof val[0] === "number") {
+ layer[key] = Buffer.from(val).toString();
+ } else if (typeof val === "object") {
+ bufferConverterRec(val);
+ }
+ }
+ };
+
const parseExifData = async (source: string): Promise<Upload.EnrichedExifData> => {
const image = await request.get(source, { encoding: null });
- return new Promise(resolve => {
+ const { data, error } = await new Promise(resolve => {
new ExifImage({ image }, (error, data) => {
let reason: Opt<string> = undefined;
if (error) {
@@ -257,6 +307,8 @@ export namespace DashUploadUtils {
resolve({ data, error: reason });
});
});
+ data && bufferConverterRec(data);
+ return { data, error };
};
const { pngs, jpgs, webps, tiffs } = AcceptibleMedia;
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 81f63656b..01aae5de7 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -19,7 +19,7 @@ export class Message<T> {
export enum Types {
Number, List, Key, Image, Web, Document, Text, Icon, RichText, DocumentReference,
- Html, Video, Audio, Ink, PDF, Tuple, HistogramOp, Boolean, Script, Templates
+ Html, Video, Audio, Ink, PDF, Tuple, Boolean, Script, Templates
}
export interface Transferable {
diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts
index a8680c0c9..80e4a6741 100644
--- a/src/server/RouteManager.ts
+++ b/src/server/RouteManager.ts
@@ -2,7 +2,6 @@ import RouteSubscriber from "./RouteSubscriber";
import { DashUserModel } from "./authentication/models/user_model";
import { Request, Response, Express } from 'express';
import { cyan, red, green } from 'colors';
-import { Utils } from "../client/northstar/utils/Utils";
export enum Method {
GET,
diff --git a/src/server/Websocket/Websocket.ts b/src/server/Websocket/Websocket.ts
index 9f9fc9619..947aa4289 100644
--- a/src/server/Websocket/Websocket.ts
+++ b/src/server/Websocket/Websocket.ts
@@ -199,7 +199,7 @@ export namespace WebSocket {
function setField(socket: Socket, newValue: Transferable) {
Database.Instance.update(newValue.id, newValue, () =>
socket.broadcast.emit(MessageStore.SetField.Message, newValue));
- if (newValue.type === Types.Text) {
+ if (newValue.type === Types.Text) { // if the newValue has sring type, then it's suitable for searching -- pass it to SOLR
Search.updateDocument({ id: newValue.id, data: (newValue as any).data });
}
}
@@ -221,6 +221,7 @@ export namespace WebSocket {
"pdf": ["_t", "url"],
"audio": ["_t", "url"],
"web": ["_t", "url"],
+ "script": ["_t", value => value.script.originalScript],
"RichTextField": ["_t", value => value.Text],
"date": ["_d", value => new Date(value.date).toISOString()],
"proxy": ["_i", "fieldId"],
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index fc6e36485..9235a97b0 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -2,8 +2,6 @@ import { action, computed, observable, reaction } from "mobx";
import * as rp from 'request-promise';
import { DocServer } from "../../../client/DocServer";
import { Docs, DocumentOptions } from "../../../client/documents/Documents";
-import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea";
-import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil";
import { UndoManager } from "../../../client/util/UndoManager";
import { Doc, DocListCast } from "../../../new_fields/Doc";
import { List } from "../../../new_fields/List";
@@ -14,7 +12,7 @@ import { Utils } from "../../../Utils";
import { nullAudio, ImageField } from "../../../new_fields/URLField";
import { DragManager } from "../../../client/util/DragManager";
import { InkingControl } from "../../../client/views/InkingControl";
-import { Scripting } from "../../../client/util/Scripting";
+import { Scripting, CompileScript } from "../../../client/util/Scripting";
import { CollectionViewType } from "../../../client/views/collections/CollectionView";
import { makeTemplate } from "../../../client/util/DropConverter";
import { RichTextField } from "../../../new_fields/RichTextField";
@@ -59,9 +57,9 @@ export class CurrentUserUtils {
doc.iconView = new PrefetchProxy(Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
Doc.GetProto(doc.iconView as any as Doc).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', "");
doc.isTemplateDoc = makeTemplate(doc.iconView as any as Doc);
- doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
+ doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") }));
doc.isTemplateDoc = makeTemplate(doc.iconImageView as any as Doc, true, "image_icon");
- doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") }));
+ doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") }));
doc.isTemplateDoc = makeTemplate(doc.iconColView as any as Doc, true, "collection_icon");
doc.iconViews = Docs.Create.TreeDocument([doc.iconView as any as Doc, doc.iconImageView as any as Doc, doc.iconColView as any as Doc], { title: "icon types", _height: 75 });
}
@@ -75,13 +73,13 @@ export class CurrentUserUtils {
{ title: "collection", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: emptyCollection },
{ title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]"), { _width: 250, _height: 250, title: "container" })' },
{ title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", {_width: 300, _height: 300, title: "New Webpage" })' },
- { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 200, title: "an image of a cat" })' },
- { title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" },
+ { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' },
{ title: "screenshot", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' },
{ title: "webcam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' },
{ title: "record", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` },
{ title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, title: "Button" })' },
{ title: "presentation", icon: "tv", click: 'openOnRight(Doc.UserDoc().curPresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().curPresentation = getCopy(this.dragFactory,true)`, dragFactory: emptyPresentation },
+ { title: "script", icon: "terminal", ignoreClick: true, drag: 'Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250 title: "untitled script" })' },
{ title: "import folder", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' },
{ title: "mobile view", icon: "phone", ignoreClick: true, drag: 'Doc.UserDoc().activeMobile' },
{ title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", ischecked: `sameDocs(this.activePen.pen, this)`, activePen: doc },
@@ -90,8 +88,7 @@ export class CurrentUserUtils {
{ title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc },
{ title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', ischecked: `sameDocs(this.activePen.pen, this)`, backgroundColor: "white", activePen: doc },
{ title: "query", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' },
-
-
+ // { title: "buxton", icon: "cloud-upload-alt", ignoreClick: true, drag: "Docs.Create.Buxton()" },
];
return docProtoData.filter(d => !alreadyCreatedButtons?.includes(d.title)).map(data => Docs.Create.FontIconDocument({
_nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100,
@@ -99,9 +96,12 @@ export class CurrentUserUtils {
title: data.title,
ignoreClick: data.ignoreClick,
dropAction: data.click ? "copy" : undefined,
- onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
- ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined, activePen: data.activePen, dontDecorateSelection: true,
- backgroundColor: data.backgroundColor, removeDropProperties: new List<string>(["dropAction"]), dragFactory: data.dragFactory,
+ onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined,
+ onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
+ ischecked: data.ischecked ? ComputedField.MakeFunction(data.ischecked) : undefined,
+ activePen: data.activePen,
+ backgroundColor: data.backgroundColor, removeDropProperties: new List<string>(["dropAction"]),
+ dragFactory: data.dragFactory,
}));
}
@@ -166,9 +166,12 @@ export class CurrentUserUtils {
static setupThumbDoc(userDoc: Doc) {
if (!userDoc.thumbDoc) {
const thumbDoc = Docs.Create.LinearDocument(CurrentUserUtils.setupThumbButtons(userDoc), {
- _width: 100, _height: 50, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons", _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white"
+ _width: 100, _height: 50, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled", title: "buttons",
+ _autoHeight: true, _yMargin: 5, linearViewIsExpanded: true, backgroundColor: "white"
+ });
+ thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], {
+ _width: 300, _height: 25, _autoHeight: true, _chromeStatus: "disabled", linearViewIsExpanded: true, flexDirection: "column"
});
- thumbDoc.inkToTextDoc = Docs.Create.LinearDocument([], { _width: 300, _height: 25, _autoHeight: true, _chromeStatus: "disabled", linearViewIsExpanded: true, flexDirection: "column" });
userDoc.thumbDoc = thumbDoc;
}
return Cast(userDoc.thumbDoc, Doc);
@@ -210,7 +213,7 @@ export class CurrentUserUtils {
});
return Docs.Create.ButtonDocument({
- _width: 35, _height: 25, title: "Tools", fontSize: 10, targetContainer: sidebarContainer, dontDecorateSelection: true,
+ _width: 35, _height: 25, title: "Tools", fontSize: 10, targetContainer: sidebarContainer,
letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
sourcePanel: Docs.Create.StackingDocument([dragCreators, color], {
_width: 500, lockedPosition: true, _chromeStatus: "disabled", title: "tools stack", forceActive: true
@@ -236,7 +239,7 @@ export class CurrentUserUtils {
});
return Docs.Create.ButtonDocument({
- _width: 50, _height: 25, title: "Library", fontSize: 10, dontDecorateSelection: true,
+ _width: 50, _height: 25, title: "Library", fontSize: 10,
letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, Docs.Prototypes.MainLinkDocument(), doc, doc.recentlyClosed as Doc], {
title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "place", lockedPosition: true, boxShadow: "0 0", dontRegisterChildren: true
@@ -249,7 +252,7 @@ export class CurrentUserUtils {
// setup the Search button which will display the search panel.
static setupSearchPanel(sidebarContainer: Doc) {
return Docs.Create.ButtonDocument({
- _width: 50, _height: 25, title: "Search", fontSize: 10, dontDecorateSelection: true,
+ _width: 50, _height: 25, title: "Search", fontSize: 10,
letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
sourcePanel: Docs.Create.QueryDocument({ title: "search stack", }),
targetContainer: sidebarContainer,
@@ -280,26 +283,29 @@ export class CurrentUserUtils {
static setupExpandingButtons(doc: Doc) {
const queryTemplate = Docs.Create.MulticolumnDocument(
[
- Docs.Create.QueryDocument({ title: "query", _height: 200 }),
+ Docs.Create.QueryDocument({ title: "query", _height: 200, forceActive: true }),
Docs.Create.FreeformDocument([], { title: "data", _height: 100, _LODdisable: true, forceActive: true })
],
{ _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true, hideFilterView: true });
queryTemplate.isTemplateDoc = makeTemplate(queryTemplate);
const slideTemplate = Docs.Create.MultirowDocument(
[
- Docs.Create.MulticolumnDocument([], { title: "data", _height: 200 }),
- Docs.Create.TextDocument("", { title: "text", _height: 100 })
+ Docs.Create.MulticolumnDocument([], { title: "data", _height: 200, forceActive: true }),
+ Docs.Create.TextDocument("", { title: "text", _height: 100, forceActive: true })
],
- { _width: 400, _height: 300, title: "slideView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false });
+ { _width: 400, _height: 300, title: "slideView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false, forceActive: true, hideFilterView: true });
slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
const descriptionTemplate = Docs.Create.TextDocument("", { title: "text", _height: 100, _showTitle: "title" });
Doc.GetProto(descriptionTemplate).layout = FormattedTextBox.LayoutString("description");
descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView");
- const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ ...opts, dontDecorateSelection: true, dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100 })) as any as Doc;
+ const ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
+ ...opts,
+ dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
+ })) as any as Doc;
const blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
...opts,
- _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", dontDecorateSelection: true, forceActive: true,
+ _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true
})) as any as Doc;
@@ -309,9 +315,9 @@ export class CurrentUserUtils {
doc.slidesBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "presentation slide", icon: "sticky-note" });
doc.descriptionBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: descriptionTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "description view", icon: "sticky-note" });
doc.queryBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: queryTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "query view", icon: "sticky-note" });
- doc.templateButtons = blist({ title: "template buttons" }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc, doc.queryBtn as Doc]);
- doc.expandingButtons = blist({ title: "expanding buttons" }, [doc.undoBtn as Doc, doc.redoBtn as Doc, doc.templateButtons as Doc]);
- doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([doc.noteTypes as Doc, doc.templateButtons as Doc], {
+ doc.templateButtons = blist({ title: "template buttons", ignoreClick: true }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc, doc.queryBtn as Doc]);
+ doc.expandingButtons = blist({ title: "expanding buttons", ignoreClick: true }, [doc.undoBtn as Doc, doc.redoBtn as Doc, doc.templateButtons as Doc]);
+ doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([doc.noteTypes as Doc, doc.templateButtons as Doc, doc.clickFuncs as Doc], {
title: "template layouts", _xPadding: 0,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name })
}));
@@ -324,7 +330,7 @@ export class CurrentUserUtils {
// the initial presentation Doc to use
static setupDefaultPresentation(doc: Doc) {
- doc.presentationTemplate = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" }));
+ doc.presentationTemplate = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" }));
doc.curPresentation = Docs.Create.PresDocument(new List<Doc>(), { title: "Presentation", _viewType: CollectionViewType.Stacking, _LODdisable: true, _chromeStatus: "replaced", _showTitle: "title", boxShadow: "0 0" });
}
@@ -332,21 +338,37 @@ export class CurrentUserUtils {
doc.optionalRightCollection = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "New mobile uploads" }));
}
+ static setupChildClicks(doc: Doc) {
+ const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript(
+ "docCast(thisContainer.target).then((target) => { target && docCast(this.source).then((source) => { target.proto.data = new List([source || this]); } ); } )",
+ { target: Doc.name }), { title: "On Child Clicked (open in target)", _width: 300, _height: 200 });
+ const onClick = Docs.Create.ScriptingDocument(undefined, { title: "onClick", "onClick-rawScript": "console.log('click')", isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200 }, "onClick");
+ const onCheckedClick = Docs.Create.ScriptingDocument(undefined,
+ { title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)", "onCheckedClick-params": new List<string>(["heading", "checked", "containingTreeView"]), isTemplateDoc: true, isTemplateForField: "onCheckedClick", _width: 300, _height: 200 }, "onCheckedClick");
+ doc.childClickFuncs = Docs.Create.TreeDocument([openInTarget], { title: "on Child Click function templates" });
+ doc.clickFuncs = Docs.Create.TreeDocument([onClick, onCheckedClick], { title: "onClick funcs" });
+ }
+
static updateUserDocument(doc: Doc) {
doc.title = Doc.CurrentUserEmail;
new InkingControl();
(doc.iconTypes === undefined) && CurrentUserUtils.setupDefaultIconTypes(doc);
(doc.noteTypes === undefined) && CurrentUserUtils.setupDefaultDocTemplates(doc);
+ (doc.childClickFuncs === undefined) && CurrentUserUtils.setupChildClicks(doc);
(doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc);
(doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc);
(doc.expandingButtons === undefined) && CurrentUserUtils.setupExpandingButtons(doc);
(doc.curPresentation === undefined) && CurrentUserUtils.setupDefaultPresentation(doc);
(doc.sidebarButtons === undefined) && CurrentUserUtils.setupSidebarButtons(doc);
+ // this is equivalent to using PrefetchProxies to make sure all the childClickFuncs have been retrieved.
+ PromiseValue(Cast(doc.childClickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
// this is equivalent to using PrefetchProxies to make sure the recentlyClosed doc is ready
PromiseValue(Cast(doc.recentlyClosed, Doc)).then(recent => recent && PromiseValue(recent.data).then(DocListCast));
// this is equivalent to using PrefetchProxies to make sure all the sidebarButtons and noteType internal Doc's have been retrieved.
PromiseValue(Cast(doc.noteTypes, Doc)).then(noteTypes => noteTypes && PromiseValue(noteTypes.data).then(DocListCast));
+ PromiseValue(Cast(doc.clickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
+ PromiseValue(Cast(doc.childClickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast));
PromiseValue(Cast(doc.sidebarButtons, Doc)).then(stackingDoc => {
stackingDoc && PromiseValue(Cast(stackingDoc.data, listSpec(Doc))).then(sidebarButtons => {
sidebarButtons && sidebarButtons.map((sidebarBtn, i) => {
@@ -396,77 +418,6 @@ export class CurrentUserUtils {
throw new Error("There should be a user id! Why does Dash think there isn't one?");
}
});
- // try {
- // const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" });
- // NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json());
- // await Gateway.Instance.ClearCatalog();
- // const extraSchemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []);
- // let extras = await Promise.all(extraSchemas.map(sc => Gateway.Instance.GetSchema("", sc)));
- // let catprom = CurrentUserUtils.SetNorthstarCatalog(await Gateway.Instance.GetCatalog(), extras);
- // // if (catprom) await Promise.all(catprom);
- // } catch (e) {
-
- // }
- }
-
- /* Northstar catalog ... really just for testing so this should eventually go away */
- // --------------- Northstar hooks ------------- /
- static _northstarSchemas: Doc[] = [];
- @observable private static _northstarCatalog?: Catalog;
- @computed public static get NorthstarDBCatalog() { return this._northstarCatalog; }
-
- @action static SetNorthstarCatalog(ctlog: Catalog, extras: Catalog[]) {
- CurrentUserUtils.NorthstarDBCatalog = ctlog;
- // if (ctlog && ctlog.schemas) {
- // extras.map(ex => ctlog.schemas!.push(ex));
- // return ctlog.schemas.map(async schema => {
- // let schemaDocuments: Doc[] = [];
- // let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema);
- // await Promise.all(attributesToBecomeDocs.reduce((promises, attr) => {
- // promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
- // if (field instanceof Doc) {
- // schemaDocuments.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));
- // schemaDocuments.push(Docs.Create.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }));
- // }
- // })));
- // return promises;
- // }, [] as Promise<void>[]));
- // return CurrentUserUtils._northstarSchemas.push(Docs.Create.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! }));
- // });
- // }
- }
- public static set NorthstarDBCatalog(ctlog: Catalog | undefined) { this._northstarCatalog = ctlog; }
-
- public static AddNorthstarSchema(schema: Schema, schemaDoc: Doc) {
- if (this._northstarCatalog && CurrentUserUtils._northstarSchemas) {
- this._northstarCatalog.schemas!.push(schema);
- CurrentUserUtils._northstarSchemas.push(schemaDoc);
- const schemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []);
- schemas.push(schema.displayName!);
- CurrentUserUtils.UserDocument.DBSchemas = new List<string>(schemas);
- }
- }
- public static GetNorthstarSchema(name: string): Schema | undefined {
- return !this._northstarCatalog || !this._northstarCatalog.schemas ? undefined :
- ArrayUtil.FirstOrDefault<Schema>(this._northstarCatalog.schemas, (s: Schema) => s.displayName === name);
- }
- public static GetAllNorthstarColumnAttributes(schema: Schema) {
- const recurs = (attrs: Attribute[], g?: AttributeGroup) => {
- if (g && g.attributes) {
- attrs.push.apply(attrs, g.attributes);
- if (g.attributeGroups) {
- g.attributeGroups.forEach(ng => recurs(attrs, ng));
- }
- }
- return attrs;
- };
- return recurs([] as Attribute[], schema ? schema.rootAttributeGroup : undefined);
}
}
diff --git a/src/server/database.ts b/src/server/database.ts
index fc91ff3a2..a46531641 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -54,7 +54,7 @@ export namespace Database {
private onConnect: (() => void)[] = [];
constructor() {
- this.MongoClient.connect(url, (_err, client) => {
+ this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000 }, (_err, client) => {
if (!client) {
console.error("\nPlease start MongoDB by running 'mongod' in a terminal before continuing...\n");
process.exit(0);
diff --git a/src/server/index.ts b/src/server/index.ts
index 97f70630b..8b040c926 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -39,10 +39,10 @@ export const filesDirectory = path.resolve(publicDirectory, "files");
*/
async function preliminaryFunctions() {
// Utils.TraceConsoleLog();
+ await DashUploadUtils.buildFileDirectories();
await Logger.initialize();
await GoogleCredentialsLoader.loadCredentials();
GoogleApiServerUtils.processProjectCredentials();
- await DashUploadUtils.buildFileDirectories();
if (process.env.DB !== "MEM") {
await log_execution({
startMessage: "attempting to initialize mongodb connection",
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index 1150118f7..add607761 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -20,7 +20,6 @@ import * as request from 'request';
import RouteSubscriber from './RouteSubscriber';
import { publicDirectory } from '.';
import { logPort, } from './ActionUtilities';
-import { Utils } from '../Utils';
import { blue, yellow } from 'colors';
import * as cors from "cors";
diff --git a/src/server/updateProtos.ts b/src/server/updateProtos.ts
index 90490eb45..e9860bd61 100644
--- a/src/server/updateProtos.ts
+++ b/src/server/updateProtos.ts
@@ -1,8 +1,7 @@
import { Database } from "./database";
const protos =
- ["text", "histogram", "image", "web", "collection", "kvp",
- "video", "audio", "pdf", "icon", "import", "linkdoc"];
+ ["text", "image", "web", "collection", "kvp", "video", "audio", "pdf", "icon", "import", "linkdoc"];
(async function () {
await Promise.all(