From 8c801b3c98e1eaae297b0f1682b42fc478a1b887 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 14 Apr 2019 00:44:02 -0400 Subject: Got a basic version of search working --- src/server/Search.ts | 27 +++++++++++++++++++++++++++ src/server/ServerUtil.ts | 4 ++-- src/server/database.ts | 12 ++++++++++++ src/server/index.ts | 12 +++++++++++- 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/server/Search.ts (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts new file mode 100644 index 000000000..f9babc433 --- /dev/null +++ b/src/server/Search.ts @@ -0,0 +1,27 @@ +import * as rp from 'request-promise'; +import { Database } from './database'; + +export class Search { + public static Instance = new Search(); + private url = 'http://localhost:8983/solr/'; + + public updateDocument(document: any): rp.RequestPromise { + return rp.post(this.url + "dash/update/json/docs", { + headers: { 'content-type': 'application/json' }, + body: JSON.stringify(document) + }); + } + + public async search(query: string) { + const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { + qs: { + q: query + } + })); + 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; + } +} \ No newline at end of file diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts index 0973f82b1..dc8687b7e 100644 --- a/src/server/ServerUtil.ts +++ b/src/server/ServerUtil.ts @@ -73,9 +73,9 @@ export class ServerUtils { return InkField.FromJson(id, data); case Types.Document: let doc: Document = new Document(id, false); - let fields: [string, string][] = data as [string, string][]; + let fields: { key: string, field: string }[] = data as { key: string, field: string }[]; fields.forEach(element => { - doc._proxies.set(element[0], element[1]); + doc._proxies.set(element.key, element.field); }); return doc; default: diff --git a/src/server/database.ts b/src/server/database.ts index 3290edde0..4011f26bd 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -71,6 +71,18 @@ export class Database { }); } + public searchQuery(ids: string[], collectionName = Database.DocumentsCollection): Promise { + return new Promise(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); + }); + }); + } + public print() { console.log("db says hi!"); } diff --git a/src/server/index.ts b/src/server/index.ts index a6fe6fa2c..fef26f78a 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -22,7 +22,7 @@ import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLo import { DashUserModel } from './authentication/models/user_model'; import { Client } from './Client'; import { Database } from './database'; -import { MessageStore, Transferable } from "./Message"; +import { MessageStore, Transferable, Types } from "./Message"; import { RouteStore } from './RouteStore'; const app = express(); const config = require('../../webpack.config'); @@ -32,6 +32,7 @@ const serverPort = 4321; import expressFlash = require('express-flash'); import flash = require('connect-flash'); import c = require("crypto"); +import { Search } from './Search'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); @@ -118,6 +119,12 @@ app.get("/pull", (req, res) => // GETTERS +app.get("/search", async (req, res) => { + let query = req.query.query || "hello"; + let results = await Search.Instance.search(query); + res.send(results); +}); + // anyone attempting to navigate to localhost at this port will // first have to login addSecureRoute( @@ -258,6 +265,9 @@ function getFields([ids, callback]: [string[], (result: any) => void]) { function setField(socket: Socket, newValue: Transferable) { Database.Instance.update(newValue._id, newValue, () => socket.broadcast.emit(MessageStore.SetField.Message, newValue)); + if (newValue.type === Types.Text) { + Search.Instance.updateDocument({ id: newValue._id, data: (newValue as any).data }); + } } server.listen(serverPort); -- cgit v1.2.3-70-g09d2 From be1976fb0ba33064978ee973993b3a2316cdf43c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 14 Apr 2019 01:02:25 -0400 Subject: deleting database now also clears Solr indexes --- src/server/Search.ts | 11 +++++++++++ src/server/index.ts | 7 +++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts index f9babc433..7d8602346 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -24,4 +24,15 @@ export class Search { const docIds = docs.map((doc: any) => doc._id); return docIds; } + + public async clear() { + return rp.post(this.url + "dash/update", { + body: { + delete: { + query: "*:*" + } + }, + json: true + }); + } } \ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index bea84c6ed..cb4268a2d 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -11,6 +11,7 @@ import { ObservableMap } from 'mobx'; import * as passport from 'passport'; import * as path from 'path'; import * as request from 'request'; +import * as rp from 'request-promise'; import * as io from 'socket.io'; import { Socket } from 'socket.io'; import * as webpack from 'webpack'; @@ -241,14 +242,16 @@ server.on("connection", function (socket: Socket) { Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields); }); -function deleteFields() { - return Database.Instance.deleteAll(); +async function deleteFields() { + await Database.Instance.deleteAll(); + await Search.Instance.clear(); } async function deleteAll() { await Database.Instance.deleteAll(); await Database.Instance.deleteAll('sessions'); await Database.Instance.deleteAll('users'); + await Search.Instance.clear(); } function barReceived(guid: String) { -- cgit v1.2.3-70-g09d2 From 94fa065ae2a0f3ccb6a16141a45f11543add3b63 Mon Sep 17 00:00:00 2001 From: ab Date: Mon, 22 Apr 2019 19:56:49 -0400 Subject: exploratory sprint --- src/server/Search.ts | 1 + src/server/index.ts | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts index 7d8602346..bcea03d5c 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -6,6 +6,7 @@ export class Search { private url = 'http://localhost:8983/solr/'; public updateDocument(document: any): rp.RequestPromise { + console.log(JSON.stringify(document)); return rp.post(this.url + "dash/update/json/docs", { headers: { 'content-type': 'application/json' }, body: JSON.stringify(document) diff --git a/src/server/index.ts b/src/server/index.ts index a68dabc0c..b3df90199 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -34,6 +34,7 @@ import expressFlash = require('express-flash'); import flash = require('connect-flash'); import c = require("crypto"); import { Search } from './Search'; +import { debug } from 'util'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); @@ -276,6 +277,7 @@ 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"); } } @@ -286,10 +288,17 @@ function GetRefField([id, callback]: [string, (result?: Transferable) => void]) function UpdateField(socket: Socket, diff: Diff) { Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments"); + //if (diff.diff === Types.Text) { + Search.Instance.updateDocument({ name: "john", burns: "true" }); + Search.Instance.updateDocument({ id: diff.id, data: diff.diff.data }); + //console.log("set field"); + //} + console.log("updated field", diff.diff); } function CreateField(newValue: any) { Database.Instance.insert(newValue, "newDocuments"); + console.log("created field"); } server.listen(serverPort); -- cgit v1.2.3-70-g09d2 From 85ce4c9a3cd665983067d7783e20eb7701376503 Mon Sep 17 00:00:00 2001 From: ab Date: Tue, 23 Apr 2019 19:00:15 -0400 Subject: idk --- src/server/index.ts | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index b3df90199..464d3f68f 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -35,6 +35,7 @@ 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'); @@ -289,11 +290,32 @@ function UpdateField(socket: Socket, diff: Diff) { Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments"); //if (diff.diff === Types.Text) { - Search.Instance.updateDocument({ name: "john", burns: "true" }); - Search.Instance.updateDocument({ id: diff.id, data: diff.diff.data }); + //Search.Instance.updateDocument({ name: "john", burns: "true" }); + //Search.Instance.updateDocument({ id: diff.id, data: diff.diff.data }); //console.log("set field"); //} - console.log("updated field", diff.diff); + const docid = { id: diff.id }; + const docfield = diff.diff; + console.log("FIELD: ", docfield); + var dynfield = false; + for (var key in docfield) { + const val = docfield[key]; + if (typeof val === 'number') { + key = key + "_n"; + dynfield = true; + } + else if (typeof val === 'string') { + key = key + "_t"; + dynfield = true; + } + console.log(key); + } + var merged = {}; + _.extend(merged, docid, docfield); + if (dynfield) { + console.log("dynamic field detected!"); + Search.Instance.updateDocument(merged); + } } function CreateField(newValue: any) { -- cgit v1.2.3-70-g09d2 From df9fa3e362a6bdd616bc0b46ef9b425cfc5a010d Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Tue, 30 Apr 2019 16:17:39 -0400 Subject: before pull --- src/client/views/SearchBox.scss | 1 - src/fields/Document.ts | 15 +++++++-------- src/server/Search.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/server/database.ts | 12 ++++++++++++ src/server/index.ts | 19 ++++++++++++++++--- 5 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 src/server/Search.ts (limited to 'src/server') diff --git a/src/client/views/SearchBox.scss b/src/client/views/SearchBox.scss index e1a1de142..92363e681 100644 --- a/src/client/views/SearchBox.scss +++ b/src/client/views/SearchBox.scss @@ -9,7 +9,6 @@ align-items: center; .submit-search { - display: inline-block; text-align: right; color: $dark-color; -webkit-transition: right 0.4s; diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 2797efc09..6f6533754 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -29,15 +29,14 @@ export class Document extends Field { } static FromJson(data: any, id: string, save: boolean): Document { let doc = new Document(id, save); - let fields = data as [string, string][]; - fields.forEach(pair => doc._proxies.set(pair[0], pair[1])); + let fields = data as { key: string, field: string }[]; + fields.forEach(pair => doc._proxies.set(pair.key, pair.field)); return doc; } - UpdateFromServer(data: [string, string][]) { - for (const key in data) { - const element = data[key]; - this._proxies.set(element[0], element[1]); + UpdateFromServer(data: { key: string, field: string }[]) { + for (const kv of data) { + this._proxies.set(kv.key, kv.field); } } @@ -448,9 +447,9 @@ export class Document extends Field { } ToJson() { - let fields: [string, string][] = []; + let fields: { key: string, field: string }[] = []; this._proxies.forEach((field, key) => - field && fields.push([key, field])); + field && fields.push({ key, field })); return { type: Types.Document, diff --git a/src/server/Search.ts b/src/server/Search.ts new file mode 100644 index 000000000..7d8602346 --- /dev/null +++ b/src/server/Search.ts @@ -0,0 +1,38 @@ +import * as rp from 'request-promise'; +import { Database } from './database'; + +export class Search { + public static Instance = new Search(); + private url = 'http://localhost:8983/solr/'; + + public updateDocument(document: any): rp.RequestPromise { + return rp.post(this.url + "dash/update/json/docs", { + headers: { 'content-type': 'application/json' }, + body: JSON.stringify(document) + }); + } + + public async search(query: string) { + const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { + qs: { + q: query + } + })); + 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; + } + + public async clear() { + return rp.post(this.url + "dash/update", { + body: { + delete: { + query: "*:*" + } + }, + json: true + }); + } +} \ No newline at end of file diff --git a/src/server/database.ts b/src/server/database.ts index 5457e4dd5..d5905c7b3 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -72,6 +72,18 @@ export class Database { }); } + public searchQuery(ids: string[], collectionName = Database.DocumentsCollection): Promise { + return new Promise(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); + }); + }); + } + public print() { console.log("db says hi!"); } diff --git a/src/server/index.ts b/src/server/index.ts index 70a7d266c..cb4268a2d 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -11,6 +11,7 @@ import { ObservableMap } from 'mobx'; import * as passport from 'passport'; import * as path from 'path'; import * as request from 'request'; +import * as rp from 'request-promise'; import * as io from 'socket.io'; import { Socket } from 'socket.io'; import * as webpack from 'webpack'; @@ -22,7 +23,7 @@ import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLo import { DashUserModel } from './authentication/models/user_model'; import { Client } from './Client'; import { Database } from './database'; -import { MessageStore, Transferable } from "./Message"; +import { MessageStore, Transferable, Types } from "./Message"; import { RouteStore } from './RouteStore'; const app = express(); const config = require('../../webpack.config'); @@ -32,6 +33,7 @@ const serverPort = 4321; import expressFlash = require('express-flash'); import flash = require('connect-flash'); import c = require("crypto"); +import { Search } from './Search'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); @@ -120,6 +122,12 @@ app.get("/pull", (req, res) => // GETTERS +app.get("/search", async (req, res) => { + let query = req.query.query || "hello"; + let results = await Search.Instance.search(query); + res.send(results); +}); + // anyone attempting to navigate to localhost at this port will // first have to login addSecureRoute( @@ -234,14 +242,16 @@ server.on("connection", function (socket: Socket) { Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields); }); -function deleteFields() { - return Database.Instance.deleteAll(); +async function deleteFields() { + await Database.Instance.deleteAll(); + await Search.Instance.clear(); } async function deleteAll() { await Database.Instance.deleteAll(); await Database.Instance.deleteAll('sessions'); await Database.Instance.deleteAll('users'); + await Search.Instance.clear(); } function barReceived(guid: String) { @@ -260,6 +270,9 @@ function getFields([ids, callback]: [string[], (result: Transferable[]) => void] function setField(socket: Socket, newValue: Transferable) { Database.Instance.update(newValue.id, newValue, () => socket.broadcast.emit(MessageStore.SetField.Message, newValue)); + if (newValue.type === Types.Text) { + Search.Instance.updateDocument({ id: newValue.id, data: (newValue as any).data }); + } } server.listen(serverPort); -- cgit v1.2.3-70-g09d2 From da792d534024d8e0d266e291f92b9a1e83be51c2 Mon Sep 17 00:00:00 2001 From: ab Date: Tue, 30 Apr 2019 18:38:05 -0400 Subject: set not working --- src/debug/Test.tsx | 50 +++++++++++++++++++++++++------------------------- src/server/index.ts | 14 ++++++++++---- 2 files changed, 35 insertions(+), 29 deletions(-) (limited to 'src/server') diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx index 6a677f80f..47cfac2c1 100644 --- a/src/debug/Test.tsx +++ b/src/debug/Test.tsx @@ -46,34 +46,34 @@ class Test extends React.Component { doc.fields = "test"; doc.test = "hello doc"; doc.url = url; - doc.testDoc = doc2; + //doc.testDoc = doc2; - const test1: TestDoc = TestDoc(doc); - const test2: Test2Doc = Test2Doc(doc); - assert(test1.hello === 5); - assert(test1.fields === undefined); - assert(test1.test === "hello doc"); - assert(test1.url === url); - assert(test1.testDoc === doc2); - test1.myField = 20; - assert(test1.myField === 20); + // const test1: TestDoc = TestDoc(doc); + // const test2: Test2Doc = Test2Doc(doc); + // assert(test1.hello === 5); + // assert(test1.fields === undefined); + // assert(test1.test === "hello doc"); + // assert(test1.url === url); + // //assert(test1.testDoc === doc2); + // test1.myField = 20; + // assert(test1.myField === 20); - assert(test2.hello === undefined); - // assert(test2.fields === "test"); - assert(test2.test === undefined); - assert(test2.url === undefined); - assert(test2.testDoc === undefined); - test2.url = 35; - assert(test2.url === 35); - const l = new List(); - //TODO push, and other array functions don't go through the proxy - l.push(1); - //TODO currently length, and any other string fields will get serialized - l.length = 3; - l[2] = 5; - console.log(l.slice()); - console.log(SerializationHelper.Serialize(l)); + // assert(test2.hello === undefined); + // // assert(test2.fields === "test"); + // assert(test2.test === undefined); + // assert(test2.url === undefined); + // assert(test2.testDoc === undefined); + // test2.url = 35; + // assert(test2.url === 35); + // const l = new List(); + // //TODO push, and other array functions don't go through the proxy + // l.push(1); + // //TODO currently length, and any other string fields will get serialized + // l.length = 3; + // l[2] = 5; + // console.log(l.slice()); + // console.log(SerializationHelper.Serialize(l)); } render() { diff --git a/src/server/index.ts b/src/server/index.ts index 464d3f68f..b57e5c482 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -295,23 +295,29 @@ function UpdateField(socket: Socket, diff: Diff) { //console.log("set field"); //} const docid = { id: diff.id }; - const docfield = diff.diff; + var docfield = diff.diff; + docfield = JSON.parse(JSON.stringify(docfield).split("fields.").join("")); console.log("FIELD: ", docfield); var dynfield = false; for (var key in docfield) { const val = docfield[key]; if (typeof val === 'number') { - key = key + "_n"; + const new_key: string = key + "_n"; + docfield = JSON.parse(JSON.stringify(docfield).split(key).join(new_key)); + //docfield[new_key] = { 'set': val }; dynfield = true; } else if (typeof val === 'string') { - key = key + "_t"; + const new_key: string = key + "_t"; + docfield = JSON.parse(JSON.stringify(docfield).split(key).join(new_key)); + docfield[new_key] = { 'set': val }; dynfield = true; } - console.log(key); } var merged = {}; _.extend(merged, docid, docfield); + console.log(merged); + console.log(docfield); if (dynfield) { console.log("dynamic field detected!"); Search.Instance.updateDocument(merged); -- cgit v1.2.3-70-g09d2 From eed0866d6148dfdb29c3f87b42afe365231f258c Mon Sep 17 00:00:00 2001 From: Monika Hedman Date: Tue, 30 Apr 2019 21:47:03 -0400 Subject: i am CONFUSED --- src/client/views/SearchBox.tsx | 31 ++++++++++++++++++++++++------- src/server/Search.ts | 2 ++ 2 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src/server') diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 7ceaf1da6..0670360a2 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -9,6 +9,10 @@ import { faSearch } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; import { actionFieldDecorator } from 'mobx/lib/internal'; +// const app = express(); +// import * as express from 'express'; +import { Search } from '../../server/Search'; + library.add(faSearch); @@ -26,12 +30,25 @@ export class SearchBox extends React.Component { } submitSearch = () => { - Utils.EmitCallback(Server.Socket, MessageStore.SearchFor, this.searchString, (results: string[]) => { - for (const result of results) { - console.log(result); - //Utils.GetQueryVariable(); - } - }); + // Utils.EmitCallback(Server.Socket, MessageStore.SearchFor, this.searchString, (results: string[]) => { + // for (const result of results) { + // console.log(result); + // //Utils.GetQueryVariable(); + // } + // }); + + let query = this.searchString; + console.log(query); + //something bad is happening here + let results = Search.Instance.search(query); + console.log(results); + + // app.get("/search", async (req, res) => { + // //let query = req.query.query || "hello"; + // let query = this.searchString; + // let results = await Search.Instance.search(query); + // res.send(results); + // }); } @action @@ -73,7 +90,7 @@ export class SearchBox extends React.Component { map(prop => )} */} -
+
diff --git a/src/server/Search.ts b/src/server/Search.ts index 7d8602346..8ae996e9e 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -13,6 +13,8 @@ export class Search { } public async search(query: string) { + console.log("____________________________"); + console.log(query); const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { qs: { q: query -- cgit v1.2.3-70-g09d2 From 0c28cabf0d496be24da3e5ee414a8fcd925250ab Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 3 May 2019 01:42:54 -0400 Subject: Got part of search working --- src/server/Search.ts | 13 ++++++------- src/server/database.ts | 12 ------------ src/server/index.ts | 4 ++-- 3 files changed, 8 insertions(+), 21 deletions(-) (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts index bcea03d5c..9e462f0ae 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -1,15 +1,16 @@ 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/'; - public updateDocument(document: any): rp.RequestPromise { - console.log(JSON.stringify(document)); - return rp.post(this.url + "dash/update/json/docs", { + 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]) }); } @@ -21,9 +22,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/database.ts b/src/server/database.ts index 1e8004328..a61b4d823 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -74,18 +74,6 @@ export class Database { }); } - public searchQuery(ids: string[], collectionName = Database.DocumentsCollection): Promise { - return new Promise(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); - }); - }); - } - public print() { console.log("db says hi!"); } diff --git a/src/server/index.ts b/src/server/index.ts index b57e5c482..b4252c2a1 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -316,8 +316,8 @@ function UpdateField(socket: Socket, diff: Diff) { } var merged = {}; _.extend(merged, docid, docfield); - console.log(merged); - console.log(docfield); + console.log("MERGED: ", merged); + console.log("DOC_FIELD: ", docfield); if (dynfield) { console.log("dynamic field detected!"); Search.Instance.updateDocument(merged); -- cgit v1.2.3-70-g09d2 From 189eeefbb3e7f3d96d1d140beff74fcffe305786 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 3 May 2019 20:28:22 -0400 Subject: Added debugging support and added removing of unused keys in Solr --- .vscode/launch.json | 9 +++++++++ package.json | 3 ++- src/server/index.ts | 40 +++++++++++++++------------------------- 3 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src/server') diff --git a/.vscode/launch.json b/.vscode/launch.json index fb91a1080..e92a4949a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,6 +13,15 @@ "url": "http://localhost:1050/login", "webRoot": "${workspaceFolder}", }, + { + "type": "node", + "request": "attach", + "name": "Typescript Server", + "protocol": "inspector", + "port": 9229, + "localRoot": "${workspaceFolder}", + "remoteRoot": "." + }, { "type": "node", "request": "launch", diff --git a/package.json b/package.json index 1eb546a80..fd794d062 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "scripts": { "start": "ts-node-dev -- src/server/index.ts", + "debug": "ts-node-dev --inspect -- src/server/index.ts", "build": "webpack --env production", "test": "mocha -r ts-node/register test/**/*.ts", "tsc": "tsc" @@ -171,4 +172,4 @@ "uuid": "^3.3.2", "xoauth2": "^1.2.0" } -} +} \ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index b4252c2a1..f90724152 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -286,41 +286,31 @@ function GetRefField([id, callback]: [string, (result?: Transferable) => void]) Database.Instance.getDocument(id, 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"); - //if (diff.diff === Types.Text) { - //Search.Instance.updateDocument({ name: "john", burns: "true" }); - //Search.Instance.updateDocument({ id: diff.id, data: diff.diff.data }); - //console.log("set field"); - //} - const docid = { id: diff.id }; - var docfield = diff.diff; - docfield = JSON.parse(JSON.stringify(docfield).split("fields.").join("")); + const docfield = diff.diff; + const update: any = { id: diff.id }; console.log("FIELD: ", docfield); - var dynfield = false; - for (var key in docfield) { + let dynfield = false; + for (let key in docfield) { + if (!key.startsWith("fields.")) continue; const val = docfield[key]; - if (typeof val === 'number') { - const new_key: string = key + "_n"; - docfield = JSON.parse(JSON.stringify(docfield).split(key).join(new_key)); - //docfield[new_key] = { 'set': val }; - dynfield = true; - } - else if (typeof val === 'string') { - const new_key: string = key + "_t"; - docfield = JSON.parse(JSON.stringify(docfield).split(key).join(new_key)); - docfield[new_key] = { 'set': val }; + 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; } } - var merged = {}; - _.extend(merged, docid, docfield); - console.log("MERGED: ", merged); - console.log("DOC_FIELD: ", docfield); if (dynfield) { console.log("dynamic field detected!"); - Search.Instance.updateDocument(merged); + Search.Instance.updateDocument(update); } } -- cgit v1.2.3-70-g09d2 From e19fdbba4cf672aee5bfb59b91b6162431d146d3 Mon Sep 17 00:00:00 2001 From: ab Date: Sat, 4 May 2019 18:48:01 -0400 Subject: queries semi work --- package.json | 3 ++- src/debug/Test.tsx | 19 ++++++++++++++++++- src/server/Search.ts | 25 +++++++++++++++++++++++++ src/server/index.ts | 3 +++ 4 files changed, 48 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/package.json b/package.json index fd794d062..3393eacc6 100644 --- a/package.json +++ b/package.json @@ -167,9 +167,10 @@ "serializr": "^1.5.1", "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", + "solr-node": "^1.1.3", "typescript-collections": "^1.3.2", "url-loader": "^1.1.2", "uuid": "^3.3.2", "xoauth2": "^1.2.0" } -} \ No newline at end of file +} diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx index 47cfac2c1..7d72a1ba0 100644 --- a/src/debug/Test.tsx +++ b/src/debug/Test.tsx @@ -3,6 +3,9 @@ import * as ReactDOM from 'react-dom'; import { serialize, deserialize, map } from 'serializr'; import { URLField, Doc, createSchema, makeInterface, makeStrictInterface, List, ListSpec } from '../fields/NewDoc'; import { SerializationHelper } from '../client/util/SerializationHelper'; +import { Search } from '../server/Search'; +import { restProperty } from 'babel-types'; +import * as rp from 'request-promise'; const schema1 = createSchema({ hello: "number", @@ -76,8 +79,22 @@ class Test extends React.Component { // console.log(SerializationHelper.Serialize(l)); } + onEnter = async (e: any) => { + var key = e.keyCode || e.which; + if (key === 13) { + var query = e.target.value; + await rp.get('http://localhost:1050/search', { + qs: { + query + } + }); + } + } + render() { - return ; + return
+ +
; } } diff --git a/src/server/Search.ts b/src/server/Search.ts index 9e462f0ae..4911edd1d 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -5,6 +5,31 @@ import { thisExpression } from 'babel-types'; export class Search { public static Instance = new Search(); private url = 'http://localhost:8983/solr/'; + private client: any; + + 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)); diff --git a/src/server/index.ts b/src/server/index.ts index f90724152..f2bcd3f00 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -122,11 +122,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); }); -- cgit v1.2.3-70-g09d2 From d6919d0779df080990c52157540564af95c98a18 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 6 May 2019 15:17:59 -0400 Subject: Added synchronization to db insert --- src/server/database.ts | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src/server') diff --git a/src/server/database.ts b/src/server/database.ts index 37cfcf3a3..69005d2d3 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -22,13 +22,6 @@ export class Database { return new Promise(resolve => { 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]; } @@ -52,11 +45,27 @@ export class Database { } public insert(value: any, collectionName = Database.DocumentsCollection) { + if (!this.db) { return; } if ("id" in value) { value._id = value.id; delete value.id; } - this.db && this.db.collection(collectionName).insertOne(value); + const id = value._id; + const collection = this.db.collection(collectionName); + const prom = this.currentWrites[id]; + let newProm: Promise; + const run = (): Promise => { + return new Promise(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) { -- cgit v1.2.3-70-g09d2 From 6683c5450eb25da291090091421e791bf0498aba Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 7 May 2019 16:56:41 -0400 Subject: Fix after merge --- src/server/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index 2381f9840..6b92e8e8e 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -303,7 +303,10 @@ const suffixMap: { [type: string]: string } = { 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 docfield = diff.diff.$set; + if (!docfield) { + return; + } const update: any = { id: diff.id }; console.log("FIELD: ", docfield); let dynfield = false; -- cgit v1.2.3-70-g09d2 From 152fadbad5d3c4e9c452bb6a1ade543bd84c6416 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 7 May 2019 19:26:36 -0400 Subject: Added copy fields to search to enable easier searching --- solr/conf/schema.xml | 13 ++++++++++--- src/server/Search.ts | 26 -------------------------- src/server/index.ts | 3 --- 3 files changed, 10 insertions(+), 32 deletions(-) (limited to 'src/server') diff --git a/solr/conf/schema.xml b/solr/conf/schema.xml index 5e80b17d9..99087a1db 100644 --- a/solr/conf/schema.xml +++ b/solr/conf/schema.xml @@ -40,10 +40,17 @@ - + - - + + + + + + + + + diff --git a/src/server/Search.ts b/src/server/Search.ts index 4911edd1d..59bdd4803 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -5,34 +5,8 @@ import { thisExpression } from 'babel-types'; export class Search { public static Instance = new Search(); private url = 'http://localhost:8983/solr/'; - private client: any; - - 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]) diff --git a/src/server/index.ts b/src/server/index.ts index 6b92e8e8e..44251de3d 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -308,7 +308,6 @@ function UpdateField(socket: Socket, diff: Diff) { return; } const update: any = { id: diff.id }; - console.log("FIELD: ", docfield); let dynfield = false; for (let key in docfield) { if (!key.startsWith("fields.")) continue; @@ -322,14 +321,12 @@ function UpdateField(socket: Socket, diff: Diff) { } } 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); -- cgit v1.2.3-70-g09d2 From 85d8e29c15b45cd83d258f185d3d55ff400a145e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 7 May 2019 21:57:48 -0400 Subject: Added date support --- solr/conf/schema.xml | 1 + solr/conf/solrconfig.xml | 2 +- src/server/index.ts | 24 ++++++++++++++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src/server') diff --git a/solr/conf/schema.xml b/solr/conf/schema.xml index 99087a1db..3d1ccb698 100644 --- a/solr/conf/schema.xml +++ b/solr/conf/schema.xml @@ -46,6 +46,7 @@ + diff --git a/solr/conf/solrconfig.xml b/solr/conf/solrconfig.xml index 981500022..90eff5363 100644 --- a/solr/conf/solrconfig.xml +++ b/solr/conf/solrconfig.xml @@ -696,7 +696,7 @@ explicit 10 - data + text diff --git a/src/server/index.ts b/src/server/index.ts index 44251de3d..5023bf717 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -296,10 +296,17 @@ function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => v } -const suffixMap: { [type: string]: string } = { +const suffixMap: { [type: string]: string | [string, string] | [string, string, (json: any) => any] } = { "number": "_n", - "string": "_t" + "string": "_t", + "image": ["_t", "url"], + "video": ["_t", "url"], + "pdf": ["_t", "url"], + "audio": ["_t", "url"], + "web": ["_t", "url"], + "date": ["_d", "date", millis => new Date(millis).toISOString()], }; + function UpdateField(socket: Socket, diff: Diff) { Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments"); @@ -311,9 +318,18 @@ function UpdateField(socket: Socket, diff: Diff) { let dynfield = false; for (let key in docfield) { if (!key.startsWith("fields.")) continue; - const val = docfield[key]; - const suffix = suffixMap[typeof val]; + let val = docfield[key]; + const type = val.__type || typeof val; + let suffix = suffixMap[type]; if (suffix !== undefined) { + if (Array.isArray(suffix)) { + val = val[suffix[1]]; + const func = suffix[2]; + if (func) { + val = func(val); + } + suffix = suffix[0]; + } key = key.substring(7); Object.values(suffixMap).forEach(suf => update[key + suf] = null); update[key + suffix] = { set: val }; -- cgit v1.2.3-70-g09d2 From 823b04d8084f14e298a408615eccf712dd76e2b9 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 7 May 2019 22:27:15 -0400 Subject: Removed console.logs --- src/server/Search.ts | 2 -- src/server/index.ts | 1 - 2 files changed, 3 deletions(-) (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts index 7a670e21b..59bdd4803 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -14,8 +14,6 @@ export class Search { } public async search(query: string) { - console.log("____________________________"); - console.log(query); const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { qs: { q: query diff --git a/src/server/index.ts b/src/server/index.ts index 5023bf717..5c54babb2 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -128,7 +128,6 @@ app.get("/pull", (req, res) => 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); }); -- cgit v1.2.3-70-g09d2 From c7b2ccddb6d75283a7255b612693c5e809b68f5f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 9 May 2019 00:26:09 -0400 Subject: Added lists and documents to search --- solr/conf/schema.xml | 12 +++++---- src/client/documents/Documents.ts | 1 + src/server/index.ts | 51 ++++++++++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 19 deletions(-) (limited to 'src/server') diff --git a/solr/conf/schema.xml b/solr/conf/schema.xml index 92ba9c6ff..a568db14c 100644 --- a/solr/conf/schema.xml +++ b/solr/conf/schema.xml @@ -35,19 +35,21 @@ - + - - - + + + - + + + diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a770ccc93..00233a989 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -175,6 +175,7 @@ export namespace Docs { if (!("creationDate" in protoProps)) { protoProps.creationDate = new DateField; } + protoProps.isPrototype = true; return SetDelegateOptions(SetInstanceOptions(proto, protoProps, data), delegateProps); } diff --git a/src/server/index.ts b/src/server/index.ts index 5c54babb2..93e4cafbf 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -295,7 +295,7 @@ function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => v } -const suffixMap: { [type: string]: string | [string, string] | [string, string, (json: any) => any] } = { +const suffixMap: { [type: string]: (string | [string, string | ((json: any) => any)]) } = { "number": "_n", "string": "_t", "image": ["_t", "url"], @@ -303,9 +303,40 @@ const suffixMap: { [type: string]: string | [string, string] | [string, string, "pdf": ["_t", "url"], "audio": ["_t", "url"], "web": ["_t", "url"], - "date": ["_d", "date", millis => new Date(millis).toISOString()], + "date": ["_d", value => new Date(value.date).toISOString()], + "proxy": ["_i", "fieldId"], + "list": ["_l", list => { + const results = []; + for (const value of list.fields) { + const term = ToSearchTerm(value); + if (term) { + results.push(term.value); + } + } + return results.length ? results : null; + }] }; +function ToSearchTerm(val: any): { suffix: string, value: any } | undefined { + const type = val.__type || typeof val; + let suffix = suffixMap[type]; + if (!suffix) { + return; + } + + if (Array.isArray(suffix)) { + const accessor = suffix[1]; + if (typeof accessor === "function") { + val = accessor(val); + } else { + val = val[accessor]; + } + suffix = suffix[0]; + } + + return { suffix, value: val } +} + function UpdateField(socket: Socket, diff: Diff) { Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments"); @@ -318,20 +349,12 @@ function UpdateField(socket: Socket, diff: Diff) { for (let key in docfield) { if (!key.startsWith("fields.")) continue; let val = docfield[key]; - const type = val.__type || typeof val; - let suffix = suffixMap[type]; - if (suffix !== undefined) { - if (Array.isArray(suffix)) { - val = val[suffix[1]]; - const func = suffix[2]; - if (func) { - val = func(val); - } - suffix = suffix[0]; - } + let term = ToSearchTerm(val); + if (term !== undefined) { + let { suffix, value } = term; key = key.substring(7); Object.values(suffixMap).forEach(suf => update[key + suf] = null); - update[key + suffix] = { set: val }; + update[key + suffix] = { set: value }; dynfield = true; } } -- cgit v1.2.3-70-g09d2 From b18aec5d4b07bbc859a5b1b2d22ca3bd92ca53cd Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 9 May 2019 20:30:40 -0400 Subject: Added try catches to search to not throw errors on the server --- src/server/Search.ts | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts index 59bdd4803..1d8cfdcf0 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -7,31 +7,39 @@ export class Search { private url = 'http://localhost:8983/solr/'; public async updateDocument(document: any) { - return rp.post(this.url + "dash/update", { - headers: { 'content-type': 'application/json' }, - body: JSON.stringify([document]) - }); + try { + return rp.post(this.url + "dash/update", { + headers: { 'content-type': 'application/json' }, + body: JSON.stringify([document]) + }); + } catch { } } public async search(query: string) { - const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { - qs: { - q: query - } - })); - const fields = searchResults.response.docs; - const ids = fields.map((field: any) => field.id); - return ids; + try { + const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { + qs: { + q: query + } + })); + const fields = searchResults.response.docs; + const ids = fields.map((field: any) => field.id); + return ids; + } catch { + return []; + } } public async clear() { - return rp.post(this.url + "dash/update", { - body: { - delete: { - query: "*:*" - } - }, - json: true - }); + try { + return rp.post(this.url + "dash/update", { + body: { + delete: { + query: "*:*" + } + }, + json: true + }); + } catch { } } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9c004c61dad1b6d68dc5bbe6989a12c399866343 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 9 May 2019 21:04:45 -0400 Subject: Fixed exceptions in search --- src/server/Search.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/Search.ts b/src/server/Search.ts index 1d8cfdcf0..c3cb3c3e6 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -8,7 +8,7 @@ export class Search { public async updateDocument(document: any) { try { - return rp.post(this.url + "dash/update", { + return await rp.post(this.url + "dash/update", { headers: { 'content-type': 'application/json' }, body: JSON.stringify([document]) }); @@ -32,7 +32,7 @@ export class Search { public async clear() { try { - return rp.post(this.url + "dash/update", { + return await rp.post(this.url + "dash/update", { body: { delete: { query: "*:*" -- cgit v1.2.3-70-g09d2 From 5d3c1921644e5a99b0d3281bb601d14c7484bc6f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 9 May 2019 23:45:56 -0400 Subject: Fixed a couple small search things --- src/server/index.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index 93e4cafbf..7a548607f 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -318,6 +318,9 @@ const suffixMap: { [type: string]: (string | [string, string | ((json: any) => a }; function ToSearchTerm(val: any): { suffix: string, value: any } | undefined { + if (val === null || val === undefined) { + return; + } const type = val.__type || typeof val; let suffix = suffixMap[type]; if (!suffix) { @@ -334,7 +337,11 @@ function ToSearchTerm(val: any): { suffix: string, value: any } | undefined { suffix = suffix[0]; } - return { suffix, value: val } + return { suffix, value: val }; +} + +function getSuffix(value: string | [string, any]): string { + return typeof value === "string" ? value : value[0]; } function UpdateField(socket: Socket, diff: Diff) { @@ -348,14 +355,14 @@ function UpdateField(socket: Socket, diff: Diff) { let dynfield = false; for (let key in docfield) { if (!key.startsWith("fields.")) continue; + dynfield = true; + Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = null); let val = docfield[key]; let term = ToSearchTerm(val); if (term !== undefined) { let { suffix, value } = term; key = key.substring(7); - Object.values(suffixMap).forEach(suf => update[key + suf] = null); update[key + suffix] = { set: value }; - dynfield = true; } } if (dynfield) { -- cgit v1.2.3-70-g09d2 From 913244091c3ad3fefad7c9e3eeeeb432a9b3d15e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 10 May 2019 06:39:00 -0400 Subject: Refactored SearchBox Made DragManager able to handle async functions Cleaned up some other stuff --- src/client/util/DragManager.ts | 16 +++--- src/client/views/SearchBox.scss | 43 ++++++++-------- src/client/views/SearchBox.tsx | 106 ++++++++++++++++++++++++++++------------ src/server/Search.ts | 5 +- src/server/index.ts | 4 +- 5 files changed, 110 insertions(+), 64 deletions(-) (limited to 'src/server') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 266679c16..c0402f0c9 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -6,28 +6,28 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import * as globalCssVariables from "../views/globalCssVariables.scss"; export type dropActionType = "alias" | "copy" | undefined; -export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { - let onRowMove = action((e: PointerEvent): void => { +export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { + let onRowMove = async (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); - var dragData = new DragManager.DocumentDragData([docFunc()]); + var dragData = new DragManager.DocumentDragData([await docFunc()]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); - }); - let onRowUp = action((e: PointerEvent): void => { + }; + let onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); - }); - let onItemDown = (e: React.PointerEvent) => { + }; + let onItemDown = async (e: React.PointerEvent) => { // if (this.props.isSelected() || this.props.isTopMost) { if (e.button === 0) { e.stopPropagation(); if (e.shiftKey) { - CollectionDockingView.Instance.StartOtherDrag([docFunc()], e); + CollectionDockingView.Instance.StartOtherDrag([await docFunc()], e); } else { document.addEventListener("pointermove", onRowMove); document.addEventListener("pointerup", onRowUp); diff --git a/src/client/views/SearchBox.scss b/src/client/views/SearchBox.scss index 792d6dd3c..b38e6091d 100644 --- a/src/client/views/SearchBox.scss +++ b/src/client/views/SearchBox.scss @@ -1,47 +1,50 @@ @import "globalCssVariables"; -.searchBox { +.searchBox-bar { height: 32px; - //display: flex; - //padding: 4px; - -webkit-transition: width 0.4s ease-in-out; - transition: width 0.4s ease-in-out; + display: flex; + justify-content: flex-end; align-items: center; + padding-left: 2px; + padding-right: 2px; - - - input[type=text] { + .searchBox-input { width: 130px; -webkit-transition: width 0.4s; transition: width 0.4s; - position: absolute; - right: 100px; + align-self: stretch; } - input[type=text]:focus { + .searchBox-input:focus { width: 500px; outline: 3px solid lightblue; } - .filter-button { - position: absolute; - right: 30px; + .searchBox-barChild { + flex: 0 1 auto; + margin-left: 2px; + margin-right: 2px; } - .submit-search { - text-align: right; + .searchBox-filter { + align-self: stretch; + } + + .searchBox-submit { color: $dark-color; - -webkit-transition: right 0.4s; - transition: right 0.4s; } - .submit-search:hover { + .searchBox-submit:hover { color: $main-accent; transform: scale(1.05); cursor: pointer; } } +.searchBox-results { + margin-left: 27px; //Is there a better way to do this? +} + .filter-form { background: $dark-color; height: 400px; @@ -64,7 +67,7 @@ height: 20px; } -.results { +.searchBox-results { top: 300px; display: flex; flex-direction: column; diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 7dd1af4e7..9b9735a4b 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -4,7 +4,7 @@ import { observable, action, runInAction } from 'mobx'; import { Utils } from '../../Utils'; import { MessageStore } from '../../server/Message'; import "./SearchBox.scss"; -import { faSearch } from '@fortawesome/free-solid-svg-icons'; +import { faSearch, faObjectGroup } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { library } from '@fortawesome/fontawesome-svg-core'; // const app = express(); @@ -18,9 +18,11 @@ import { DocServer } from '../DocServer'; import { Doc } from '../../new_fields/Doc'; import { Id } from '../../new_fields/RefField'; import { DocumentManager } from '../util/DocumentManager'; - +import { SetupDrag } from '../util/DragManager'; +import { Docs } from '../documents/Documents'; library.add(faSearch); +library.add(faObjectGroup); @observer export class SearchBox extends React.Component { @@ -40,30 +42,33 @@ export class SearchBox extends React.Component { @action submitSearch = async () => { - runInAction(() => this._results = []); let query = this.searchString; - - let response = await rp.get('http://localhost:1050/search', { - qs: { - query - } - }); - let results = JSON.parse(response); - //gets json result into a list of documents that can be used - this.getResults(results); + const results = await this.getResults(query); - runInAction(() => { this._resultsOpen = true; }); + runInAction(() => { + this._resultsOpen = true; + this._results = results; + }); } @action - getResults = async (res: string[]) => { - res.map(async result => { - const doc = await DocServer.GetRefField(result); - if (doc instanceof Doc) { - runInAction(() => this._results.push(doc)); + getResults = async (query: string) => { + let response = await rp.get('http://localhost:1050/search', { + qs: { + query } }); + let res: string[] = JSON.parse(response); + const fields = await DocServer.GetRefFields(res); + const docs: Doc[] = []; + for (const id of res) { + const field = fields[id]; + if (field instanceof Doc) { + docs.push(field); + } + } + return docs; } @action @@ -82,6 +87,7 @@ export class SearchBox extends React.Component { var id = (e.target as any).id; if (id !== "result") { this._resultsOpen = false; + this._results = []; } } @@ -107,27 +113,63 @@ export class SearchBox extends React.Component { } } + collectionRef = React.createRef(); + startDragCollection = async () => { + const results = await this.getResults(this.searchString); + const docs = results.map(doc => { + const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); + if (isProto) { + return Doc.MakeDelegate(doc); + } else { + return Doc.MakeAlias(doc); + } + }); + let x = 0; + let y = 0; + for (const doc of docs) { + doc.x = x; + doc.y = y; + doc.width = 200; + doc.height = 200; + x += 250; + if (x > 1000) { + x = 0; + y += 250; + } + } + return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, title: `Search Docs: "${this.searchString}"` }); + } + render() { return ( -
-
- - - -
-
- {this._results.map(result => )} +
+
+
+ + + + + +
+ {this._resultsOpen ? ( +
+ {this._results.map(result => )} +
+ ) : null}
-
- -
- filter by collection, key, type of node + {this._open ? ( +
+ +
+ filter by collection, key, type of node
-
+
+ ) : null}
- ); } } \ No newline at end of file diff --git a/src/server/Search.ts b/src/server/Search.ts index c3cb3c3e6..1bede5b49 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -8,11 +8,12 @@ export class Search { public async updateDocument(document: any) { try { - return await rp.post(this.url + "dash/update", { + const res = await rp.post(this.url + "dash/update", { headers: { 'content-type': 'application/json' }, body: JSON.stringify([document]) }); - } catch { } + return res; + } catch (e) { } } public async search(query: string) { diff --git a/src/server/index.ts b/src/server/index.ts index 7a548607f..6c64aa161 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -356,12 +356,12 @@ function UpdateField(socket: Socket, diff: Diff) { for (let key in docfield) { if (!key.startsWith("fields.")) continue; dynfield = true; - Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = null); let val = docfield[key]; + key = key.substring(7); + Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = null); let term = ToSearchTerm(val); if (term !== undefined) { let { suffix, value } = term; - key = key.substring(7); update[key + suffix] = { set: value }; } } -- cgit v1.2.3-70-g09d2 From 89ca54d2d335cf7d44107b03014333ee5501eb7b Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 10 May 2019 11:42:42 -0400 Subject: fixed search! --- src/client/views/collections/CollectionDockingView.tsx | 1 - src/server/index.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 159815ea5..5ee943da9 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -412,7 +412,6 @@ export class DockedFrameRenderer extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyFunction} - bringToFront={emptyFunction} ContainingCollectionView={undefined} />
); } diff --git a/src/server/index.ts b/src/server/index.ts index 6c64aa161..e5cc3ce68 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -358,7 +358,7 @@ function UpdateField(socket: Socket, diff: Diff) { dynfield = true; let val = docfield[key]; key = key.substring(7); - Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = null); + Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = { set: null }); let term = ToSearchTerm(val); if (term !== undefined) { let { suffix, value } = term; -- cgit v1.2.3-70-g09d2 From a225d9f4ee0d44e8cb14f30f27571ec0e846e1e1 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 12 May 2019 01:43:03 -0400 Subject: Small search changed --- solr/conf/schema.xml | 3 ++- src/client/views/SearchBox.tsx | 3 +++ src/server/Search.ts | 4 +++- src/server/index.ts | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/solr/conf/schema.xml b/solr/conf/schema.xml index a568db14c..9217e015b 100644 --- a/solr/conf/schema.xml +++ b/solr/conf/schema.xml @@ -48,8 +48,9 @@ - + + diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 134201071..6e64e1af1 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -140,6 +140,9 @@ export class SearchBox extends React.Component { return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, title: `Search Docs: "${this.searchString}"` }); } + // Useful queries: + // Delegates of a document: {!join from=id to=proto_i}id:{protoId} + // Documents in a collection: {!join from=data_l to=id}id:{collectionProtoId} render() { return (
diff --git a/src/server/Search.ts b/src/server/Search.ts index 1bede5b49..0f7004bdf 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -13,7 +13,9 @@ export class Search { body: JSON.stringify([document]) }); return res; - } catch (e) { } + } catch (e) { + console.warn("Search error: " + e + document); + } } public async search(query: string) { diff --git a/src/server/index.ts b/src/server/index.ts index e5cc3ce68..da6bc0165 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -298,6 +298,7 @@ function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => v const suffixMap: { [type: string]: (string | [string, string | ((json: any) => any)]) } = { "number": "_n", "string": "_t", + // "boolean": "_b", "image": ["_t", "url"], "video": ["_t", "url"], "pdf": ["_t", "url"], -- cgit v1.2.3-70-g09d2 From f52f5a408c62b93ae79eb690ff86538a6fbf60ed Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 12 May 2019 22:56:13 -0400 Subject: Started adding flyout to go up a level --- src/client/goldenLayout.js | 1 + .../views/collections/CollectionDockingView.tsx | 18 +++++++++- .../views/collections/ParentDocumentSelector.scss | 8 +++++ .../views/collections/ParentDocumentSelector.tsx | 39 ++++++++++++++++++++++ src/server/Search.ts | 3 +- 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/client/views/collections/ParentDocumentSelector.scss create mode 100644 src/client/views/collections/ParentDocumentSelector.tsx (limited to 'src/server') diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js index 56a71f1ac..ab2bcefed 100644 --- a/src/client/goldenLayout.js +++ b/src/client/goldenLayout.js @@ -2902,6 +2902,7 @@ * @returns {void} */ _$destroy: function () { + this._layoutManager.emit('tabDestroyed', this); this.element.off('mousedown touchstart', this._onTabClickFn); this.closeElement.off('click touchstart', this._onCloseClickFn); if (this._dragListener) { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index efcee9c02..8739a213f 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -18,6 +18,7 @@ import { DocumentView } from "../nodes/DocumentView"; import "./CollectionDockingView.scss"; import { SubCollectionViewProps } from "./CollectionSubView"; import React = require("react"); +import { ParentDocSelector } from './ParentDocumentSelector'; @observer export class CollectionDockingView extends React.Component { @@ -157,6 +158,7 @@ export class CollectionDockingView extends React.Component { if (doc instanceof Doc) { - let counter: any = this.htmlToElement(`
0
`); + let counter: any = this.htmlToElement(`0
`); tab.element.append(counter); + let upDiv = document.createElement("span"); + ReactDOM.render(, upDiv); + tab.reactComponents = [upDiv]; + tab.element.append(upDiv); counter.DashDocId = tab.contentItem.config.props.documentId; tab.reactionDisposer = reaction(() => [doc.linkedFromDocs, doc.LinkedToDocs, doc.title], () => { @@ -320,6 +328,14 @@ export class CollectionDockingView extends React.Component { + if (tab.reactComponents) { + for (const ele of tab.reactComponents) { + ReactDOM.unmountComponentAtNode(ele); + } + } + } _removedDocs: Doc[] = []; stackCreated = (stack: any) => { diff --git a/src/client/views/collections/ParentDocumentSelector.scss b/src/client/views/collections/ParentDocumentSelector.scss new file mode 100644 index 000000000..f3c605f3e --- /dev/null +++ b/src/client/views/collections/ParentDocumentSelector.scss @@ -0,0 +1,8 @@ +.PDS-flyout { + position: absolute; + z-index: 9999; + background-color: #d3d3d3; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + min-width: 150px; + color: black; +} \ No newline at end of file diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx new file mode 100644 index 000000000..1fdb9d4d9 --- /dev/null +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -0,0 +1,39 @@ +import * as React from "react"; +import './ParentDocumentSelector.scss'; +import { Doc } from "../../../new_fields/Doc"; +import { observer } from "mobx-react"; +import { observable, action } from "mobx"; + +@observer +export class ParentDocSelector extends React.Component<{ Document: Doc }> { + @observable hover = false; + + @action + onMouseLeave = () => { + this.hover = false; + } + + @action + onMouseEnter = () => { + this.hover = true; + } + + render() { + let flyout; + if (this.hover) { + flyout = ( +
+

Hello world

+
+ ); + } + return ( + +

^

+ {flyout} +
+ ); + } +} diff --git a/src/server/Search.ts b/src/server/Search.ts index 0f7004bdf..5ca5578a7 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -22,7 +22,8 @@ export class Search { try { const searchResults = JSON.parse(await rp.get(this.url + "dash/select", { qs: { - q: query + q: query, + fl: "id" } })); const fields = searchResults.response.docs; -- cgit v1.2.3-70-g09d2 From 281bfa589bd1ca66823003ca91cc11ce895fe5e2 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 14 May 2019 18:59:32 -0400 Subject: fixes for northstar --- src/client/documents/Documents.ts | 9 ++- src/client/northstar/dash-fields/HistogramField.ts | 11 ++-- .../dash-nodes/HistogramBinPrimitiveCollection.ts | 4 +- src/client/northstar/dash-nodes/HistogramBox.tsx | 16 +++--- .../dash-nodes/HistogramBoxPrimitives.tsx | 3 - src/client/northstar/manager/Gateway.ts | 12 ++++ src/client/northstar/model/ModelHelpers.ts | 10 +++- src/client/northstar/model/idea/idea.ts | 6 ++ src/client/northstar/operations/BaseOperation.ts | 17 ------ .../northstar/operations/HistogramOperation.ts | 12 ++-- src/client/views/Main.tsx | 54 +----------------- .../views/collections/CollectionSchemaView.tsx | 39 ++++++++++++- .../collections/collectionFreeForm/MarqueeView.tsx | 7 ++- src/client/views/nodes/DocumentView.tsx | 2 +- .../authentication/models/current_user_utils.ts | 65 ++++++++++++++++++++-- 15 files changed, 162 insertions(+), 105 deletions(-) (limited to 'src/server') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 11929455c..ed260d42e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -33,6 +33,7 @@ import { DocServer } from "../DocServer"; import { StrokeData, InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; +import { schema } from "prosemirror-schema-basic"; export interface DocumentOptions { x?: number; @@ -207,16 +208,18 @@ export namespace Docs { export function PdfDocument(url: string, options: DocumentOptions = {}) { return CreateInstance(pdfProto, new PdfField(new URL(url)), options); } + export async function DBDocument(url: string, options: 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)); + 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) => { @@ -251,8 +254,8 @@ export namespace Docs { } return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform }); } - export function SchemaDocument(documents: Array, options: DocumentOptions) { - return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Schema }); + export function SchemaDocument(schemaColumns: string[], documents: Array, options: DocumentOptions) { + return CreateInstance(collProto, new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index f01f08487..aabc77bb2 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -9,7 +9,8 @@ import { OmitKeys } from "../../../Utils"; import { Deserializable } from "../../util/SerializationHelper"; function serialize(field: HistogramField) { - return OmitKeys(field.HistoOp, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; + let obj = OmitKeys(field, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; + return obj; } function deserialize(jp: any) { @@ -31,10 +32,10 @@ function deserialize(jp: any) { } }); if (X && Y && V) { - return new HistogramField(new HistogramOperation(jp.SchemaName, X, Y, V, jp.Normalization)); + return new HistogramOperation(jp.SchemaName, X, Y, V, jp.Normalization); } } - return new HistogramField(HistogramOperation.Empty); + return HistogramOperation.Empty; } @Deserializable("histogramField") @@ -50,6 +51,8 @@ export class HistogramField extends ObjectField { } [Copy]() { - return new HistogramField(this.HistoOp.Copy()); + let y = this.HistoOp; + let z = this.HistoOp["Copy"]; + return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } } \ No newline at end of file diff --git a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts index 6291ec1fc..3e9145a1b 100644 --- a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts +++ b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts @@ -198,8 +198,8 @@ export class HistogramBinPrimitiveCollection { var marginParams = new MarginAggregateParameters(); marginParams.aggregateFunction = axis.AggregateFunction; var marginAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, axis, this.histoResult, brush.brushIndex!, marginParams); - var marginResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey) as MarginAggregateResult; - return !marginResult ? 0 : marginResult.absolutMargin!; + let aggResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey); + return aggResult instanceof MarginAggregateResult && aggResult.absolutMargin ? aggResult.absolutMargin : 0; } private createBinPrimitive(barAxis: number, brush: Brush, marginRect: PIXIRectangle, diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index ed556cf45..eb1ad69b7 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -17,9 +17,8 @@ import "./HistogramBox.scss"; import { HistogramBoxPrimitives } from './HistogramBoxPrimitives'; import { HistogramLabelPrimitives } from "./HistogramLabelPrimitives"; import { StyleConstants } from "../utils/StyleContants"; -import { NumCast, Cast } from "../../../new_fields/Types"; -import { listSpec } from "../../../new_fields/Schema"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Cast } from "../../../new_fields/Types"; +import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/RefField"; @@ -119,15 +118,16 @@ export class HistogramBox extends React.Component { if (this.HistoOp !== HistogramOperation.Empty) { reaction(() => DocListCast(this.props.Document.linkedFromDocs), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true }); reaction(() => DocListCast(this.props.Document.brushingDocs).length, - () => { - let brushingDocs = DocListCast(this.props.Document.brushingDocs); + async () => { + let brushingDocs = await DocListCastAsync(this.props.Document.brushingDocs); const proto = this.props.Document.proto; - if (proto) { - this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => { + if (proto && brushingDocs) { + let mapped = brushingDocs.map((brush, i) => { brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; let brushed = DocListCast(brush.brushingDocs); return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; - })); + }); + this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped); } }, { fireImmediately: true }); reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true }); diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx index 721bf6a89..350987695 100644 --- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx +++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx @@ -11,9 +11,6 @@ import { StyleConstants } from "../../northstar/utils/StyleContants"; import { HistogramBinPrimitiveCollection, HistogramBinPrimitive } from "./HistogramBinPrimitiveCollection"; import { HistogramBox } from "./HistogramBox"; import "./HistogramBoxPrimitives.scss"; -import { JSXElement } from "babel-types"; -import { Utils } from "../utils/Utils"; -import { all } from "bluebird"; export interface HistogramPrimitivesProps { HistoBox: HistogramBox; diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts index d26f2724f..c541cce6a 100644 --- a/src/client/northstar/manager/Gateway.ts +++ b/src/client/northstar/manager/Gateway.ts @@ -23,6 +23,18 @@ export class Gateway { } } + public async PostSchema(csvdata: string, schemaname: string): Promise { + try { + const json = await this.MakePostJsonRequest("postSchema", { csv: csvdata, schema: schemaname }); + // const cat = Catalog.fromJS(json); + // return cat; + return json; + } + catch (error) { + throw new Error("can not reach northstar's backend"); + } + } + public async GetSchema(pathname: string, schemaname: string): Promise { try { const json = await this.MakeGetRequest("schema", undefined, { path: pathname, schema: schemaname }); diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts index ac807b41f..80bb71224 100644 --- a/src/client/northstar/model/ModelHelpers.ts +++ b/src/client/northstar/model/ModelHelpers.ts @@ -31,7 +31,15 @@ export class ModelHelpers { } public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number { - return ArrayUtil.IndexOfWithEqual(histogramResult.aggregateParameters!, aggParameters); + return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => { + if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) + return true; + if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) + return true; + if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) + return true; + return false; + }); } public static GetAggregateParameter(distinctAttributeParameters: AttributeParameters | undefined, atm: AttributeTransformationModel): AggregateParameters | undefined { diff --git a/src/client/northstar/model/idea/idea.ts b/src/client/northstar/model/idea/idea.ts index 9d9d60678..c73a822c7 100644 --- a/src/client/northstar/model/idea/idea.ts +++ b/src/client/northstar/model/idea/idea.ts @@ -22,6 +22,9 @@ export abstract class AggregateParameters implements IAggregateParameters { protected _discriminator: string; + public Equals(other: Object): boolean { + return this == other; + } constructor(data?: IAggregateParameters) { if (data) { for (var property in data) { @@ -204,6 +207,9 @@ export interface IAverageAggregateParameters extends ISingleDimensionAggregatePa export abstract class AttributeParameters implements IAttributeParameters { visualizationHints?: VisualizationHint[] | undefined; rawName?: string | undefined; + public Equals(other: Object): boolean { + return this == other; + } protected _discriminator: string; diff --git a/src/client/northstar/operations/BaseOperation.ts b/src/client/northstar/operations/BaseOperation.ts index c6d5f0a15..0d1361ebf 100644 --- a/src/client/northstar/operations/BaseOperation.ts +++ b/src/client/northstar/operations/BaseOperation.ts @@ -25,23 +25,6 @@ export abstract class BaseOperation { @computed public get FilterString(): string { - - // let filterModels: FilterModel[] = []; - // return FilterModel.GetFilterModelsRecursive(this, new Set>(), filterModels, true) - // if (this.OverridingFilters.length > 0) { - // return "(" + this.OverridingFilters.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")"; - // } - // let rdg = MainManager.Instance.MainViewModel.FilterReverseDependencyGraph; - // let sliceModel = this.TypedViewModel.IncomingSliceModel; - // if (sliceModel !== null && sliceModel.Source !== null && instanceOfIBaseFilterProvider(sliceModel.Source) && rdg.has(sliceModel.Source)) { - // let filterModels = sliceModel.Source.FilterModels.map(f => f); - // return FilterModel.GetFilterModelsRecursive(rdg.get(sliceModel.Source), new Set>(), filterModels, false); - // } - - // if (rdg.has(this.TypedViewModel)) { - // let filterModels = []; - // return FilterModel.GetFilterModelsRecursive(rdg.get(this.TypedViewModel), new Set>(), filterModels, true) - // } return ""; } diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts index 78b206bdc..74e23ea48 100644 --- a/src/client/northstar/operations/HistogramOperation.ts +++ b/src/client/northstar/operations/HistogramOperation.ts @@ -30,7 +30,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @observable public V: AttributeTransformationModel; @observable public SchemaName: string; @observable public QRange: QuantitativeBinRange | undefined; - @computed public get Schema() { return CurrentUserUtils.GetNorthstarSchema(this.SchemaName); } + public get Schema() { return CurrentUserUtils.GetNorthstarSchema(this.SchemaName); } constructor(schemaName: string, x: AttributeTransformationModel, y: AttributeTransformationModel, v: AttributeTransformationModel, normalized?: number) { super(); @@ -41,7 +41,11 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons this.SchemaName = schemaName; } - Copy(): HistogramOperation { + public static Duplicate(op: HistogramOperation) { + + return new HistogramOperation(op.SchemaName, op.X, op.Y, op.V, op.Normalization); + } + public Copy(): HistogramOperation { return new HistogramOperation(this.SchemaName, this.X, this.Y, this.V, this.Normalization); } @@ -50,7 +54,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons } - @computed public get FilterModels() { + public get FilterModels() { return this.BarFilterModels; } @action @@ -71,9 +75,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons return FilterModel.GetFilterModelsRecursive(this, new Set(), filterModels, true); } - @computed public get BrushString(): string[] { - trace(); let brushes: string[] = []; this.BrushLinks.map(brushLink => { let brushHistogram = Cast(brushLink.b.data, HistogramField); diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 66205f8ca..385fc6ead 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -12,13 +12,6 @@ import { CurrentUserUtils } from '../../server/authentication/models/current_use import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils'; import { Docs } from '../documents/Documents'; -import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel'; -import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel'; -import { Gateway, NorthstarSettings } from '../northstar/manager/Gateway'; -import { AggregateFunction, Catalog } from '../northstar/model/idea/idea'; -import '../northstar/model/ModelExtensions'; -import { HistogramOperation } from '../northstar/operations/HistogramOperation'; -import '../northstar/utils/Extensions'; import { SetupDrag, DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; @@ -70,8 +63,6 @@ export class Main extends React.Component { } } - CurrentUserUtils.loadCurrentUser(); - library.add(faFont); library.add(faImage); library.add(faFilePdf); @@ -84,15 +75,8 @@ export class Main extends React.Component { library.add(faFilm); library.add(faMusic); library.add(faTree); - this.initEventListeners(); this.initAuthenticationRouters(); - - // try { - // this.initializeNorthstar(); - // } catch (e) { - - // } } componentDidMount() { window.onpopstate = this.onHistory; } @@ -155,7 +139,7 @@ export class Main extends React.Component { // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) setTimeout(() => { this.openWorkspace(mainDoc); - let pendingDocument = Docs.SchemaDocument([], { title: "New Mobile Uploads" }); + let pendingDocument = Docs.SchemaDocument(["title"], [], { title: "New Mobile Uploads" }); mainDoc.optionalRightCollection = pendingDocument; }, 0); } @@ -229,7 +213,7 @@ export class Main extends React.Component { let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" })); let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); - let addSchemaNode = action(() => Docs.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); + let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" })); let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" })); @@ -300,40 +284,6 @@ export class Main extends React.Component {
); } - - // --------------- Northstar hooks ------------- / - private _northstarSchemas: Doc[] = []; - - @action SetNorthstarCatalog(ctlog: Catalog) { - CurrentUserUtils.NorthstarDBCatalog = ctlog; - if (ctlog && ctlog.schemas) { - ctlog.schemas.map(schema => { - let schemaDocuments: Doc[] = []; - let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema); - Promise.all(attributesToBecomeDocs.reduce((promises, attr) => { - promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt) => { - 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.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! })); - } - }))); - return promises; - }, [] as Promise[])).finally(() => - this._northstarSchemas.push(Docs.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! }))); - }); - } - } - async initializeNorthstar(): Promise { - const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" }); - NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json()); - Gateway.Instance.ClearCatalog().then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog())); - } } (async () => { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 9ecccc559..f4ad5b357 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -20,11 +20,20 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { Opt, Field, Doc, DocListCastAsync, DocListCast } from "../../../new_fields/Doc"; -import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; import { Id } from "../../../new_fields/RefField"; import { isUndefined } from "typescript-collections/dist/lib/util"; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import { Gateway } from "../../northstar/manager/Gateway"; +import { DocServer } from "../../DocServer"; +import { ColumnAttributeModel } from "../../northstar/core/attribute/AttributeModel"; +import { HistogramOperation } from "../../northstar/operations/HistogramOperation"; +import { AggregateFunction } from "../../northstar/model/idea/idea"; +import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel"; +import { Docs } from "../../documents/Documents"; +import { ContextMenu } from "../ContextMenu"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 @@ -207,6 +216,32 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + onContextMenu = (e: React.MouseEvent): void => { + if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB }); + } + } + + @action + makeDB = async () => { + let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); + csv = csv.substr(0, csv.length - 1) + "\n"; + let self = this; + DocListCast(this.props.Document.data).map(doc => { + csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); + csv = csv.substr(0, csv.length - 1) + "\n"; + }) + csv.substring(0, csv.length - 1); + let dbName = StrCast(this.props.Document.title); + let res = await Gateway.Instance.PostSchema(csv, dbName); + if (self.props.CollectionView.props.addDocument) { + let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); + if (schemaDoc) { + self.props.CollectionView.props.addDocument(schemaDoc, false); + } + } + } + @action addColumn = () => { this.columns.push(this._newKeyName); @@ -325,7 +360,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { const children = this.children; return (
this.onDrop(e, {})} ref={this.createTarget}> + onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
({ diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 24dea200e..be7cddca6 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -17,6 +17,9 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { ImageField } from "../../../../new_fields/URLField"; import { Template, Templates } from "../../Templates"; +import { Gateway } from "../../../northstar/manager/Gateway"; +import { DocServer } from "../../../DocServer"; +import { Id } from "../../../../new_fields/RefField"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -111,8 +114,8 @@ export class MarqueeView extends React.Component doc.title = i.toString(); docList.push(doc); } - let newCol = Docs.SchemaDocument(docList, { x: x, y: y, title: "-dropped table-", width: 300, height: 100 }); - newCol.proto!.schemaColumns = new List([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)]); + let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); + this.props.addDocument(newCol, false); } })(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b7ad9249a..c97bcbd94 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -306,7 +306,7 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: "Find aliases", event: async () => { const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(aliases, {})); + CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(["title"], aliases, {})); } }); cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])) }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 5f45d7bcc..5b63ac356 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,15 +1,21 @@ import { computed, observable, action, runInAction } from "mobx"; import * as rp from 'request-promise'; import { Docs } from "../../../client/documents/Documents"; -import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea"; +import { Attribute, AttributeGroup, Catalog, Schema, AggregateFunction } from "../../../client/northstar/model/idea/idea"; import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; import { RouteStore } from "../../RouteStore"; import { DocServer } from "../../../client/DocServer"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, Opt, Field } 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"; +import { NorthstarSettings, Gateway } from "../../../client/northstar/manager/Gateway"; +import { AttributeTransformationModel } from "../../../client/northstar/core/attribute/AttributeTransformationModel"; +import { ColumnAttributeModel } from "../../../client/northstar/core/attribute/AttributeModel"; +import { HistogramOperation } from "../../../client/northstar/operations/HistogramOperation"; +import { Cast, PromiseValue } from "../../../new_fields/Types"; +import { listSpec } from "../../../new_fields/Schema"; export class CurrentUserUtils { private static curr_email: string; @@ -31,13 +37,13 @@ export class CurrentUserUtils { doc.title = this.email; doc.data = new List(); doc.excludeFromLibrary = true; - doc.optionalRightCollection = Docs.SchemaDocument([], { title: "Pending documents" }); + doc.optionalRightCollection = Docs.SchemaDocument(["title"], [], { title: "Pending documents" }); // doc.library = Docs.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` }); // (doc.library as Doc).excludeFromLibrary = true; return doc; } - public static loadCurrentUser(): Promise { + public static async loadCurrentUser(): Promise { let userPromise = rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => { if (response) { let obj = JSON.parse(response); @@ -47,7 +53,7 @@ export class CurrentUserUtils { throw new Error("There should be a user! Why does Dash think there isn't one?"); } }); - let userDocPromise = rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => { + let userDocPromise = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => { if (id) { return DocServer.GetRefField(id).then(field => runInAction(() => this.user_document = field instanceof Doc ? field : this.createUserDocument(id))); @@ -55,14 +61,63 @@ 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(async sc => await Gateway.Instance.GetSchema("", sc))); + let catprom = CurrentUserUtils.SetNorthstarCatalog(await Gateway.Instance.GetCatalog(), extras); + if (catprom) await Promise.all(catprom); + } catch (e) { + + } return Promise.all([userPromise, userDocPromise]); } /* 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) => { + 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.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! })); + } + }))); + return promises; + }, [] as Promise[])); + return CurrentUserUtils._northstarSchemas.push(Docs.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); + let schemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []); + schemas.push(schema.displayName!); + CurrentUserUtils.UserDocument.DBSchemas = new List(schemas); + } + } public static GetNorthstarSchema(name: string): Schema | undefined { return !this._northstarCatalog || !this._northstarCatalog.schemas ? undefined : ArrayUtil.FirstOrDefault(this._northstarCatalog.schemas, (s: Schema) => s.displayName === name); -- cgit v1.2.3-70-g09d2 From b29a0d1cef60b55f609fcd94ad38232ae557e681 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 16 May 2019 18:32:57 -0400 Subject: Fixed linter errors --- src/client/goldenLayout.d.ts | 3 +++ src/client/northstar/dash-fields/HistogramField.ts | 2 +- src/client/northstar/model/ModelHelpers.ts | 9 +++---- src/client/util/DragManager.ts | 2 +- src/client/util/RichTextSchema.tsx | 16 +++++------ src/client/util/TooltipTextMenu.tsx | 13 ++++----- src/client/views/DocumentDecorations.tsx | 31 +++++++++++----------- src/client/views/PresentationView.tsx | 4 +-- src/client/views/TemplateMenu.tsx | 4 +-- .../views/collections/CollectionDockingView.tsx | 5 ++-- .../views/collections/CollectionSchemaView.tsx | 10 +++---- .../views/collections/CollectionTreeView.tsx | 9 ++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 13 ++++----- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 8 +++--- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 3 ++- src/client/views/nodes/VideoBox.tsx | 22 +++++++-------- src/new_fields/CursorField.ts | 6 ++--- src/new_fields/Doc.ts | 4 +-- src/new_fields/ObjectField.ts | 2 +- .../authentication/models/current_user_utils.ts | 2 +- 24 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 src/client/goldenLayout.d.ts (limited to 'src/server') diff --git a/src/client/goldenLayout.d.ts b/src/client/goldenLayout.d.ts new file mode 100644 index 000000000..b50240563 --- /dev/null +++ b/src/client/goldenLayout.d.ts @@ -0,0 +1,3 @@ + +declare const GoldenLayout: any; +export = GoldenLayout; \ No newline at end of file diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index aabc77bb2..1ee2189b9 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -52,7 +52,7 @@ export class HistogramField extends ObjectField { [Copy]() { let y = this.HistoOp; - let z = this.HistoOp["Copy"]; + let z = this.HistoOp.Copy; return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } } \ No newline at end of file diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts index 80bb71224..88e6e72b8 100644 --- a/src/client/northstar/model/ModelHelpers.ts +++ b/src/client/northstar/model/ModelHelpers.ts @@ -32,12 +32,9 @@ export class ModelHelpers { public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number { return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => { - if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) - return true; - if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) - return true; - if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) - return true; + if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) return true; + if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) return true; + if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) return true; return false; }); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 26da34e67..05eb5c38a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -41,7 +41,7 @@ export function SetupDrag(_reference: React.RefObject, 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); 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/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 6eb654319..223921428 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"; @@ -192,8 +192,9 @@ export class TooltipTextMenu { let docid = href.replace(DocServer.prepend("/doc/"), ""); DocServer.GetRefField(docid).then(action((f: Opt) => { 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 +202,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 +217,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 +240,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.tooltip.appendChild(this.linkEditor); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b2c65a31f..7083b1003 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -250,22 +250,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); } if (!this._removeIcon) { - if (selectedDocs.length === 1) + if (selectedDocs.length === 1) { this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized()); - else - if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && - Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { - let docViews = SelectionManager.ViewsSortedVertically(); - let topDocView = docViews[0]; - let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); - if (ind !== -1) { - topDocView.templates.splice(ind, 1); - topDocView.props.Document.subBulletDocs = undefined; - } else { - topDocView.addTemplate(Templates.Bullet); - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); - } + } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && + Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { + let docViews = SelectionManager.ViewsSortedVertically(); + let topDocView = docViews[0]; + let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); + if (ind !== -1) { + topDocView.templates.splice(ind, 1); + topDocView.props.Document.subBulletDocs = undefined; + } else { + topDocView.addTemplate(Templates.Bullet); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); } + } } this._removeIcon = false; } @@ -537,9 +536,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (temp !== Templates.Bullet.Layout || i === 0) { res.push(temp); } - }) + }); } - return res + return res; }, [] as string[]); let checked = false; docTemps.forEach(temp => { diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 098e725c7..7d0dc2913 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; -import React = require("react") +import React = require("react"); import { observable, action, runInAction, reaction } from "mobx"; -import "./PresentationView.scss" +import "./PresentationView.scss"; import "./Main.tsx"; import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index cfe1b0663..e5b679e24 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -43,7 +43,7 @@ export class TemplateMenu extends React.Component { @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { if (event.target.checked) { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.addTemplate(template); topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); @@ -52,7 +52,7 @@ export class TemplateMenu extends React.Component { } this.props.templates.set(template, true); } else { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.removeTemplate(template); topDocView.props.Document.subBulletDocs = undefined; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 58f1e33a1..deec64225 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -83,7 +83,7 @@ export class CollectionDockingView extends React.Component tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) { child.contentItems[j].remove(); @@ -94,8 +94,9 @@ export class CollectionDockingView extends React.Component doc) { let fieldContentView = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => - (this.props.CollectionView!.props.isSelected() ? + (this.props.CollectionView.props.isSelected() ? SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined); let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { const res = run({ this: doc }); @@ -127,7 +127,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } const run = script.run; //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]) + const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); val && val.forEach(doc => applyToDoc(doc, run)); }}> @@ -230,14 +230,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { DocListCast(this.props.Document.data).map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; - }) + }); csv.substring(0, csv.length - 1); let dbName = StrCast(this.props.Document.title); let res = await Gateway.Instance.PostSchema(csv, dbName); if (self.props.CollectionView.props.addDocument) { let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); if (schemaDoc) { - self.props.CollectionView.props.addDocument(schemaDoc, false); + self.props.CollectionView.props.addDocument(schemaDoc, false); } } } @@ -263,7 +263,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewDocument(): Doc | undefined { const children = DocListCast(this.props.Document[this.props.fieldKey]); const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined; - return selected ? (this.previewScript && this.previewScript != "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; + return selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; } get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); } get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 70c09d97c..6acef434e 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -56,7 +56,7 @@ class TreeView extends React.Component { } else { CollectionDockingView.Instance.AddRightSplit(this.props.document); } - }; + } get children() { return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed? .filter(doc => FieldValue(doc)); @@ -184,8 +184,9 @@ class TreeView extends React.Component { {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)}
); - } else + } else { bulletType = BulletType.Collapsed; + } } }); return
{
; } public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) { - return docs.filter(child => child instanceof Doc && !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).filter(doc => FieldValue(doc)).map(child => - ); + return docs.filter(child => !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).map(child => + ); } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 12edb2c2a..c3c4115b8 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -63,7 +63,7 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); for (let i = 0; i < ns.length - 1; i++) { while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || ns[i].endsWith(";\r") || ns[i].endsWith(";") || @@ -80,7 +80,7 @@ export class MarqueeView extends React.Component let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); this.props.addDocument(newBox, false); y += 40 * this.props.getTransform().Scale; - }) + }); })(); } else if (e.key === "b" && e.ctrlKey) { //heuristically converts pasted text into a table. @@ -93,9 +93,10 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); - while (ns.length > 0 && ns[0].split("\t").length < 2) + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + while (ns.length > 0 && ns[0].split("\t").length < 2) { ns.splice(0, 1); + } if (ns.length > 0) { let columns = ns[0].split("\t"); let docList: Doc[] = []; @@ -109,7 +110,7 @@ export class MarqueeView extends React.Component let doc = new Doc(); columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { - doc["_group"] = groupAttr; + doc._group = groupAttr; } doc.title = i.toString(); docList.push(doc); @@ -284,7 +285,7 @@ export class MarqueeView extends React.Component // summarizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); // }); this.props.addLiveTextDocument(summary); - }) + }); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7c7ca9e25..d4f660b3f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]); } } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cf8bcbb42..428dd9b36 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -244,7 +244,7 @@ export class DocumentView extends DocComponent(Docu const protoDest = destDoc.proto; const protoSrc = sourceDoc.proto; - if (de.mods == "Control") { + if (de.mods === "Control") { let src = protoSrc ? protoSrc : sourceDoc; let dst = protoDest ? protoDest : destDoc; dst.data = src; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f24d4ae88..f30022508 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -184,7 +184,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), dispatchTransaction: this.dispatchTransaction, nodeViews: { - image(node, view, getPos) { return new ImageResizeView(node, view, getPos) } + image(node, view, getPos) { return new ImageResizeView(node, view, getPos); } } }); let text = StrCast(this.props.Document.documentText); @@ -232,9 +232,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(action((f: Opt) => { 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); + } else { + CollectionDockingView.Instance.AddRightSplit(f); + } } })); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6472ae711..3cc60a6c5 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -165,7 +165,7 @@ export class ImageBox extends DocComponent(ImageD else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50); let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; - let id = this.props.id; // bcz: used to set id = "isExpander" in templates.tsx + let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx return (
{ @observable private _keyInput: string = ""; @observable private _valueInput: string = ""; @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); } - get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document } + get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document; } constructor(props: FieldViewProps) { super(props); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 5de660d57..4f7919f50 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -46,8 +46,9 @@ export class KeyValuePair extends React.Component {
,
+
+ +
0 ? { "display": "initial" } : { "display": "none" }}> + {length} +
+
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 5686ccfef..2bccde241 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -16,6 +16,7 @@ export enum CollectionViewType { Schema, Docking, Tree, + Stacking } export interface CollectionRenderProps { diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss new file mode 100644 index 000000000..803e680e5 --- /dev/null +++ b/src/client/views/collections/CollectionStackingView.scss @@ -0,0 +1,44 @@ +@import "../globalCssVariables"; + +.collectionStackingView { + top: 0; + left: 0; + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + position: absolute; + overflow-y: scroll; + min-width: 250px; + border-width: 0; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + border-color: $light-color-secondary; + border-style: solid; + border-radius: 0 0 $border-radius $border-radius; + box-sizing: border-box; + + .collectionStackingView-docView-container { + width: 45%; + margin: 5% 2.5%; + padding-left: 2.5%; + height: auto; + } + + .collectionStackingView-flexCont { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + } + + .collectionStackingView-description { + font-size: 100%; + margin-bottom: 1vw; + padding: 10px; + height: 2vw; + width: 100%; + font-family: $sans-serif; + background: $dark-color; + color: $light-color; + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx new file mode 100644 index 000000000..a1cb73123 --- /dev/null +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -0,0 +1,54 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import { CollectionSubView } from "./CollectionSubView"; +import Measure from "react-measure"; +import { Doc, WidthSym, HeightSym } from "../../../new_fields/Doc"; +import { DocumentView } from "../nodes/DocumentView"; +import { Transform } from "../../util/Transform"; +import { emptyFunction, returnOne } from "../../../Utils"; +import "./CollectionStackingView.scss"; +import { runInAction, action, observable, computed } from "mobx"; +import { StrCast } from "../../../new_fields/Types"; + +@observer +export class CollectionStackingView extends CollectionSubView(doc => doc) { + getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform(); + + @action + moveDocument = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean): boolean => { + this.props.removeDocument(doc); + addDocument(doc); + return true; + } + + render() { + const docs = this.childDocs; + return ( +
e.stopPropagation()}> +
{StrCast(this.props.Document.documentText, StrCast(this.props.Document.title, "stacking collection"))}
+
+ {docs.map(d => { + return (
+ +
); + })} +
+
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index bfdef8e8c..39c8af4ab 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -12,6 +12,7 @@ import { CollectionDockingView } from "./CollectionDockingView"; import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import { CollectionStackingView } from './CollectionStackingView'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -31,6 +32,7 @@ export class CollectionView extends React.Component { case CollectionViewType.Schema: return (); case CollectionViewType.Docking: return (); case CollectionViewType.Tree: return (); + case CollectionViewType.Stacking: return (); case CollectionViewType.Freeform: default: return (); @@ -48,6 +50,7 @@ export class CollectionView extends React.Component { } ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); + ContextMenu.Instance.addItem({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); } } diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index d0b7d4e41..65305dd04 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -1,7 +1,13 @@ +@import "../client/views/globalCssVariables.scss"; + .imgupload_cont { - height: 100vh; + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; width: 100vw; - align-content: center; + height: 100vh; + .button_file { text-align: center; height: 50%; @@ -10,4 +16,15 @@ color: grey; font-size: 3em; } + + .upload_label { + width: 80vw; + height: 40vh; + background: $dark-color; + font-size: 10vw; + font-family: $sans-serif; + text-align: center; + padding-top: 20vh; + color: white; + } } \ No newline at end of file diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 690937339..84bbfeb14 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -71,6 +71,7 @@ const onFileLoad = async (file: React.ChangeEvent) => { ReactDOM.render((
{/* */} +
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index b947f5e01..e85aa2c74 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -37,7 +37,7 @@ export class CurrentUserUtils { doc.title = this.email; doc.data = new List(); doc.excludeFromLibrary = true; - doc.optionalRightCollection = Docs.SchemaDocument(["title"], [], { title: "Pending documents" }); + doc.optionalRightCollection = Docs.StackingDocument([], { title: "New mobile uploads" }); // doc.library = Docs.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` }); // (doc.library as Doc).excludeFromLibrary = true; return doc; -- cgit v1.2.3-70-g09d2 From fe9dbb871d613d6a55873bd317d0d1af13a50ad8 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 22 May 2019 13:34:59 -0400 Subject: Tried script --- src/server/remapUrl.ts | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/server/remapUrl.ts (limited to 'src/server') diff --git a/src/server/remapUrl.ts b/src/server/remapUrl.ts new file mode 100644 index 000000000..90044738f --- /dev/null +++ b/src/server/remapUrl.ts @@ -0,0 +1,59 @@ +import { Database } from "./database"; +import { Search } from "./Search"; +import * as path from 'path'; + +const suffixMap: { [type: string]: true } = { + "video": true, + "pdf": true, + "audio": true, + "web": true +}; + +async function update() { + await new Promise(res => setTimeout(res, 10)); + console.log("update"); + const cursor = await Database.Instance.query({}); + console.log("Cleared"); + const updates: [string, any][] = []; + function updateDoc(doc: any) { + if (doc.__type !== "Doc") { + return; + } + const fields = doc.fields; + if (!fields) { + return; + } + const update: any = { + }; + let dynfield = false; + for (const key in fields) { + const value = fields[key]; + if (value && value.__type && suffixMap[value.__type]) { + const url = new URL(value.url); + if (url.href.includes("azure")) { + dynfield = true; + + update.$set = { ["fields." + key]: { url: `${url.protocol}//localhost:1050${url.pathname}`, __type: "image" } }; + } + } + } + if (dynfield) { + updates.push([doc._id, update]); + } + } + await cursor.forEach(updateDoc); + await Promise.all(updates.map(doc => { + console.log(doc[0], doc[1]); + return new Promise(res => Database.Instance.update(doc[0], doc[1], () => { + console.log("wrote " + JSON.stringify(doc[1])); + res(); + })); + })); + console.log("Done"); + // await Promise.all(updates.map(update => { + // return limit(() => Search.Instance.updateDocument(update)); + // })); + cursor.close(); +} + +update(); -- cgit v1.2.3-70-g09d2 From 54a4ff2f080b1e5ab87b7a0954272fd82194924e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 23 May 2019 01:08:27 -0400 Subject: Fixed remapUrl script --- src/server/remapUrl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/remapUrl.ts b/src/server/remapUrl.ts index 90044738f..6f4d6642f 100644 --- a/src/server/remapUrl.ts +++ b/src/server/remapUrl.ts @@ -33,7 +33,7 @@ async function update() { if (url.href.includes("azure")) { dynfield = true; - update.$set = { ["fields." + key]: { url: `${url.protocol}//localhost:1050${url.pathname}`, __type: "image" } }; + update.$set = { ["fields." + key + ".url"]: `${url.protocol}//localhost:1050${url.pathname}` }; } } } @@ -47,7 +47,7 @@ async function update() { return new Promise(res => Database.Instance.update(doc[0], doc[1], () => { console.log("wrote " + JSON.stringify(doc[1])); res(); - })); + }, false, "newDocuments")); })); console.log("Done"); // await Promise.all(updates.map(update => { -- cgit v1.2.3-70-g09d2 From 20f45adceb17b8cfe47f979d6f20329163477126 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 23 May 2019 01:32:33 -0400 Subject: More image upload changes --- src/server/index.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index deb3c1bd6..fd66c90b4 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -172,9 +172,9 @@ const pngTypes = [".png", ".PNG"]; const jpgTypes = [".jpg", ".JPG", ".jpeg", ".JPEG"]; const uploadDir = __dirname + "/public/files/"; // SETTERS -addSecureRoute( - Method.POST, - (user, res, req) => { +app.post( + RouteStore.upload, + (req, res) => { let form = new formidable.IncomingForm(); form.uploadDir = uploadDir; form.keepExtensions = true; @@ -212,9 +212,7 @@ addSecureRoute( } res.send(names); }); - }, - undefined, - RouteStore.upload + } ); addSecureRoute( -- cgit v1.2.3-70-g09d2 From 05771afc1687f18bd645991d9a853637cc85e16f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 23 May 2019 02:46:37 -0400 Subject: Enabled https --- package.json | 1 + src/client/DocServer.ts | 2 +- src/server/index.ts | 14 ++++++++++---- src/server/server.cert | 21 +++++++++++++++++++++ src/server/server.key | 28 ++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 src/server/server.cert create mode 100644 src/server/server.key (limited to 'src/server') diff --git a/package.json b/package.json index aa4abb0a5..8e8d93747 100644 --- a/package.json +++ b/package.json @@ -117,6 +117,7 @@ "formidable": "^1.2.1", "golden-layout": "^1.5.9", "html-to-image": "^0.1.0", + "https": "^1.0.0", "i": "^0.3.6", "image-data-uri": "^2.0.0", "jsonwebtoken": "^8.5.0", diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index cbcf751ee..b1b5ae529 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -8,7 +8,7 @@ import { Id, HandleUpdate } from '../new_fields/FieldSymbols'; export namespace DocServer { const _cache: { [id: string]: RefField | Promise> } = {}; - const _socket = OpenSocket(`${window.location.protocol}//${window.location.hostname}:4321`); + const _socket = OpenSocket(`${window.location.origin}`); const GUID: string = Utils.GenerateGuid(); export function makeReadOnly() { diff --git a/src/server/index.ts b/src/server/index.ts index fd66c90b4..e39dfcc14 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -2,6 +2,7 @@ import * as bodyParser from 'body-parser'; import { exec } from 'child_process'; import * as cookieParser from 'cookie-parser'; import * as express from 'express'; +import * as https from 'https'; import * as session from 'express-session'; import * as expressValidator from 'express-validator'; import * as formidable from 'formidable'; @@ -172,6 +173,8 @@ const pngTypes = [".png", ".PNG"]; const jpgTypes = [".jpg", ".JPG", ".jpeg", ".JPEG"]; const uploadDir = __dirname + "/public/files/"; // SETTERS +//TODO This should be a secured route, but iPhones don't seem to deal well with out authentication, +// so in order for the image upload from phones to work, we can make this authenticated app.post( RouteStore.upload, (req, res) => { @@ -289,10 +292,13 @@ app.use(wdm(compiler, { publicPath: config.output.publicPath })); app.use(whm(compiler)); // start the Express server -app.listen(port, () => +const httpsServer = https.createServer({ + key: fs.readFileSync(__dirname + '/server.key'), + cert: fs.readFileSync(__dirname + '/server.cert') +}, app).listen(port, () => console.log(`server started at http://localhost:${port}`)); -const server = io(); +const server = io(httpsServer); interface Map { [key: string]: Client; } @@ -441,5 +447,5 @@ function CreateField(newValue: any) { Database.Instance.insert(newValue, "newDocuments"); } -server.listen(serverPort); -console.log(`listening on port ${serverPort}`); \ No newline at end of file +// server.listen(serverPort); +// console.log(`listening on port ${serverPort}`); \ No newline at end of file diff --git a/src/server/server.cert b/src/server/server.cert new file mode 100644 index 000000000..e1610914c --- /dev/null +++ b/src/server/server.cert @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDfzCCAmegAwIBAgIJAJzroap7RHCoMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAlVTMRUwEwYDVQQIDAxSaG9kZSBJc2xhbmQxEzARBgNVBAcMClByb3ZpZGVu +Y2UxGzAZBgNVBAoMEkJyb3duIEdyYXBoaWNzIExhYjAeFw0xOTA1MjMwNjMxMDla +Fw0xOTA2MjIwNjMxMDlaMFYxCzAJBgNVBAYTAlVTMRUwEwYDVQQIDAxSaG9kZSBJ +c2xhbmQxEzARBgNVBAcMClByb3ZpZGVuY2UxGzAZBgNVBAoMEkJyb3duIEdyYXBo +aWNzIExhYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZK+dfIICO/ +w2E28yd98HFMiUNqKVWq5wEncvtaCk3zT/xSRvPrdQo8wvkgGqmjdbbi9hH1wu4u +79MZTLIaSfU4JtVlchWyqT0Tp+y74KPEFAtIlV/PpHFYkG9728DumaBGg7x+a40j +8aCLKhy4ij97IVXdn43sVCOQJNfwuxuHz2ofgjg90T/HOP2Jt5mEOygkCjPQmU45 +iR2iwVDu0DFKgD+EsosJdZk5n8yBdMTKFNoIgWpo9IJRzQ3ROqq1npcXI7rSQ3MB +b+Hw3AkUIXfB18dfLZ+7WKzS0KEm5NM0H+C/bkzRo2D26BLYZQrzFZkk1diTevex +Ws7e+4khn+8CAwEAAaNQME4wHQYDVR0OBBYEFAYSFlBF7Z0zQHVzLspbaIpGvTp1 +MB8GA1UdIwQYMBaAFAYSFlBF7Z0zQHVzLspbaIpGvTp1MAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBAI2P2nl4Xn2BUwCOpFwCuyqB3/LTTmlz3qqdOfBj +glxw6UqiLTiEQUe/q1ssthDE71NbtuVRSggzdJcoIdjMQrtG+eN79Ao22ZzhGnAj +S/MTeybZmO+1Y7yV3RSEjXCmpxIGKueQsCYAdeoTpMny7BEtr09ZROccxDPcLI2H +K91FtuCZbG7Inx10X4/PVnp9Yr1GW6zWxMkEXLPXko0o8gIf9Kj7njNEF0RPsHd9 +L3tJny4y92huYSs2aPJWeEtRit0nXIu86qXfoomMFBCsFLbGhqtwCpqogeL+QS+1 +bv0MKJk82jMpG/oLxbWwesBk2tb8R4knL2WlX32HegawoHs= +-----END CERTIFICATE----- diff --git a/src/server/server.key b/src/server/server.key new file mode 100644 index 000000000..c8a4f2745 --- /dev/null +++ b/src/server/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGSvnXyCAjv8Nh +NvMnffBxTIlDailVqucBJ3L7WgpN80/8Ukbz63UKPML5IBqpo3W24vYR9cLuLu/T +GUyyGkn1OCbVZXIVsqk9E6fsu+CjxBQLSJVfz6RxWJBve9vA7pmgRoO8fmuNI/Gg +iyocuIo/eyFV3Z+N7FQjkCTX8Lsbh89qH4I4PdE/xzj9ibeZhDsoJAoz0JlOOYkd +osFQ7tAxSoA/hLKLCXWZOZ/MgXTEyhTaCIFqaPSCUc0N0TqqtZ6XFyO60kNzAW/h +8NwJFCF3wdfHXy2fu1is0tChJuTTNB/gv25M0aNg9ugS2GUK8xWZJNXYk3r3sVrO +3vuJIZ/vAgMBAAECggEAXvm+XUoviq/oxwFoyXua1MmR3UZV8gBfkL/yZM2lrdxi +bTqDXYVjk7mysVxdKO9wDF78+XE7IpY8rGGryIqq7dctUny6fgYK5YQqpEsAt6/M +4fKsCS4NV3TSCXPLt8cQsiHUK05p+TpEG19MlmEVZn51Ywk5yOJvEnGSFBPrqq0z +IRYksRThVeoFqy6J3BS26UqDVEwlhYAPk5bg9j/RaeyEmhEXzcjfnXuYdhqhMhzW +sS6O4DM/QYs9DTn31kJ2ycgyVaQ/LYNRhp9yIDVSCCJyaInBbV6PV8DdNdr8oXOH +4G95OtNGTuk9N6BMLDgj1KCEFUjE8bQD0TgMqljV0QKBgQD4aF+qinyAg8xwLsLl +SKw4amPtlipC1YrOZ17Vtq7bU0WFSfLrKJAyDkvkf5L9OIWWsQNzLbq6enomlurm +wgjjQyaNVEvQhuJ0P9ewu6CVSC3kT7jnTrQFEnIDSgY+Mt4dyp1HhDqxp4kdMOdf +DUjyXWhyXpkokq+YXSsyM84q/QKBgQDMWnycVF/vjBy/RbbYO0rZDOl8z6F2WIl/ +wDYVi4fwe1KVWo2J/95dJd9g5DkHqkuyGBQs5Thq05QBBNhsFG87I2ghHCSC7OIz +ME4sbkouXq4TpAvoiSvCZo5/Whgypuycx5Gn3aSWVStXOyZgyiLF2NcEvoaT4Qss +w9hfcIU4WwKBgQDvrbVwlYKfdYvSSiweksoo/O5CFXvdVLFDihXE2ylH0cboXnuW +TmMjCQxNApLO5LRwu4b6oQrkVrx5c3BfCqUMsoQGJWmpYBwr0lXI3qCIqUYuXoWo +GRY1NqDvb4MqjGYoFJFAqeL/+wifM8pquiTCRUI75+6baT0oI+1D2Rx5+QKBgQCQ +gDO5P5iPBR6Wyi8e+95TWOQJ07AyxSyFX19fIMlBbZLZ9aw8NugAKfWox/jjyLG5 +/3jUvkmEkJQJnGmFE3YL9V9+ei3/Po488B13IY3m+CBT1x5skgKVdnuw5f5SYuLR +gfUnJH1rqFH7XuImcwjfqhNxUWBMVUfXoazw39n0HQKBgDXGubSFovavDSTAhh1t +soMP+3yO+Ny/+Mv47cMfblqN7dItC58VcEX2IHd9Z9QgMNQ4BDCqRRDK4O1N7RLO +bq6qV9WPyNwsDAZJLH2h9Y3gpDvUNFo+Kq/7V4ZTqaJC1YOjDKTXRnoZIwAje+5x +iNk2xg38zIscD1Ff+tTCOnYA +-----END PRIVATE KEY----- -- cgit v1.2.3-70-g09d2 From 999f5ad95498a772aeed9ca84cf176d101efd946 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 23 May 2019 03:22:31 -0400 Subject: Small changes --- src/client/views/collections/CollectionSubView.tsx | 2 +- src/server/authentication/models/current_user_utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 4a21e4465..c4e72b23a 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -129,7 +129,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { options.dropAction = "copy"; } if (type.indexOf("html") !== -1) { - if (path.includes('localhost')) { + if (path.includes(window.location.hostname)) { let s = path.split('/'); let id = s[s.length - 1]; DocServer.GetRefField(id).then(field => { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e85aa2c74..add347a88 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -68,7 +68,7 @@ export class CurrentUserUtils { 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); + // if (catprom) await Promise.all(catprom); } catch (e) { } -- cgit v1.2.3-70-g09d2 From e90059327d8910f46b9f2fb48716eb9267a060b5 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 23 May 2019 03:24:03 -0400 Subject: Revert "Enabled https" This reverts commit 05771afc1687f18bd645991d9a853637cc85e16f. --- package.json | 1 - src/client/DocServer.ts | 2 +- src/server/index.ts | 14 ++++---------- src/server/server.cert | 21 --------------------- src/server/server.key | 28 ---------------------------- 5 files changed, 5 insertions(+), 61 deletions(-) delete mode 100644 src/server/server.cert delete mode 100644 src/server/server.key (limited to 'src/server') diff --git a/package.json b/package.json index 8e8d93747..aa4abb0a5 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,6 @@ "formidable": "^1.2.1", "golden-layout": "^1.5.9", "html-to-image": "^0.1.0", - "https": "^1.0.0", "i": "^0.3.6", "image-data-uri": "^2.0.0", "jsonwebtoken": "^8.5.0", diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index b1b5ae529..cbcf751ee 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -8,7 +8,7 @@ import { Id, HandleUpdate } from '../new_fields/FieldSymbols'; export namespace DocServer { const _cache: { [id: string]: RefField | Promise> } = {}; - const _socket = OpenSocket(`${window.location.origin}`); + const _socket = OpenSocket(`${window.location.protocol}//${window.location.hostname}:4321`); const GUID: string = Utils.GenerateGuid(); export function makeReadOnly() { diff --git a/src/server/index.ts b/src/server/index.ts index e39dfcc14..fd66c90b4 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -2,7 +2,6 @@ import * as bodyParser from 'body-parser'; import { exec } from 'child_process'; import * as cookieParser from 'cookie-parser'; import * as express from 'express'; -import * as https from 'https'; import * as session from 'express-session'; import * as expressValidator from 'express-validator'; import * as formidable from 'formidable'; @@ -173,8 +172,6 @@ const pngTypes = [".png", ".PNG"]; const jpgTypes = [".jpg", ".JPG", ".jpeg", ".JPEG"]; const uploadDir = __dirname + "/public/files/"; // SETTERS -//TODO This should be a secured route, but iPhones don't seem to deal well with out authentication, -// so in order for the image upload from phones to work, we can make this authenticated app.post( RouteStore.upload, (req, res) => { @@ -292,13 +289,10 @@ app.use(wdm(compiler, { publicPath: config.output.publicPath })); app.use(whm(compiler)); // start the Express server -const httpsServer = https.createServer({ - key: fs.readFileSync(__dirname + '/server.key'), - cert: fs.readFileSync(__dirname + '/server.cert') -}, app).listen(port, () => +app.listen(port, () => console.log(`server started at http://localhost:${port}`)); -const server = io(httpsServer); +const server = io(); interface Map { [key: string]: Client; } @@ -447,5 +441,5 @@ function CreateField(newValue: any) { Database.Instance.insert(newValue, "newDocuments"); } -// server.listen(serverPort); -// console.log(`listening on port ${serverPort}`); \ No newline at end of file +server.listen(serverPort); +console.log(`listening on port ${serverPort}`); \ No newline at end of file diff --git a/src/server/server.cert b/src/server/server.cert deleted file mode 100644 index e1610914c..000000000 --- a/src/server/server.cert +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDfzCCAmegAwIBAgIJAJzroap7RHCoMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV -BAYTAlVTMRUwEwYDVQQIDAxSaG9kZSBJc2xhbmQxEzARBgNVBAcMClByb3ZpZGVu -Y2UxGzAZBgNVBAoMEkJyb3duIEdyYXBoaWNzIExhYjAeFw0xOTA1MjMwNjMxMDla -Fw0xOTA2MjIwNjMxMDlaMFYxCzAJBgNVBAYTAlVTMRUwEwYDVQQIDAxSaG9kZSBJ -c2xhbmQxEzARBgNVBAcMClByb3ZpZGVuY2UxGzAZBgNVBAoMEkJyb3duIEdyYXBo -aWNzIExhYjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMZK+dfIICO/ -w2E28yd98HFMiUNqKVWq5wEncvtaCk3zT/xSRvPrdQo8wvkgGqmjdbbi9hH1wu4u -79MZTLIaSfU4JtVlchWyqT0Tp+y74KPEFAtIlV/PpHFYkG9728DumaBGg7x+a40j -8aCLKhy4ij97IVXdn43sVCOQJNfwuxuHz2ofgjg90T/HOP2Jt5mEOygkCjPQmU45 -iR2iwVDu0DFKgD+EsosJdZk5n8yBdMTKFNoIgWpo9IJRzQ3ROqq1npcXI7rSQ3MB -b+Hw3AkUIXfB18dfLZ+7WKzS0KEm5NM0H+C/bkzRo2D26BLYZQrzFZkk1diTevex -Ws7e+4khn+8CAwEAAaNQME4wHQYDVR0OBBYEFAYSFlBF7Z0zQHVzLspbaIpGvTp1 -MB8GA1UdIwQYMBaAFAYSFlBF7Z0zQHVzLspbaIpGvTp1MAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQELBQADggEBAI2P2nl4Xn2BUwCOpFwCuyqB3/LTTmlz3qqdOfBj -glxw6UqiLTiEQUe/q1ssthDE71NbtuVRSggzdJcoIdjMQrtG+eN79Ao22ZzhGnAj -S/MTeybZmO+1Y7yV3RSEjXCmpxIGKueQsCYAdeoTpMny7BEtr09ZROccxDPcLI2H -K91FtuCZbG7Inx10X4/PVnp9Yr1GW6zWxMkEXLPXko0o8gIf9Kj7njNEF0RPsHd9 -L3tJny4y92huYSs2aPJWeEtRit0nXIu86qXfoomMFBCsFLbGhqtwCpqogeL+QS+1 -bv0MKJk82jMpG/oLxbWwesBk2tb8R4knL2WlX32HegawoHs= ------END CERTIFICATE----- diff --git a/src/server/server.key b/src/server/server.key deleted file mode 100644 index c8a4f2745..000000000 --- a/src/server/server.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDGSvnXyCAjv8Nh -NvMnffBxTIlDailVqucBJ3L7WgpN80/8Ukbz63UKPML5IBqpo3W24vYR9cLuLu/T -GUyyGkn1OCbVZXIVsqk9E6fsu+CjxBQLSJVfz6RxWJBve9vA7pmgRoO8fmuNI/Gg -iyocuIo/eyFV3Z+N7FQjkCTX8Lsbh89qH4I4PdE/xzj9ibeZhDsoJAoz0JlOOYkd -osFQ7tAxSoA/hLKLCXWZOZ/MgXTEyhTaCIFqaPSCUc0N0TqqtZ6XFyO60kNzAW/h -8NwJFCF3wdfHXy2fu1is0tChJuTTNB/gv25M0aNg9ugS2GUK8xWZJNXYk3r3sVrO -3vuJIZ/vAgMBAAECggEAXvm+XUoviq/oxwFoyXua1MmR3UZV8gBfkL/yZM2lrdxi -bTqDXYVjk7mysVxdKO9wDF78+XE7IpY8rGGryIqq7dctUny6fgYK5YQqpEsAt6/M -4fKsCS4NV3TSCXPLt8cQsiHUK05p+TpEG19MlmEVZn51Ywk5yOJvEnGSFBPrqq0z -IRYksRThVeoFqy6J3BS26UqDVEwlhYAPk5bg9j/RaeyEmhEXzcjfnXuYdhqhMhzW -sS6O4DM/QYs9DTn31kJ2ycgyVaQ/LYNRhp9yIDVSCCJyaInBbV6PV8DdNdr8oXOH -4G95OtNGTuk9N6BMLDgj1KCEFUjE8bQD0TgMqljV0QKBgQD4aF+qinyAg8xwLsLl -SKw4amPtlipC1YrOZ17Vtq7bU0WFSfLrKJAyDkvkf5L9OIWWsQNzLbq6enomlurm -wgjjQyaNVEvQhuJ0P9ewu6CVSC3kT7jnTrQFEnIDSgY+Mt4dyp1HhDqxp4kdMOdf -DUjyXWhyXpkokq+YXSsyM84q/QKBgQDMWnycVF/vjBy/RbbYO0rZDOl8z6F2WIl/ -wDYVi4fwe1KVWo2J/95dJd9g5DkHqkuyGBQs5Thq05QBBNhsFG87I2ghHCSC7OIz -ME4sbkouXq4TpAvoiSvCZo5/Whgypuycx5Gn3aSWVStXOyZgyiLF2NcEvoaT4Qss -w9hfcIU4WwKBgQDvrbVwlYKfdYvSSiweksoo/O5CFXvdVLFDihXE2ylH0cboXnuW -TmMjCQxNApLO5LRwu4b6oQrkVrx5c3BfCqUMsoQGJWmpYBwr0lXI3qCIqUYuXoWo -GRY1NqDvb4MqjGYoFJFAqeL/+wifM8pquiTCRUI75+6baT0oI+1D2Rx5+QKBgQCQ -gDO5P5iPBR6Wyi8e+95TWOQJ07AyxSyFX19fIMlBbZLZ9aw8NugAKfWox/jjyLG5 -/3jUvkmEkJQJnGmFE3YL9V9+ei3/Po488B13IY3m+CBT1x5skgKVdnuw5f5SYuLR -gfUnJH1rqFH7XuImcwjfqhNxUWBMVUfXoazw39n0HQKBgDXGubSFovavDSTAhh1t -soMP+3yO+Ny/+Mv47cMfblqN7dItC58VcEX2IHd9Z9QgMNQ4BDCqRRDK4O1N7RLO -bq6qV9WPyNwsDAZJLH2h9Y3gpDvUNFo+Kq/7V4ZTqaJC1YOjDKTXRnoZIwAje+5x -iNk2xg38zIscD1Ff+tTCOnYA ------END PRIVATE KEY----- -- cgit v1.2.3-70-g09d2 From 890a40ef8cc2efa7beea5722301b59ede5141238 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 30 May 2019 13:47:53 -0400 Subject: fixed context menus and tree view jitter. --- src/client/util/DragManager.ts | 4 +-- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/MainView.tsx | 6 ++-- .../views/collections/CollectionDockingView.tsx | 6 +++- .../views/collections/CollectionTreeView.scss | 6 +++- .../views/collections/CollectionTreeView.tsx | 33 +++++++++++++--------- src/client/views/collections/CollectionView.tsx | 30 +++++++------------- src/client/views/nodes/DocumentView.tsx | 31 ++++++++++++++------ src/client/views/nodes/FormattedTextBox.tsx | 25 +--------------- src/client/views/nodes/ImageBox.tsx | 11 ++++---- .../authentication/models/current_user_utils.ts | 20 ++++++------- 13 files changed, 85 insertions(+), 93 deletions(-) (limited to 'src/server') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7f75a95f0..8f0cce095 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -26,7 +26,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () // if (this.props.isSelected() || this.props.isTopMost) { if (e.button === 0) { e.stopPropagation(); - if (e.shiftKey) { + if (e.shiftKey && CollectionDockingView.Instance) { CollectionDockingView.Instance.StartOtherDrag([await docFunc()], e); } else { document.addEventListener("pointermove", onRowMove); @@ -264,7 +264,7 @@ export namespace DragManager { if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined; } - if (e.shiftKey) { + if (e.shiftKey && CollectionDockingView.Instance) { AbortDrag(); CollectionDockingView.Instance.StartOtherDrag(docs, { pageX: e.pageX, diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index a1f80120f..5dd10f1bf 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -194,7 +194,7 @@ export class TooltipTextMenu { if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); } - else CollectionDockingView.Instance.AddRightSplit(f); + else if (CollectionDockingView.Instance) CollectionDockingView.Instance.AddRightSplit(f); } })); } diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 61ae69179..74acba615 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -22,7 +22,7 @@ color: $light-color; } -.subMenu-cont { +.contextMenu-subMenu-cont { position: absolute; display: flex; z-index: 1000; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 63347e076..fcda0db89 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -56,7 +56,7 @@ export class ContextMenuItem extends React.Component { } else { let submenu = !this.overItem ? (null) : -
+
{this._items.map(prop => )}
; return ( diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 74dafadc4..a093ffdec 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -104,7 +104,9 @@ export class MainView extends React.Component { }, false); // drag event handler // click interactions for the context menu document.addEventListener("pointerdown", action(function (e: PointerEvent) { - if (!ContextMenu.Instance.intersects(e.pageX, e.pageY)) { + + const targets = document.elementsFromPoint(e.x, e.y); + if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) { ContextMenu.Instance.clearItems(); } }), true); @@ -163,7 +165,7 @@ export class MainView extends React.Component { } openNotifsCol = () => { - if (this._notifsCol) { + if (this._notifsCol && CollectionDockingView.Instance) { CollectionDockingView.Instance.AddRightSplit(this._notifsCol); } } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index b6076b5f7..dcc1bd95d 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -22,6 +22,7 @@ import { ParentDocSelector } from './ParentDocumentSelector'; import { DocumentManager } from '../../util/DocumentManager'; import { CollectionViewType } from './CollectionBaseView'; import { Id } from '../../../new_fields/FieldSymbols'; +import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; @observer export class CollectionDockingView extends React.Component { @@ -415,7 +416,10 @@ export class DockedFrameRenderer extends React.Component { @observable private _panelHeight = 0; @observable private _document: Opt; get _stack(): any { - return (this.props as any).glContainer.parent.parent; + let parent = (this.props as any).glContainer.parent.parent; + if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) + return parent.parent.contentItems[1]; + return parent; } constructor(props: any) { super(props); diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 2f0329fc4..bb3be0a73 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -48,7 +48,11 @@ .treeViewItem-openRight { display: inline-block; // display: inline; - transform: translate(0px, -3px); //TODO Fix this + svg { + display:block; + padding:0px; + margin: 0px; + } } } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 85aab96d3..2814c0502 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -9,7 +9,7 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); import { Document, listSpec } from '../../../new_fields/Schema'; -import { Cast, StrCast, BoolCast, FieldValue } from '../../../new_fields/Types'; +import { Cast, StrCast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types'; import { Doc, DocListCast } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { ContextMenu } from '../ContextMenu'; @@ -19,6 +19,7 @@ import { CollectionDockingView } from './CollectionDockingView'; import { DocumentManager } from '../../util/DocumentManager'; import { Docs } from '../../documents/Documents'; import { MainView } from '../MainView'; +import { CollectionViewType } from './CollectionBaseView'; export interface TreeViewProps { @@ -54,7 +55,7 @@ class TreeView extends React.Component { if (this.props.document.dockingConfig) { MainView.Instance.openWorkspace(this.props.document); } else { - CollectionDockingView.Instance.AddRightSplit(this.props.document); + this.props.addDocTab(this.props.document, "openRight"); } } @@ -122,11 +123,11 @@ class TreeView extends React.Component { return true; }} />); - let dataDocs = Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []); + let dataDocs = CollectionDockingView.Instance ? Cast(CollectionDockingView.Instance.props.Document.data, listSpec(Doc), []) : []; let openRight = dataDocs && dataDocs.indexOf(this.props.document) !== -1 ? (null) : (
- + {/* */}
); return (
{ } onWorkspaceContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.props.document)) }); - ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight") }); - ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.KVPDocument(this.props.document, { width: 300, height: 300 }), "onRight") }); - if (DocumentManager.Instance.getDocumentViews(this.props.document).length) { - ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.props.document).map(view => view.props.focus(this.props.document)) }); + ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.KVPDocument(this.props.document, { width: 300, height: 300 }), "onRight"), icon: "layer-group" }); + if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) { + ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab"), icon: "folder" }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight"), icon: "caret-square-right" }); + if (DocumentManager.Instance.getDocumentViews(this.props.document).length) { + ContextMenu.Instance.addItem({ description: "Focus", event: () => DocumentManager.Instance.getDocumentViews(this.props.document).map(view => view.props.focus(this.props.document)) }); + } + ContextMenu.Instance.addItem({ description: "Delete Item", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); + } else { + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); } - ContextMenu.Instance.addItem({ description: "Delete", event: undoBatch(() => this.props.deleteDoc(this.props.document)) }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); e.stopPropagation(); } @@ -207,11 +213,10 @@ export class CollectionTreeView extends CollectionSubView(Document) { } } onContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout + if (!e.isPropagationStopped() && this.props.Document.excludeFromLibrary) { // excludeFromLibrary means this is the user document ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()) }); - } - if (!ContextMenu.Instance.getItems().some(item => item.description === "Delete")) { - ContextMenu.Instance.addItem({ description: "Delete", event: undoBatch(() => this.remove(this.props.Document)) }); + ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) }); } } render() { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a1e7c7c69..68eefab4c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,20 +1,19 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faProjectDiagram, faSquare, faTh, faTree, faSignature, faThList } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; import { Id } from '../../../new_fields/FieldSymbols'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from '../ContextMenuItem'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import { CollectionBaseView, CollectionRenderProps, CollectionViewType } from './CollectionBaseView'; import { CollectionDockingView } from "./CollectionDockingView"; -import { CollectionSchemaView } from "./CollectionSchemaView"; -import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; -import { NumCast } from '../../../new_fields/Types'; -import { WidthSym, HeightSym } from '../../../new_fields/Doc'; +import { CollectionTreeView } from "./CollectionTreeView"; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -44,26 +43,17 @@ export class CollectionView extends React.Component { get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's? - freezeNativeDimensions = (e: React.MouseEvent): void => { - if (NumCast(this.props.Document.nativeWidth)) { - this.props.Document.proto!.nativeWidth = undefined; - this.props.Document.proto!.nativeHeight = undefined; - - } else { - this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); - } - } onContextMenu = (e: React.MouseEvent): void => { if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); + let subItems: ContextMenuProps[] = []; + subItems.push({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform), icon: "signature" }); if (CollectionBaseView.InSafeMode()) { ContextMenu.Instance.addItem({ description: "Test Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Invalid), icon: "project-diagram" }); } - ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); - ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); - ContextMenu.Instance.addItem({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); - ContextMenu.Instance.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" }); + subItems.push({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "th-list" }); + subItems.push({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); + subItems.push({ description: "Stacking", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Stacking), icon: "th-list" }); + ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems }); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a16a52ac6..69691b6f3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -29,6 +29,7 @@ import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; +import { ContextMenuProps } from '../ContextMenuItem'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); @@ -263,7 +264,7 @@ export class DocumentView extends DocComponent(Docu expandedProtoDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized); } } - if (maxLocation && maxLocation !== "inPlace") { + if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) { let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data); if (dataDocs) { expandedDocs.forEach(maxDoc => @@ -295,7 +296,7 @@ export class DocumentView extends DocComponent(Docu this._downX = e.clientX; this._downY = e.clientY; this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0; - if (e.shiftKey && e.buttons === 1) { + if (e.shiftKey && e.buttons === 1 && CollectionDockingView.Instance) { CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e); e.stopPropagation(); } else { @@ -341,7 +342,7 @@ export class DocumentView extends DocComponent(Docu } } fullScreenClicked = (): void => { - CollectionDockingView.Instance.OpenFullScreen(Doc.MakeCopy(this.props.Document, false)); + CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(Doc.MakeCopy(this.props.Document, false)); SelectionManager.DeselectAll(); } @@ -398,6 +399,17 @@ export class DocumentView extends DocComponent(Docu this.templates = this.templates; } + freezeNativeDimensions = (e: React.MouseEvent): void => { + if (NumCast(this.props.Document.nativeWidth)) { + this.props.Document.proto!.nativeWidth = undefined; + this.props.Document.proto!.nativeHeight = undefined; + + } else { + this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); + this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); + } + } + @action onContextMenu = (e: React.MouseEvent): void => { e.stopPropagation(); @@ -409,16 +421,19 @@ export class DocumentView extends DocComponent(Docu e.preventDefault(); const cm = ContextMenu.Instance; - cm.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "desktop" }); - cm.addItem({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "inTab"), icon: "folder" }); - cm.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document), icon: "caret-square-right" }); - cm.addItem({ description: "Fields", event: this.fieldsClicked, icon: "layer-group" }); + let subitems: ContextMenuProps[] = []; + subitems.push({ description: "Open Full Screen", event: this.fullScreenClicked, icon: "desktop" }); + subitems.push({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "inTab"), icon: "folder" }); + subitems.push({ description: "Open Right", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "onRight"), icon: "caret-square-right" }); + subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); + cm.addItem({ description: "Open...", subitems: subitems }); + cm.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" }); cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" }); cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" }); cm.addItem({ description: "Find aliases", event: async () => { const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(["title"], aliases, {})); + this.props.addDocTab && this.props.addDocTab(Docs.SchemaDocument(["title"], aliases, {}), "onRight"); }, icon: "search" }); cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" }); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index da584c811..5d93edaac 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -240,7 +240,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); } else { - CollectionDockingView.Instance.AddRightSplit(f); + this.props.addDocTab && this.props.addDocTab(f, "onRight"); } } })); @@ -274,29 +274,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } } } - - freezeNativeDimensions = (e: React.MouseEvent): void => { - if (NumCast(this.props.Document.nativeWidth)) { - this.props.Document.proto!.nativeWidth = undefined; - this.props.Document.proto!.nativeHeight = undefined; - - } else { - this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); - } - } - specificContextMenu = (e: React.MouseEvent): void => { - if (!this._gotDown) { - e.preventDefault(); - return; - } - ContextMenu.Instance.addItem({ - description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", - event: this.freezeNativeDimensions, - icon: "edit" - }); - } - onPointerWheel = (e: React.WheelEvent): void => { if (this.props.isSelected()) { e.stopPropagation(); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 8ea6c5436..4c2b73b70 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -19,6 +19,7 @@ import { InkingControl } from '../InkingControl'; import { Doc, WidthSym, HeightSym } from '../../../new_fields/Doc'; import { faImage } from '@fortawesome/free-solid-svg-icons'; import { library } from '@fortawesome/fontawesome-svg-core'; +import { ContextMenuItemProps, ContextMenuProps } from '../ContextMenuItem'; var path = require('path'); @@ -131,12 +132,9 @@ export class ImageBox extends DocComponent(ImageD let field = Cast(this.Document[this.props.fieldKey], ImageField); if (field) { let url = field.url.href; - ContextMenu.Instance.addItem({ - description: "Copy path", event: () => { - Utils.CopyText(url); - }, icon: "expand-arrows-alt" - }); - ContextMenu.Instance.addItem({ + let subitems: ContextMenuProps[] = []; + subitems.push({ description: "Copy path", event: () => Utils.CopyText(url), icon: "expand-arrows-alt" }); + subitems.push({ description: "Rotate", event: action(() => { this.props.Document.rotation = (NumCast(this.props.Document.rotation) + 90) % 360; let nw = this.props.Document.nativeWidth; @@ -147,6 +145,7 @@ export class ImageBox extends DocComponent(ImageD this.props.Document.height = w; }), icon: "expand-arrows-alt" }); + ContextMenu.Instance.addItem({ description: "Image Funcs...", subitems: subitems }); } } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index add347a88..e5b7a025b 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,21 +1,17 @@ -import { computed, observable, action, runInAction } from "mobx"; +import { action, computed, observable, runInAction } from "mobx"; import * as rp from 'request-promise'; +import { DocServer } from "../../../client/DocServer"; import { Docs } from "../../../client/documents/Documents"; -import { Attribute, AttributeGroup, Catalog, Schema, AggregateFunction } from "../../../client/northstar/model/idea/idea"; +import { Gateway, NorthstarSettings } from "../../../client/northstar/manager/Gateway"; +import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea"; import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; -import { RouteStore } from "../../RouteStore"; -import { DocServer } from "../../../client/DocServer"; -import { Doc, Opt, Field } 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"; -import { NorthstarSettings, Gateway } from "../../../client/northstar/manager/Gateway"; -import { AttributeTransformationModel } from "../../../client/northstar/core/attribute/AttributeTransformationModel"; -import { ColumnAttributeModel } from "../../../client/northstar/core/attribute/AttributeModel"; -import { HistogramOperation } from "../../../client/northstar/operations/HistogramOperation"; -import { Cast, PromiseValue } from "../../../new_fields/Types"; +import { Doc } from "../../../new_fields/Doc"; +import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; +import { Cast } from "../../../new_fields/Types"; +import { RouteStore } from "../../RouteStore"; export class CurrentUserUtils { private static curr_email: string; -- cgit v1.2.3-70-g09d2