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/server/authentication/models/current_user_utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/server') diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 5b63ac356..aef2d3f4a 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -66,7 +66,7 @@ export class CurrentUserUtils { 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 extras = await Promise.all(extraSchemas.map(sc => Gateway.Instance.GetSchema("", sc))); let catprom = CurrentUserUtils.SetNorthstarCatalog(await Gateway.Instance.GetCatalog(), extras); if (catprom) await Promise.all(catprom); } catch (e) { -- cgit v1.2.3-70-g09d2 From b841d1daa793c3e911a3188ffa27228481055974 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 17:21:07 -0400 Subject: Read only database --- src/server/index.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index da6bc0165..9696dab94 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -278,6 +278,7 @@ function getFields([ids, callback]: [string[], (result: Transferable[]) => void] } function setField(socket: Socket, newValue: Transferable) { + return; Database.Instance.update(newValue.id, newValue, () => socket.broadcast.emit(MessageStore.SetField.Message, newValue)); if (newValue.type === Types.Text) { @@ -346,6 +347,7 @@ function getSuffix(value: string | [string, any]): string { } function UpdateField(socket: Socket, diff: Diff) { + return; Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments"); const docfield = diff.diff.$set; @@ -362,8 +364,8 @@ function UpdateField(socket: Socket, diff: Diff) { Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = { set: null }); let term = ToSearchTerm(val); if (term !== undefined) { - let { suffix, value } = term; - update[key + suffix] = { set: value }; + // let { suffix, value } = term; + // update[key + suffix] = { set: value }; } } if (dynfield) { @@ -372,6 +374,7 @@ function UpdateField(socket: Socket, diff: Diff) { } function CreateField(newValue: any) { + return; Database.Instance.insert(newValue, "newDocuments"); } -- cgit v1.2.3-70-g09d2 From 20a1c2a1e59c02b29bbe744c57df6022952e2741 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 18:10:31 -0400 Subject: more debugging --- src/client/views/collections/CollectionTreeView.tsx | 3 +-- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/server/index.ts | 3 --- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src/server') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 4cc4ae6b6..72fa69cb1 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -17,7 +17,6 @@ import { undoBatch } from '../../util/UndoManager'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { CollectionDockingView } from './CollectionDockingView'; import { DocumentManager } from '../../util/DocumentManager'; -import { List } from '../../../new_fields/List'; import { Docs } from '../../documents/Documents'; import { MainView } from '../MainView'; @@ -232,7 +231,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
e.stopPropagation()} + onWheel={(e: React.WheelEvent) => this.props.isSelected() && e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
void] } function setField(socket: Socket, newValue: Transferable) { - return; Database.Instance.update(newValue.id, newValue, () => socket.broadcast.emit(MessageStore.SetField.Message, newValue)); if (newValue.type === Types.Text) { @@ -347,7 +346,6 @@ function getSuffix(value: string | [string, any]): string { } function UpdateField(socket: Socket, diff: Diff) { - return; Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments"); const docfield = diff.diff.$set; @@ -374,7 +372,6 @@ function UpdateField(socket: Socket, diff: Diff) { } function CreateField(newValue: any) { - return; Database.Instance.insert(newValue, "newDocuments"); } -- cgit v1.2.3-70-g09d2 From 873e2b9381a12ad0b2e6303f6a308d5d47e1f14f Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 04:31:11 -0400 Subject: Added downsizing images --- package.json | 2 ++ src/server/downsize.ts | 40 ++++++++++++++++++++++++++++++++++++++ src/server/index.ts | 33 ++++++++++++++++++++++++++++--- src/server/public/files/.gitignore | 3 ++- 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 src/server/downsize.ts (limited to 'src/server') diff --git a/package.json b/package.json index 147f59c25..0d0e6ff3e 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "@types/react-table": "^6.7.22", "@types/request": "^2.48.1", "@types/request-promise": "^4.1.42", + "@types/sharp": "^0.22.2", "@types/socket.io": "^2.1.2", "@types/socket.io-client": "^1.4.32", "@types/typescript": "^2.0.0", @@ -165,6 +166,7 @@ "request": "^2.88.0", "request-promise": "^4.2.4", "serializr": "^1.5.1", + "sharp": "^0.22.1", "socket.io": "^2.2.0", "socket.io-client": "^2.2.0", "solr-node": "^1.1.3", diff --git a/src/server/downsize.ts b/src/server/downsize.ts new file mode 100644 index 000000000..ed68fbecc --- /dev/null +++ b/src/server/downsize.ts @@ -0,0 +1,40 @@ +import * as sharp from 'sharp'; +import * as fs from 'fs'; + +const folder = "./src/server/public/files/"; +const pngTypes = ["png", "PNG"]; +const jpgTypes = ["jpg", "JPG", "jpeg", "JPEG"]; +const smallResizer = sharp().resize(100); +fs.readdir(folder, async (err, files) => { + if (err) { + console.log(err); + return; + } + // files.forEach(file => { + // if (file.includes("_s") || file.includes("_m") || file.includes("_l")) { + // fs.unlink(folder + file, () => { }); + // } + // }); + for (const file of files) { + const filesplit = file.split("."); + let resizers = [ + { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, + { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, + { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, + ]; + if (pngTypes.some(type => file.endsWith(type))) { + resizers.forEach(element => { + element.resizer = element.resizer.png(); + }); + } else if (jpgTypes.some(type => file.endsWith(type))) { + resizers.forEach(element => { + element.resizer = element.resizer.jpeg(); + }); + } else { + continue; + } + resizers.forEach(resizer => { + fs.createReadStream(folder + file).pipe(resizer.resizer).pipe(fs.createWriteStream(folder + filesplit[0] + resizer.suffix + "." + filesplit[1])); + }); + } +}); \ No newline at end of file diff --git a/src/server/index.ts b/src/server/index.ts index d19c65e0a..af99b116a 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -6,6 +6,7 @@ import * as session from 'express-session'; import * as expressValidator from 'express-validator'; import * as formidable from 'formidable'; import * as fs from 'fs'; +import * as sharp from 'sharp'; import * as mobileDetect from 'mobile-detect'; import { ObservableMap } from 'mobx'; import * as passport from 'passport'; @@ -166,13 +167,15 @@ addSecureRoute( RouteStore.getCurrUser ); +const pngTypes = [".png", ".PNG"]; +const jpgTypes = [".jpg", ".JPG", ".jpeg", ".JPEG"]; +const uploadDir = __dirname + "/public/files/"; // SETTERS - addSecureRoute( Method.POST, (user, res, req) => { let form = new formidable.IncomingForm(); - form.uploadDir = __dirname + "/public/files/"; + form.uploadDir = uploadDir; form.keepExtensions = true; // let path = req.body.path; console.log("upload"); @@ -180,7 +183,31 @@ addSecureRoute( console.log("parsing"); let names: string[] = []; for (const name in files) { - names.push(`/files/` + path.basename(files[name].path)); + const file = path.basename(files[name].path); + const ext = path.extname(file); + let resizers = [ + { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, + { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, + { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, + ]; + let isImage = false; + if (pngTypes.includes(ext)) { + resizers.forEach(element => { + element.resizer = element.resizer.png(); + }); + isImage = true; + } else if (jpgTypes.includes(ext)) { + resizers.forEach(element => { + element.resizer = element.resizer.jpeg(); + }); + isImage = true; + } + if (isImage) { + resizers.forEach(resizer => { + fs.createReadStream(uploadDir + file).pipe(resizer.resizer).pipe(fs.createWriteStream(uploadDir + file.substring(0, file.length - ext.length) + resizer.suffix + ext)); + }); + } + names.push(`/files/` + file); } res.send(names); }); diff --git a/src/server/public/files/.gitignore b/src/server/public/files/.gitignore index f59ec20aa..c96a04f00 100644 --- a/src/server/public/files/.gitignore +++ b/src/server/public/files/.gitignore @@ -1 +1,2 @@ -* \ No newline at end of file +* +!.gitignore \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 99bbb42cfa5718f543213f7a64463bd31c73d781 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 14:36:43 -0400 Subject: Added route to save data uri as image --- package.json | 1 + src/server/RouteStore.ts | 1 + src/server/index.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) (limited to 'src/server') diff --git a/package.json b/package.json index 0d0e6ff3e..40402b44c 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,7 @@ "golden-layout": "^1.5.9", "html-to-image": "^0.1.0", "i": "^0.3.6", + "image-data-uri": "^2.0.0", "jsonwebtoken": "^8.5.0", "jsx-to-string": "^1.4.0", "lodash": "^4.17.11", diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts index fdf5b6a5c..c4af5cdaa 100644 --- a/src/server/RouteStore.ts +++ b/src/server/RouteStore.ts @@ -11,6 +11,7 @@ export enum RouteStore { // UPLOAD AND STATIC FILE SERVING public = "/public", upload = "/upload", + dataUriToImage = "/uploadURI", images = "/images", // USER AND WORKSPACES diff --git a/src/server/index.ts b/src/server/index.ts index af99b116a..a12751fe3 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -7,6 +7,7 @@ import * as expressValidator from 'express-validator'; import * as formidable from 'formidable'; import * as fs from 'fs'; import * as sharp from 'sharp'; +const imageDataUri = require('image-data-uri'); import * as mobileDetect from 'mobile-detect'; import { ObservableMap } from 'mobx'; import * as passport from 'passport'; @@ -216,6 +217,45 @@ addSecureRoute( RouteStore.upload ); +addSecureRoute( + Method.POST, + (user, res, req) => { + const uri = req.query.uri; + const filename = req.query.name; + if (!uri || !filename) { + res.status(400).send("incorrect parameters specified"); + return; + } + imageDataUri.outputFile(uri, uploadDir + filename).then((savedName: string) => { + const ext = path.extname(savedName); + let resizers = [ + { resizer: sharp().resize(100, undefined, { withoutEnlargement: true }), suffix: "_s" }, + { resizer: sharp().resize(400, undefined, { withoutEnlargement: true }), suffix: "_m" }, + { resizer: sharp().resize(900, undefined, { withoutEnlargement: true }), suffix: "_l" }, + ]; + let isImage = false; + if (pngTypes.includes(ext)) { + resizers.forEach(element => { + element.resizer = element.resizer.png(); + }); + isImage = true; + } else if (jpgTypes.includes(ext)) { + resizers.forEach(element => { + element.resizer = element.resizer.jpeg(); + }); + isImage = true; + } + if (isImage) { + resizers.forEach(resizer => { + fs.createReadStream(savedName).pipe(resizer.resizer).pipe(fs.createWriteStream(uploadDir + filename + resizer.suffix + ext)); + }); + } + res.send("/files/" + filename + ext); + }); + }, + undefined, + RouteStore.dataUriToImage +); // AUTHENTICATION // Sign Up -- cgit v1.2.3-70-g09d2 From e02e8bee7ee36490b83edb0a416978216b0f4a17 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 15:46:21 -0400 Subject: hooking up image data url stuff. --- src/client/views/SearchBox.tsx | 17 +++++++++++++++++ src/client/views/nodes/PDFBox.tsx | 10 +++++++--- src/server/index.ts | 8 +++++--- 3 files changed, 29 insertions(+), 6 deletions(-) (limited to 'src/server') diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 8efd8d266..0ec1a6758 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -20,6 +20,7 @@ import { Id } from '../../new_fields/FieldSymbols'; import { DocumentManager } from '../util/DocumentManager'; import { SetupDrag } from '../util/DragManager'; import { Docs } from '../documents/Documents'; +import { RouteStore } from '../../server/RouteStore'; library.add(faSearch); library.add(faObjectGroup); @@ -70,6 +71,22 @@ export class SearchBox extends React.Component { } return docs; } + public static async convertDataUri(imageUri: string, returnedFilename: string) { + try { + let posting = DocServer.prepend(RouteStore.dataUriToImage); + const returnedUri = await rp.post(posting, { + body: { + uri: imageUri, + name: returnedFilename + }, + json: true, + }); + return returnedUri; + + } catch (e) { + console.log(e); + } + } @action handleClickFilter = (e: Event): void => { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index e71ac4924..1017f5235 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -21,6 +21,8 @@ import { positionSchema } from "./DocumentView"; import { pageSchema } from "./ImageBox"; import { ImageField, PdfField } from "../../../new_fields/URLField"; import { InkingControl } from "../InkingControl"; +import { SearchBox } from "../SearchBox"; +import { Id } from "../../../new_fields/FieldSymbols"; /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, @@ -250,9 +252,11 @@ export class PDFBox extends DocComponent(PdfDocumen let nheight = FieldValue(this.Document.nativeHeight, 0); htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 }) .then(action((dataUrl: string) => { - this.props.Document.thumbnail = new ImageField(new URL(dataUrl)); - this.props.Document.thumbnailPage = FieldValue(this.Document.curPage, -1); - this._renderAsSvg = true; + SearchBox.convertDataUri(dataUrl, this.Document[Id] + "_" + this.curPage).then((returnedFilename) => { + this.props.Document.thumbnail = new ImageField(new URL(dataUrl)); + this.props.Document.thumbnailPage = FieldValue(this.Document.curPage, -1); + this._renderAsSvg = true; + }) })) .catch(function (error: any) { console.error('oops, something went wrong!', error); diff --git a/src/server/index.ts b/src/server/index.ts index a12751fe3..6843afbe4 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -114,6 +114,8 @@ function addSecureRoute(method: Method, app.use(express.static(__dirname + RouteStore.public)); app.use(RouteStore.images, express.static(__dirname + RouteStore.public)); +app.use(express.json()); + app.get("/pull", (req, res) => exec('"C:\\Program Files\\Git\\git-bash.exe" -c "git pull"', (err, stdout, stderr) => { if (err) { @@ -220,10 +222,10 @@ addSecureRoute( addSecureRoute( Method.POST, (user, res, req) => { - const uri = req.query.uri; - const filename = req.query.name; + const uri = req.body.uri; + const filename = req.body.name; if (!uri || !filename) { - res.status(400).send("incorrect parameters specified"); + res.status(401).send("incorrect parameters specified"); return; } imageDataUri.outputFile(uri, uploadDir + filename).then((savedName: string) => { -- cgit v1.2.3-70-g09d2 From ba57c927bbb7b7ba80e65e8ada9520533f1270b6 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 15:49:57 -0400 Subject: uncommented search thing --- src/server/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index a12751fe3..0952e20aa 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -429,8 +429,8 @@ function UpdateField(socket: Socket, diff: Diff) { Object.values(suffixMap).forEach(suf => update[key + getSuffix(suf)] = { set: null }); let term = ToSearchTerm(val); if (term !== undefined) { - // let { suffix, value } = term; - // update[key + suffix] = { set: value }; + let { suffix, value } = term; + update[key + suffix] = { set: value }; } } if (dynfield) { -- cgit v1.2.3-70-g09d2 From fe3a7e6fbdcb10d764813d551ae052fa837f76ff Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 15:56:20 -0400 Subject: Fixed pdf uploader --- src/server/index.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index 5cdd62726..574241f62 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -60,7 +60,7 @@ app.use(session({ app.use(flash()); app.use(expressFlash()); -app.use(bodyParser.json()); +app.use(bodyParser.json({ limit: "10mb" })); app.use(bodyParser.urlencoded({ extended: true })); app.use(expressValidator()); app.use(passport.initialize()); @@ -114,8 +114,6 @@ function addSecureRoute(method: Method, app.use(express.static(__dirname + RouteStore.public)); app.use(RouteStore.images, express.static(__dirname + RouteStore.public)); -app.use(express.json()); - app.get("/pull", (req, res) => exec('"C:\\Program Files\\Git\\git-bash.exe" -c "git pull"', (err, stdout, stderr) => { if (err) { -- cgit v1.2.3-70-g09d2 From 7cde8383e45ccf8293ec9cba2beddc64bceda2aa Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 17:08:40 -0400 Subject: Added update search script Added debug current file launch config Made database not ignore requests before it is initialized. --- .vscode/launch.json | 24 +++++---- package.json | 1 + src/server/database.ts | 124 +++++++++++++++++++++++++++++---------------- src/server/updateSearch.ts | 101 ++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 54 deletions(-) create mode 100644 src/server/updateSearch.ts (limited to 'src/server') diff --git a/.vscode/launch.json b/.vscode/launch.json index 452acc823..d245be2ad 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -31,6 +31,20 @@ "localRoot": "${workspaceFolder}", "remoteRoot": "." }, + { + "type": "node", + "request": "launch", + "name": "Current TS File", + "runtimeExecutable": "npx", + "runtimeArgs": [ + "ts-node-dev", + "--nolazy", + "--inspect", + "--", + "${relativeFile}" + ], + "port": 9229 + }, { "type": "node", "request": "launch", @@ -65,15 +79,5 @@ "internalConsoleOptions": "openOnSessionStart", "protocol": "inspector" }, - { - "type": "node", - "request": "launch", - "name": "Launch via NPM", - "runtimeExecutable": "npm", - "runtimeArgs": [ - "start" - ], - "port": 9229 - } ] } \ No newline at end of file diff --git a/package.json b/package.json index 40402b44c..790535728 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,7 @@ "nodemon": "^1.18.10", "normalize.css": "^8.0.1", "npm": "^6.9.0", + "p-limit": "^2.2.0", "passport": "^0.4.0", "passport-local": "^1.0.0", "prosemirror-commands": "^1.0.7", diff --git a/src/server/database.ts b/src/server/database.ts index 69005d2d3..70b3efced 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -8,9 +8,13 @@ export class Database { private url = 'mongodb://localhost:27017/Dash'; private currentWrites: { [id: string]: Promise } = {}; private db?: mongodb.Db; + private onConnect: (() => void)[] = []; constructor() { - this.MongoClient.connect(this.url, (err, client) => this.db = client.db()); + this.MongoClient.connect(this.url, (err, client) => { + this.db = client.db(); + this.onConnect.forEach(fn => fn()); + }); } public update(id: string, value: any, callback: () => void, upsert = true, collectionName = Database.DocumentsCollection) { @@ -32,66 +36,98 @@ export class Database { }; newProm = prom ? prom.then(run) : run(); this.currentWrites[id] = newProm; + } else { + this.onConnect.push(() => this.update(id, value, callback, upsert, collectionName)); } } public delete(id: string, collectionName = Database.DocumentsCollection) { - this.db && this.db.collection(collectionName).remove({ id: id }); + if (this.db) { + this.db.collection(collectionName).remove({ id: id }); + } else { + this.onConnect.push(() => this.delete(id, collectionName)); + } } public deleteAll(collectionName = Database.DocumentsCollection): Promise { - return new Promise(res => - this.db && this.db.collection(collectionName).deleteMany({}, res)); + return new Promise(res => { + if (this.db) { + this.db.collection(collectionName).deleteMany({}, res); + } else { + this.onConnect.push(() => this.db && this.db.collection(collectionName).deleteMany({}, res)); + } + }); } public insert(value: any, collectionName = Database.DocumentsCollection) { - if (!this.db) { return; } - if ("id" in value) { - value._id = value.id; - delete value.id; - } - const id = value._id; - const collection = this.db.collection(collectionName); - const prom = this.currentWrites[id]; - let newProm: Promise; - const run = (): Promise => { - return new Promise(resolve => { - collection.insertOne(value, (err, res) => { - if (this.currentWrites[id] === newProm) { - delete this.currentWrites[id]; - } - resolve(); + if (this.db) { + if ("id" in value) { + value._id = value.id; + delete value.id; + } + const id = value._id; + const collection = this.db.collection(collectionName); + const prom = this.currentWrites[id]; + let newProm: Promise; + 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; + }; + newProm = prom ? prom.then(run) : run(); + this.currentWrites[id] = newProm; + } else { + this.onConnect.push(() => this.insert(value, collectionName)); + } } public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = Database.DocumentsCollection) { - this.db && this.db.collection(collectionName).findOne({ _id: id }, (err, result) => { - if (result) { - result.id = result._id; - delete result._id; - fn(result); - } else { - fn(undefined); - } - }); + if (this.db) { + this.db.collection(collectionName).findOne({ _id: id }, (err, result) => { + if (result) { + result.id = result._id; + delete result._id; + fn(result); + } else { + fn(undefined); + } + }); + } else { + this.onConnect.push(() => this.getDocument(id, fn, collectionName)); + } } public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = Database.DocumentsCollection) { - this.db && this.db.collection(collectionName).find({ _id: { "$in": ids } }).toArray((err, docs) => { - if (err) { - console.log(err.message); - console.log(err.errmsg); - } - fn(docs.map(doc => { - doc.id = doc._id; - delete doc._id; - return doc; - })); - }); + if (this.db) { + this.db.collection(collectionName).find({ _id: { "$in": ids } }).toArray((err, docs) => { + if (err) { + console.log(err.message); + console.log(err.errmsg); + } + fn(docs.map(doc => { + doc.id = doc._id; + delete doc._id; + return doc; + })); + }); + } else { + this.onConnect.push(() => this.getDocuments(ids, fn, collectionName)); + } + } + + public query(query: any): Promise { + if (this.db) { + return Promise.resolve(this.db.collection('newDocuments').find(query)); + } else { + return new Promise(res => { + this.onConnect.push(() => res(this.query(query))); + }); + } } public print() { diff --git a/src/server/updateSearch.ts b/src/server/updateSearch.ts new file mode 100644 index 000000000..da33e3747 --- /dev/null +++ b/src/server/updateSearch.ts @@ -0,0 +1,101 @@ +import { Database } from "./database"; +import { Cursor } from "mongodb"; +import { Search } from "./Search"; +import pLimit from 'p-limit'; + +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"], + "audio": ["_t", "url"], + "web": ["_t", "url"], + "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 { + if (val === null || val === undefined) { + return; + } + 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 getSuffix(value: string | [string, any]): string { + return typeof value === "string" ? value : value[0]; +} + +const limit = pLimit(5); +async function update() { + // await new Promise(res => setTimeout(res, 5)); + console.log("update"); + await Search.Instance.clear(); + const cursor = await Database.Instance.query({}); + console.log("Cleared"); + const updates: any[] = []; + let numDocs = 0; + function updateDoc(doc: any) { + numDocs++; + if ((numDocs % 50) === 0) { + console.log("updateDoc " + numDocs); + } + console.log("doc " + numDocs); + if (doc.__type !== "Doc") { + return; + } + const fields = doc.fields; + if (!fields) { + return; + } + const update: any = { id: doc._id }; + let dynfield = false; + for (const key in fields) { + const value = fields[key]; + const term = ToSearchTerm(value); + if (term !== undefined) { + let { suffix, value } = term; + update[key + suffix] = value; + dynfield = true; + } + } + if (dynfield) { + updates.push(update); + console.log(updates.length); + } + } + await cursor.forEach(updateDoc); + await Promise.all(updates.map(update => { + return limit(() => Search.Instance.updateDocument(update)); + })); + cursor.close(); +} + +update(); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 2e2dafc6d805e54e4119e28943a3800fe08c0ca9 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 17:33:59 -0400 Subject: Disabled images in search --- src/server/index.ts | 2 +- src/server/updateSearch.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index 574241f62..5a534afae 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -366,7 +366,7 @@ const suffixMap: { [type: string]: (string | [string, string | ((json: any) => a "number": "_n", "string": "_t", // "boolean": "_b", - "image": ["_t", "url"], + // "image": ["_t", "url"], "video": ["_t", "url"], "pdf": ["_t", "url"], "audio": ["_t", "url"], diff --git a/src/server/updateSearch.ts b/src/server/updateSearch.ts index da33e3747..de1fd25e1 100644 --- a/src/server/updateSearch.ts +++ b/src/server/updateSearch.ts @@ -7,7 +7,7 @@ const suffixMap: { [type: string]: (string | [string, string | ((json: any) => a "number": "_n", "string": "_t", // "boolean": "_b", - "image": ["_t", "url"], + // "image": ["_t", "url"], "video": ["_t", "url"], "pdf": ["_t", "url"], "audio": ["_t", "url"], -- cgit v1.2.3-70-g09d2 From b3f1e5f60ee4a00522d3e4b0b03495685bde006c Mon Sep 17 00:00:00 2001 From: Abdullah Ahmed Date: Tue, 21 May 2019 16:31:45 -0400 Subject: testing --- src/server/index.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'src/server') diff --git a/src/server/index.ts b/src/server/index.ts index af99b116a..83c0bc222 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -310,6 +310,7 @@ function setField(socket: Socket, newValue: Transferable) { if (newValue.type === Types.Text) { Search.Instance.updateDocument({ id: newValue.id, data: (newValue as any).data }); console.log("set field"); + console.log("checking in"); } } -- cgit v1.2.3-70-g09d2 From f196645935814b7f2d3faef0da7fd6c5d46f14f0 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 18:04:16 -0400 Subject: various fixes --- src/client/util/SearchUtil.ts | 3 +- src/client/views/MainOverlayTextBox.tsx | 2 +- .../views/collections/CollectionTreeView.scss | 4 +- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 3 +- .../authentication/models/current_user_utils.ts | 46 +++++++++++----------- 6 files changed, 32 insertions(+), 28 deletions(-) (limited to 'src/server') diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index e8eb70837..28ec8ca14 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -20,6 +20,7 @@ export namespace SearchUtil { export async function GetAliasesOfDocument(doc: Doc): Promise { const proto = await Doc.GetT(doc, "proto", Doc, true); const protoId = (proto || doc)[Id]; - return Search(`{!join from=id to=proto_i}id:${protoId}`, true); + return Search(`proto_i:"${protoId}"`, true); + // return Search(`{!join from=id to=proto_i}id:${protoId}`, true); } } \ No newline at end of file diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 91f626737..9be408049 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -90,7 +90,7 @@ export class MainOverlayTextBox extends React.Component style={{ width: `${textRect.width * s}px`, height: `${textRect.height * s}px` }}> + ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={emptyFunction} />
; } diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 5f82137c6..2f0329fc4 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -46,7 +46,9 @@ .docContainer:hover { .treeViewItem-openRight { - display: inline; + display: inline-block; + // display: inline; + transform: translate(0px, -3px); //TODO Fix this } } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 092ccb9b0..d3d765eed 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -35,7 +35,7 @@ export interface FieldViewProps { isTopMost: boolean; selectOnLoad: boolean; addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean; - addDocTab: (document: Doc, where: string) => boolean; + addDocTab: (document: Doc, where: string) => void; removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 2363553df..228d07018 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,7 +1,7 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { emptyFunction, returnFalse, returnZero } from '../../../Utils'; +import { emptyFunction, returnFalse, returnZero, returnTrue } from '../../../Utils'; import { CompileScript } from "../../util/Scripting"; import { Transform } from '../../util/Transform'; import { EditableView } from "../EditableView"; @@ -38,6 +38,7 @@ export class KeyValuePair extends React.Component { focus: emptyFunction, PanelWidth: returnZero, PanelHeight: returnZero, + addDocTab: emptyFunction }; let contents = ; let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index aef2d3f4a..b947f5e01 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -83,29 +83,29 @@ export class CurrentUserUtils { @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! })); - }); - } + // 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; } -- cgit v1.2.3-70-g09d2 From ab001ffd9749814c3f0b0f30e9f86f65e2f8ac0c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 20:49:49 -0400 Subject: "Rebased" Stanley's image upload changes --- src/client/documents/Documents.ts | 3 ++ src/client/views/Main.scss | 15 ++++++ src/client/views/MainView.tsx | 33 ++++++++++--- .../views/collections/CollectionBaseView.tsx | 1 + .../views/collections/CollectionStackingView.scss | 44 ++++++++++++++++++ .../views/collections/CollectionStackingView.tsx | 54 ++++++++++++++++++++++ src/client/views/collections/CollectionView.tsx | 3 ++ src/mobile/ImageUpload.scss | 21 ++++++++- src/mobile/ImageUpload.tsx | 1 + .../authentication/models/current_user_utils.ts | 2 +- 10 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 src/client/views/collections/CollectionStackingView.scss create mode 100644 src/client/views/collections/CollectionStackingView.tsx (limited to 'src/server') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 3d65826a9..b17544229 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -292,6 +292,9 @@ export namespace Docs { export function TreeDocument(documents: Array, options: DocumentOptions) { return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); } + export function StackingDocument(documents: Array, options: DocumentOptions) { + return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Stacking }); + } export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { return CreateInstance(collProto, new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index d63b0147b..302c49c10 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -97,6 +97,21 @@ button:hover { right: 0px; } +.main-notifs-badge { + position: absolute; + top: -10px; + right: -10px; + color: white; + background: #f44b42; + font-weight: 300; + border-radius: 100%; + width: 25px; + height: 25px; + text-align: center; + padding-top: 4px; + font-size: 12px; +} + //toolbar stuff #toolbar { position: absolute; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index af224747d..1d491d11f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; +import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faTree, faUndoAlt, faBell } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; @@ -25,7 +25,7 @@ import { DocumentView } from './nodes/DocumentView'; import { PreviewCursor } from './PreviewCursor'; import { SearchBox } from './SearchBox'; import { SelectionManager } from '../util/SelectionManager'; -import { FieldResult, Field, Doc, Opt } from '../../new_fields/Doc'; +import { FieldResult, Field, Doc, Opt, DocListCast } from '../../new_fields/Doc'; import { Cast, FieldValue, StrCast } from '../../new_fields/Types'; import { DocServer } from '../DocServer'; import { listSpec } from '../../new_fields/Schema'; @@ -137,12 +137,14 @@ export class MainView 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"], [], { title: "New Mobile Uploads" }); - mainDoc.optionalRightCollection = pendingDocument; + // let pendingDocument = Docs.StackingDocument([], { title: "New Mobile Uploads" }); + // mainDoc.optionalRightCollection = pendingDocument; }, 0); } } + @observable _notifsCol: Opt; + @action openWorkspace = async (doc: Doc, fromHistory = false) => { CurrentUserUtils.MainDocId = doc[Id]; @@ -153,12 +155,19 @@ export class MainView extends React.Component { setTimeout(async () => { if (col) { const l = Cast(col.data, listSpec(Doc)); - if (l && l.length > 0) { - CollectionDockingView.Instance.AddRightSplit(col); + if (l) { + runInAction(() => this._notifsCol = col); } } }, 100); } + + openNotifsCol = () => { + if (this._notifsCol) { + CollectionDockingView.Instance.AddRightSplit(this._notifsCol); + } + } + @action onResize = (r: any) => { this.pwidth = r.offset.width; @@ -254,11 +263,23 @@ export class MainView extends React.Component { /* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */ @computed get miscButtons() { + const length = this._notifsCol ? DocListCast(this._notifsCol.data).length : 0; + const notifsRef = React.createRef(); + const dragNotifs = action(() => this._notifsCol!); let logoutRef = React.createRef(); return [ ,
+
+ +
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 From e1b7feda380f540e677e69e306d91d6b57ce03e7 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 7 Jun 2019 19:42:43 -0400 Subject: tree view reordering. --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 16 +++-- .../views/collections/CollectionDockingView.tsx | 5 +- .../views/collections/CollectionStackingView.tsx | 1 - src/client/views/collections/CollectionSubView.tsx | 24 ++----- .../views/collections/CollectionTreeView.scss | 79 ++++++++++++---------- src/new_fields/Doc.ts | 6 +- .../authentication/models/current_user_utils.ts | 1 + 8 files changed, 70 insertions(+), 64 deletions(-) (limited to 'src/server') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ab61b915c..5f2d729cf 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -30,7 +30,7 @@ import { Cast, NumCast } from "../../new_fields/Types"; import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; -import { StrokeData, InkField } from "../../new_fields/InkField"; +import { InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 1e84a0db0..32476b785 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -6,7 +6,7 @@ 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 | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { +export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { let onRowMove = async (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -16,6 +16,8 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () var dragData = new DragManager.DocumentDragData([await docFunc()]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; + dragData.options = options; + dragData.dontHideOnDrop = dontHideOnDrop; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); }; let onRowUp = (): void => { @@ -185,6 +187,7 @@ export namespace DragManager { export let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { + eles = eles.filter(e => e); if (!dragDiv) { dragDiv = document.createElement("div"); dragDiv.className = "dragManager-dragDiv"; @@ -241,6 +244,13 @@ export namespace DragManager { // pdfBox.replaceChild(img, pdfBox.children[0]) // } // } + let set = dragElement.getElementsByTagName('*'); + for (let i = 0; i < set.length; i++) + if (set[i].hasAttribute("style")) { + let s = set[i]; + (s as any).style.pointerEvents = "none"; + } + dragDiv.appendChild(dragElement); return dragElement; @@ -259,8 +269,6 @@ export namespace DragManager { let lastX = downX; let lastY = downY; const moveHandler = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined; } @@ -309,7 +317,7 @@ export namespace DragManager { } function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { - let removed = dragEles.map(dragEle => { + let removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { // let parent = dragEle.parentElement; // if (parent) parent.removeChild(dragEle); let ret = [dragEle, dragEle.style.width, dragEle.style.height]; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 8f6c9b1fc..51e29cb54 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -23,6 +23,7 @@ import "./CollectionDockingView.scss"; import { SubCollectionViewProps } from "./CollectionSubView"; import { ParentDocSelector } from './ParentDocumentSelector'; import React = require("react"); +import { MainView } from '../MainView'; @observer export class CollectionDockingView extends React.Component { @@ -457,7 +458,9 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } addDocTab = (doc: Doc, location: string) => { - if (location === "onRight") { + if (doc.dockingConfig) { + MainView.Instance.openWorkspace(doc); + } else if (location === "onRight") { CollectionDockingView.Instance.AddRightSplit(doc); } else { CollectionDockingView.Instance.AddTab(this._stack, doc); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index b8eb4ac84..0a119a3b4 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -109,7 +109,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @computed get children() { - trace(); return this.childDocs.filter(d => !d.isMinimized).map((d, i) => { let dref = React.createRef(); let dxf = () => this.getDocTransform(d, dref.current!); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 06d77fec5..762955a08 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -18,6 +18,7 @@ import { CollectionVideoView } from "./CollectionVideoView"; import { CollectionView } from "./CollectionView"; import React = require("react"); import { FormattedTextBox } from "../nodes/FormattedTextBox"; +import { Id } from "../../../new_fields/FieldSymbols"; export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; @@ -81,28 +82,15 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { @action protected drop(e: Event, de: DragManager.DropEvent): boolean { if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.dropAction || de.data.userDropAction) { - ["width", "height", "curPage"].map(key => - de.data.draggedDocuments.map((draggedDocument: Doc, i: number) => - PromiseValue(Cast(draggedDocument[key], "number")).then(f => f && (de.data.droppedDocuments[i][key] = f)))); - } let added = false; if (de.data.dropAction || de.data.userDropAction) { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); + added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } else if (de.data.moveDocument) { - const move = de.data.moveDocument; - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = move(d, this.props.Document, this.props.addDocument); - return moved || added; - }, false); + let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments; + added = movedDocs.reduce((added: boolean, d) => + de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); } else { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); + added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } e.stopPropagation(); return added; diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 458030b28..2dc4b2e80 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -19,10 +19,6 @@ padding-left: 20px; } - li { - margin: 5px 0; - } - .no-indent { padding-left: 0; @@ -34,30 +30,9 @@ width: 15px; display: block; color: $intermediate-color; - margin-top: 3px; + margin-top: 8px; transform: scale(1.3, 1.3); } - - .docContainer { - margin-left: 10px; - display: block; - // width:100%;//width: max-content; - } - - .docContainer:hover { - .treeViewItem-openRight { - display: inline-block; - height:13px; - // display: inline; - svg { - display:block; - padding:0px; - margin: 0px; - } - } - } - - .editableView-container { font-weight: bold; } @@ -70,10 +45,6 @@ display: inline; } - .treeViewItem-openRight { - margin-left: 5px; - display: none; - } .docContainer:hover { .delete-button { @@ -88,13 +59,51 @@ font-size: 24px; } - .collection-child { - margin-top: 10px; - margin-bottom: 10px; - } - .collectionTreeView-keyHeader { font-style: italic; font-size: 8pt; } +} + +.docContainer { + margin-left: 10px; + display: block; + // width:100%;//width: max-content; + + .treeViewItem-openRight { + margin-left: 5px; + display: none; + } +} +#docContainer-data { + margin-top: 5px; +} + +.docContainer:hover { + .treeViewItem-openRight { + display: inline-block; + height:13px; + // display: inline; + svg { + display:block; + padding:0px; + margin: 0px; + } + } +} + +.treeViewItem-header { + border: transparent 1px solid; +} +.treeViewItem-header-above { + border: transparent 1px solid; + border-top: black 1px solid; +} +.treeViewItem-header-below { + border: transparent 1px solid; + border-bottom: black 1px solid; +} +.treeViewItem-header-inside { + border: transparent 1px solid; + border: black 1px solid; } \ No newline at end of file diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 7f7263cf1..7e02a5bc5 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -211,13 +211,11 @@ export namespace Doc { return Array.from(results); } - export function MakeAlias(doc: Doc) { - const alias = new Doc; if (!GetT(doc, "isPrototype", "boolean", true)) { - alias.proto = doc.proto; + return Doc.MakeCopy(doc); } - return alias; + return new Doc; } export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e5b7a025b..816c5f269 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -29,6 +29,7 @@ export class CurrentUserUtils { private static createUserDocument(id: string): Doc { let doc = new Doc(id, true); doc.viewType = CollectionViewType.Tree; + doc.dropAction = "alias"; doc.layout = CollectionView.LayoutString(); doc.title = this.email; doc.data = new List(); -- cgit v1.2.3-70-g09d2