aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/Message.ts13
-rw-r--r--src/server/Search.ts37
-rw-r--r--src/server/ServerUtil.ts64
-rw-r--r--src/server/authentication/controllers/WorkspacesMenu.css3
-rw-r--r--src/server/authentication/controllers/WorkspacesMenu.tsx89
-rw-r--r--src/server/authentication/models/current_user_utils.ts37
-rw-r--r--src/server/database.ts70
-rw-r--r--src/server/index.ts58
8 files changed, 162 insertions, 209 deletions
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 854ae0168..e9a8b0f0c 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -24,6 +24,14 @@ export interface Transferable {
readonly data?: any;
}
+export interface Reference {
+ readonly id: string;
+}
+
+export interface Diff extends Reference {
+ readonly diff: any;
+}
+
export namespace MessageStore {
export const Foo = new Message<string>("Foo");
export const Bar = new Message<string>("Bar");
@@ -32,4 +40,9 @@ export namespace MessageStore {
export const GetFields = new Message<string[]>("Get Fields"); // send string[] of 'id' get Transferable[] back
export const GetDocument = new Message<string>("Get Document");
export const DeleteAll = new Message<any>("Delete All");
+
+ export const GetRefField = new Message<string>("Get Ref Field");
+ export const GetRefFields = new Message<string[]>("Get Ref Fields");
+ export const UpdateField = new Message<Diff>("Update Ref Field");
+ export const CreateField = new Message<Reference>("Create Ref Field");
}
diff --git a/src/server/Search.ts b/src/server/Search.ts
index 8ae996e9e..6e7883bc9 100644
--- a/src/server/Search.ts
+++ b/src/server/Search.ts
@@ -1,14 +1,41 @@
import * as rp from 'request-promise';
import { Database } from './database';
+import { thisExpression } from 'babel-types';
export class Search {
public static Instance = new Search();
private url = 'http://localhost:8983/solr/';
+ private client: any;
- public updateDocument(document: any): rp.RequestPromise {
- return rp.post(this.url + "dash/update/json/docs", {
+ constructor() {
+ console.log("Search Instantiated!");
+ var SolrNode = require('solr-node');
+ this.client = new SolrNode({
+ host: 'localhost',
+ port: '8983',
+ core: 'dash',
+ protocol: 'http'
+ });
+ var strQuery = this.client.query().q('text:test');
+
+ console.log(strQuery);
+
+ // Search documents using strQuery
+ // client.search(strQuery, (err: any, result: any) => {
+ // if (err) {
+ // console.log(err);
+ // return;
+ // }
+ // console.log('Response:', result.response);
+ // });
+ }
+
+
+ public async updateDocument(document: any) {
+ console.log("UPDATE: ", JSON.stringify(document));
+ return rp.post(this.url + "dash/update", {
headers: { 'content-type': 'application/json' },
- body: JSON.stringify(document)
+ body: JSON.stringify([document])
});
}
@@ -22,9 +49,7 @@ export class Search {
}));
const fields = searchResults.response.docs;
const ids = fields.map((field: any) => field.id);
- const docs = await Database.Instance.searchQuery(ids);
- const docIds = docs.map((doc: any) => doc._id);
- return docIds;
+ return ids;
}
public async clear() {
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
deleted file mode 100644
index eb5749dff..000000000
--- a/src/server/ServerUtil.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { HistogramField } from "../client/northstar/dash-fields/HistogramField";
-import { AudioField } from "../fields/AudioField";
-import { BooleanField } from "../fields/BooleanField";
-import { HtmlField } from "../fields/HtmlField";
-import { InkField } from "../fields/InkField";
-import { PDFField } from "../fields/PDFField";
-import { ScriptField } from "../fields/ScriptField";
-import { TupleField } from "../fields/TupleField";
-import { VideoField } from "../fields/VideoField";
-import { WebField } from "../fields/WebField";
-import { Utils } from "../Utils";
-import { Document } from "./../fields/Document";
-import { Field } from "./../fields/Field";
-import { ImageField } from "./../fields/ImageField";
-import { Key } from "./../fields/Key";
-import { ListField } from "./../fields/ListField";
-import { NumberField } from "./../fields/NumberField";
-import { RichTextField } from "./../fields/RichTextField";
-import { TextField } from "./../fields/TextField";
-import { Transferable, Types } from "./Message";
-import { TemplateField } from "../fields/TemplateField";
-import { IconField } from "../fields/IconFIeld";
-
-export class ServerUtils {
- public static prepend(extension: string): string {
- return window.location.origin + extension;
- }
-
- public static FromJson(json: Transferable): Field {
-
- if (!(json.data !== undefined && json.id && json.type !== undefined)) {
- console.log(
- "how did you manage to get an object that doesn't have a data or an id?"
- );
- return new TextField("Something to fill the space", Utils.GenerateGuid());
- }
-
- switch (json.type) {
- case Types.Boolean: return new BooleanField(json.data, json.id, false);
- case Types.Number: return new NumberField(json.data, json.id, false);
- case Types.Text: return new TextField(json.data, json.id, false);
- case Types.Icon: return new IconField(json.data, json.id, false);
- case Types.Html: return new HtmlField(json.data, json.id, false);
- case Types.Web: return new WebField(new URL(json.data), json.id, false);
- case Types.RichText: return new RichTextField(json.data, json.id, false);
- case Types.Key: return new Key(json.data, json.id, false);
- case Types.Image: return new ImageField(new URL(json.data), json.id, false);
- case Types.HistogramOp: return HistogramField.FromJson(json.id, json.data);
- case Types.PDF: return new PDFField(new URL(json.data), json.id, false);
- case Types.List: return ListField.FromJson(json.id, json.data);
- case Types.Script: return ScriptField.FromJson(json.id, json.data);
- case Types.Audio: return new AudioField(new URL(json.data), json.id, false);
- case Types.Video: return new VideoField(new URL(json.data), json.id, false);
- case Types.Tuple: return new TupleField(json.data, json.id, false);
- case Types.Ink: return InkField.FromJson(json.id, json.data);
- case Types.Templates: return TemplateField.FromJson(json.id, json.data);
- case Types.Document: return Document.FromJson(json.data, json.id, false);
- default:
- throw Error(
- "Error, unrecognized field type received from server. If you just created a new field type, be sure to add it here"
- );
- }
- }
-}
diff --git a/src/server/authentication/controllers/WorkspacesMenu.css b/src/server/authentication/controllers/WorkspacesMenu.css
deleted file mode 100644
index b89039965..000000000
--- a/src/server/authentication/controllers/WorkspacesMenu.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.ids:hover {
- color: darkblue;
-} \ No newline at end of file
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
deleted file mode 100644
index b08c1aebe..000000000
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import * as React from 'react';
-import { observable, action, configure, reaction, computed, ObservableMap, runInAction } from 'mobx';
-import { observer } from "mobx-react";
-import './WorkspacesMenu.css';
-import { Document } from '../../../fields/Document';
-import { EditableView } from '../../../client/views/EditableView';
-import { KeyStore } from '../../../fields/KeyStore';
-
-export interface WorkspaceMenuProps {
- active: Document | undefined;
- open: (workspace: Document) => void;
- new: () => void;
- allWorkspaces: Document[];
- isShown: () => boolean;
- toggle: () => void;
-}
-
-@observer
-export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
- constructor(props: WorkspaceMenuProps) {
- super(props);
- this.addNewWorkspace = this.addNewWorkspace.bind(this);
- }
-
- @action
- addNewWorkspace() {
- this.props.new();
- this.props.toggle();
- }
-
- render() {
- return (
- <div
- style={{
- width: "auto",
- maxHeight: '200px',
- overflow: 'scroll',
- borderRadius: 5,
- position: "absolute",
- top: 78,
- left: this.props.isShown() ? 11 : -500,
- background: "white",
- border: "black solid 2px",
- transition: "all 1s ease",
- zIndex: 15,
- padding: 10,
- paddingRight: 12,
- }}>
- <img
- src="https://bit.ly/2IBBkxk"
- style={{
- width: 20,
- height: 20,
- marginTop: 3,
- marginLeft: 3,
- marginBottom: 3,
- cursor: "grab"
- }}
- onClick={this.addNewWorkspace}
- />
- {this.props.allWorkspaces.map((s, i) =>
- <div
- key={s.Id}
- onContextMenu={(e) => {
- e.preventDefault();
- this.props.open(s);
- }}
- style={{
- marginTop: 10,
- color: s === this.props.active ? "red" : "black"
- }}
- >
- <span>{i + 1} - </span>
- <EditableView
- display={"inline"}
- GetValue={() => s.Title}
- SetValue={(title: string): boolean => {
- s.SetText(KeyStore.Title, title);
- return true;
- }}
- contents={s.Title}
- height={20}
- />
- </div>
- )}
- </div>
- );
- }
-} \ No newline at end of file
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 5d4479c88..5f45d7bcc 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -1,19 +1,20 @@
import { computed, observable, action, runInAction } from "mobx";
import * as rp from 'request-promise';
-import { Documents } from "../../../client/documents/Documents";
+import { Docs } from "../../../client/documents/Documents";
import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea";
import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil";
-import { Server } from "../../../client/Server";
-import { Document } from "../../../fields/Document";
-import { KeyStore } from "../../../fields/KeyStore";
-import { ListField } from "../../../fields/ListField";
import { RouteStore } from "../../RouteStore";
-import { ServerUtils } from "../../ServerUtil";
+import { DocServer } from "../../../client/DocServer";
+import { Doc } from "../../../new_fields/Doc";
+import { List } from "../../../new_fields/List";
+import { CollectionViewType } from "../../../client/views/collections/CollectionBaseView";
+import { CollectionTreeView } from "../../../client/views/collections/CollectionTreeView";
+import { CollectionView } from "../../../client/views/collections/CollectionView";
export class CurrentUserUtils {
private static curr_email: string;
private static curr_id: string;
- @observable private static user_document: Document;
+ @observable private static user_document: Doc;
//TODO tfs: these should be temporary...
private static mainDocId: string | undefined;
@@ -23,15 +24,21 @@ export class CurrentUserUtils {
public static get MainDocId() { return this.mainDocId; }
public static set MainDocId(id: string | undefined) { this.mainDocId = id; }
- private static createUserDocument(id: string): Document {
- let doc = new Document(id);
- doc.Set(KeyStore.Workspaces, new ListField<Document>());
- doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" }));
+ private static createUserDocument(id: string): Doc {
+ let doc = new Doc(id, true);
+ doc.viewType = CollectionViewType.Tree;
+ doc.layout = CollectionView.LayoutString();
+ doc.title = this.email;
+ doc.data = new List<Doc>();
+ doc.excludeFromLibrary = true;
+ doc.optionalRightCollection = Docs.SchemaDocument([], { title: "Pending documents" });
+ // doc.library = Docs.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` });
+ // (doc.library as Doc).excludeFromLibrary = true;
return doc;
}
public static loadCurrentUser(): Promise<any> {
- let userPromise = rp.get(ServerUtils.prepend(RouteStore.getCurrUser)).then(response => {
+ let userPromise = rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => {
if (response) {
let obj = JSON.parse(response);
CurrentUserUtils.curr_id = obj.id as string;
@@ -40,10 +47,10 @@ export class CurrentUserUtils {
throw new Error("There should be a user! Why does Dash think there isn't one?");
}
});
- let userDocPromise = rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(id => {
+ let userDocPromise = rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => {
if (id) {
- return Server.GetField(id).then(field =>
- runInAction(() => this.user_document = field instanceof Document ? field : this.createUserDocument(id)));
+ return DocServer.GetRefField(id).then(field =>
+ runInAction(() => this.user_document = field instanceof Doc ? field : this.createUserDocument(id)));
} else {
throw new Error("There should be a user id! Why does Dash think there isn't one?");
}
diff --git a/src/server/database.ts b/src/server/database.ts
index d5905c7b3..69005d2d3 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -13,22 +13,15 @@ export class Database {
this.MongoClient.connect(this.url, (err, client) => this.db = client.db());
}
- public update(id: string, value: any, callback: () => void) {
+ public update(id: string, value: any, callback: () => void, upsert = true, collectionName = Database.DocumentsCollection) {
if (this.db) {
- let collection = this.db.collection('documents');
+ let collection = this.db.collection(collectionName);
const prom = this.currentWrites[id];
let newProm: Promise<void>;
const run = (): Promise<void> => {
return new Promise<void>(resolve => {
- collection.updateOne({ _id: id }, { $set: value }, { upsert: true }
+ collection.updateOne({ _id: id }, value, { upsert }
, (err, res) => {
- if (err) {
- console.log(err.message);
- console.log(err.errmsg);
- }
- // if (res) {
- // console.log(JSON.stringify(res.result));
- // }
if (this.currentWrites[id] === newProm) {
delete this.currentWrites[id];
}
@@ -51,36 +44,53 @@ export class Database {
this.db && this.db.collection(collectionName).deleteMany({}, res));
}
- public insert(kvpairs: any, collectionName = Database.DocumentsCollection) {
- this.db && this.db.collection(collectionName).insertOne(kvpairs, (err, res) =>
- err // && console.log(err)
- );
+ public insert(value: any, collectionName = Database.DocumentsCollection) {
+ if (!this.db) { return; }
+ if ("id" in value) {
+ value._id = value.id;
+ delete value.id;
+ }
+ const id = value._id;
+ const collection = this.db.collection(collectionName);
+ const prom = this.currentWrites[id];
+ let newProm: Promise<void>;
+ const run = (): Promise<void> => {
+ return new Promise<void>(resolve => {
+ collection.insertOne(value, (err, res) => {
+ if (this.currentWrites[id] === newProm) {
+ delete this.currentWrites[id];
+ }
+ resolve();
+ });
+ });
+ };
+ newProm = prom ? prom.then(run) : run();
+ this.currentWrites[id] = newProm;
}
public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = Database.DocumentsCollection) {
- this.db && this.db.collection(collectionName).findOne({ id: id }, (err, result) =>
- fn(result ? ({ id: result._id, type: result.type, data: result.data }) : undefined));
+ this.db && this.db.collection(collectionName).findOne({ _id: id }, (err, result) => {
+ if (result) {
+ result.id = result._id;
+ delete result._id;
+ fn(result);
+ } else {
+ fn(undefined);
+ }
+ });
}
public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = Database.DocumentsCollection) {
- this.db && this.db.collection(collectionName).find({ id: { "$in": ids } }).toArray((err, docs) => {
+ this.db && this.db.collection(collectionName).find({ _id: { "$in": ids } }).toArray((err, docs) => {
if (err) {
console.log(err.message);
console.log(err.errmsg);
}
- fn(docs.map(doc => ({ id: doc._id, type: doc.type, data: doc.data })));
- });
- }
-
- public searchQuery(ids: string[], collectionName = Database.DocumentsCollection): Promise<any> {
- return new Promise<any>(resolve => {
- this.db && this.db.collection(collectionName).find({ "data.field": { "$in": ids } }).toArray((err, docs) => {
- if (err) {
- console.log(err.message);
- console.log(err.errmsg);
- }
- resolve(docs);
- });
+ fn(docs.map(doc => {
+ doc.id = doc._id;
+ delete doc._id;
+ return doc;
+ }));
});
}
diff --git a/src/server/index.ts b/src/server/index.ts
index cb4268a2d..2381f9840 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -17,13 +17,12 @@ import { Socket } from 'socket.io';
import * as webpack from 'webpack';
import * as wdm from 'webpack-dev-middleware';
import * as whm from 'webpack-hot-middleware';
-import { Field, FieldId } from '../fields/Field';
import { Utils } from '../Utils';
import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/controllers/user_controller';
import { DashUserModel } from './authentication/models/user_model';
import { Client } from './Client';
import { Database } from './database';
-import { MessageStore, Transferable, Types } from "./Message";
+import { MessageStore, Transferable, Types, Diff } from "./Message";
import { RouteStore } from './RouteStore';
const app = express();
const config = require('../../webpack.config');
@@ -34,6 +33,8 @@ import expressFlash = require('express-flash');
import flash = require('connect-flash');
import c = require("crypto");
import { Search } from './Search';
+import { debug } from 'util';
+import _ = require('lodash');
const MongoStore = require('connect-mongo')(session);
const mongoose = require('mongoose');
@@ -120,11 +121,14 @@ app.get("/pull", (req, res) =>
res.redirect("/");
}));
+// SEARCH
+
// GETTERS
app.get("/search", async (req, res) => {
let query = req.query.query || "hello";
let results = await Search.Instance.search(query);
+ console.log(results);
res.send(results);
});
@@ -240,15 +244,22 @@ server.on("connection", function (socket: Socket) {
Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField);
Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields);
Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields);
+
+ Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField);
+ Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff));
+ Utils.AddServerHandlerCallback(socket, MessageStore.GetRefField, GetRefField);
+ Utils.AddServerHandlerCallback(socket, MessageStore.GetRefFields, GetRefFields);
});
async function deleteFields() {
await Database.Instance.deleteAll();
await Search.Instance.clear();
+ await Database.Instance.deleteAll('newDocuments');
}
async function deleteAll() {
await Database.Instance.deleteAll();
+ await Database.Instance.deleteAll('newDocuments');
await Database.Instance.deleteAll('sessions');
await Database.Instance.deleteAll('users');
await Search.Instance.clear();
@@ -272,7 +283,50 @@ function setField(socket: Socket, newValue: Transferable) {
socket.broadcast.emit(MessageStore.SetField.Message, newValue));
if (newValue.type === Types.Text) {
Search.Instance.updateDocument({ id: newValue.id, data: (newValue as any).data });
+ console.log("set field");
+ }
+}
+
+function GetRefField([id, callback]: [string, (result?: Transferable) => void]) {
+ Database.Instance.getDocument(id, callback, "newDocuments");
+}
+
+function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => void]) {
+ Database.Instance.getDocuments(ids, callback, "newDocuments");
+}
+
+
+const suffixMap: { [type: string]: string } = {
+ "number": "_n",
+ "string": "_t"
+};
+function UpdateField(socket: Socket, diff: Diff) {
+ Database.Instance.update(diff.id, diff.diff,
+ () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments");
+ const docfield = diff.diff;
+ const update: any = { id: diff.id };
+ console.log("FIELD: ", docfield);
+ let dynfield = false;
+ for (let key in docfield) {
+ if (!key.startsWith("fields.")) continue;
+ const val = docfield[key];
+ const suffix = suffixMap[typeof val];
+ if (suffix !== undefined) {
+ key = key.substring(7);
+ Object.values(suffixMap).forEach(suf => update[key + suf] = null);
+ update[key + suffix] = { set: val };
+ dynfield = true;
+ }
}
+ if (dynfield) {
+ console.log("dynamic field detected!");
+ Search.Instance.updateDocument(update);
+ }
+}
+
+function CreateField(newValue: any) {
+ Database.Instance.insert(newValue, "newDocuments");
+ console.log("created field");
}
server.listen(serverPort);