From a13c0bacfb58970b3316c75b18582ad24cf8bee4 Mon Sep 17 00:00:00 2001 From: ab Date: Sat, 9 Mar 2019 15:58:58 -0500 Subject: merge --- src/client/views/ContextMenu.scss | 4 ++-- src/client/views/ContextMenu.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 2ac5d3b52..47a4e38ab 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -7,8 +7,8 @@ } .contextMenu-item { - width: 10vw; - height: 4vh; + width: 10vw; //10vw + height: auto; //4vh background: #DDDDDD; display: flex; justify-content: center; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 2359c673d..d4be0dea8 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem"; import { observable, action } from "mobx"; -import { observer } from "mobx-react"; +import { observer } from "mobx-react" import "./ContextMenu.scss" @observer -- cgit v1.2.3-70-g09d2 From d2745992e5a4df1c92c8cb2edfb9829b7a1cc420 Mon Sep 17 00:00:00 2001 From: ab Date: Sat, 9 Mar 2019 16:07:24 -0500 Subject: idk --- src/client/views/ContextMenu.scss | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 89351c76c..a83572279 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -7,15 +7,9 @@ } .contextMenu-item { -<<<<<<< HEAD width: 10vw; //10vw height: auto; //4vh background: #DDDDDD; -======= - width: auto; - height: auto; - background: #F0F8FF; ->>>>>>> 09928503be98d605052fba65dcd2f91f9b056f23 display: flex; justify-content: left; align-items: center; -- cgit v1.2.3-70-g09d2 From 1f038048612e01d0ada6deb9ff2a056cb8d13702 Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Mon, 11 Mar 2019 17:32:49 -0400 Subject: some changes --- src/client/views/ContextMenu.scss | 13 ++- src/client/views/ContextMenu.tsx | 5 +- src/client/views/ContextMenuItem.tsx | 42 +++++-- src/client/views/nodes/FormattedTextBox.tsx | 23 ++-- src/server/index.ts | 172 ++++++++++++++++++++-------- 5 files changed, 180 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index ea40c8e99..82e736520 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -6,9 +6,18 @@ flex-direction: column; } +.subMenu-cont { + position: relative; + display: flex; + z-index: 1000; + box-shadow: #AAAAAA .2vw .2vw .4vw; + flex-direction: column; + left: 100%; //should make this appear 100% to the right of the parent element (the original context menu) +} + .contextMenu-item { - width: auto; - height: auto; + width: 10vw; //auto + height: 2vh; //auto background: #F0F8FF; display: flex; justify-content: left; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index fcb934860..8a8403c62 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -9,6 +9,7 @@ export class ContextMenu extends React.Component { static Instance: ContextMenu @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }]; + //need to add a subitems component? @observable private _pageX: number = 0; @observable private _pageY: number = 0; @observable private _display: string = "none"; @@ -80,4 +81,6 @@ export class ContextMenu extends React.Component { onChange = (e: React.ChangeEvent) => { this._searchString = e.target.value; } -} \ No newline at end of file +} + +// \ No newline at end of file diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 723606dcf..3319b62db 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,26 +1,46 @@ import React = require("react"); -import { ContextMenu } from "./ContextMenu"; +import { observable, action } from "mobx"; -export interface ContextMenuProps { +export interface OriginalMenuProps { description: string; event: (e: React.MouseEvent) => void; } export interface SubmenuProps { description: string; - subitems: ContextMenuProps[]; + subitems: OriginalMenuProps[]; } -export interface ContextMenuItemProps { - type: ContextMenuProps | SubmenuProps -} +export type ContextMenuProps = OriginalMenuProps | SubmenuProps; export class ContextMenuItem extends React.Component { + @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }]; + @observable private _pageX: number = 0; + @observable private _pageY: number = 0; + @observable private _display: string = "none"; + @observable private overItem = false; + render() { - return ( -
-
{this.props.description}
-
- ) + if ("event" in this.props) { + return ( +
+
{this.props.description}
+
) + } + else { + let submenu = null; + if (this.overItem) { + submenu = (
+ {this._items.map(prop => { + return + })} +
) + } + return ( +
this.overItem = true)} onMouseLeave={action(() => this.overItem = false)}> +
{this.props.description}
+ {submenu} +
) + } } } \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 8b3deeb8b..baedf0852 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -119,17 +119,18 @@ export class FormattedTextBox extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); - // ContextMenu.Instance.addItem({ - // description: "Submenu", - // items: [ - // { - // description: "item 1", event: - // }, - // { - // description: "item 2", event: - // } - // ] - // }) + ContextMenu.Instance.addItem({ + description: "Submenu", subitems: + [{ description: "Sub 1", event: this.textCapability }] + // [{ description: "Sub 2", event: this.textCapability }] + // { + // description: "item 1", event: + // }, + // { + // description: "item 2", event: + // } + // ] + }) // e.stopPropagation() } diff --git a/src/server/index.ts b/src/server/index.ts index 84acb72cb..7850fd1d8 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,23 +1,75 @@ -import * as express from 'express' -const app = express() -import * as webpack from 'webpack' +import * as express from 'express'; +const app = express(); +import * as webpack from 'webpack'; import * as wdm from 'webpack-dev-middleware'; import * as whm from 'webpack-hot-middleware'; -import * as path from 'path' +import * as path from 'path'; import * as passport from 'passport'; -import { MessageStore, Message, SetFieldArgs, GetFieldArgs, Transferable } from "./Message"; -import { Client } from './Client'; -import { Socket } from 'socket.io'; -import { Utils } from '../Utils'; -import { ObservableMap } from 'mobx'; -import { FieldId, Field } from '../fields/Field'; -import { Database } from './database'; -import { ServerUtils } from './ServerUtil'; -import { ObjectID } from 'mongodb'; -import { Document } from '../fields/Document'; -import * as io from 'socket.io' +import { + MessageStore, + Message, + SetFieldArgs, + GetFieldArgs, + Transferable +} + + from "./Message"; +import { + Client +} + + from './Client'; +import { + Socket +} + + from 'socket.io'; +import { + Utils +} + + from '../Utils'; +import { + ObservableMap +} + + from 'mobx'; +import { + FieldId, + Field +} + + from '../fields/Field'; +import { + Database +} + + from './database'; +import { + ServerUtils +} + + from './ServerUtil'; +import { + ObjectID +} + + from 'mongodb'; +import { + Document +} + + from '../fields/Document'; +import * as io from 'socket.io'; import * as passportConfig from './authentication/config/passport'; -import { getLogin, postLogin, getSignup, postSignup } from './authentication/controllers/user'; +import { + getLogin, + postLogin, + getSignup, + postSignup +} + + from './authentication/controllers/user'; const config = require('../../webpack.config'); const compiler = webpack(config); const port = 1050; // default port to listen @@ -30,17 +82,20 @@ import c = require("crypto"); const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); const bluebird = require('bluebird'); -import { performance } from 'perf_hooks' -import * as fs from 'fs'; -import * as request from 'request' +import { + performance +} + from 'perf_hooks'; +import * as fs from 'fs'; +import * as request from 'request'; const download = (url: string, dest: fs.PathLike) => { request.get(url).pipe(fs.createWriteStream(dest)); } const mongoUrl = 'mongodb://localhost:27017/Dash'; // mongoose.Promise = bluebird; -mongoose.connect(mongoUrl)//.then( +mongoose.connect(mongoUrl) //.then( // () => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ }, // ).catch((err: any) => { // console.log("MongoDB connection error. Please make sure MongoDB is running. " + err); @@ -48,77 +103,88 @@ mongoose.connect(mongoUrl)//.then( // }); mongoose.connection.on('connected', function () { console.log("connected"); -}) +} +); app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.urlencoded({ + extended: true +} + +)); app.use(expressValidator()); app.use(expressFlash()); app.use(require('express-session')({ - secret: `${c.randomBytes(64)}`, - resave: true, - saveUninitialized: true, - store: new MongoStore({ + secret: `$ { + c.randomBytes(64) + } + `, resave: true, saveUninitialized: true, store: new MongoStore({ url: 'mongodb://localhost:27017/Dash' - }) -})); + } + ) +} + +)); app.use(passport.initialize()); app.use(passport.session()); app.use((req, res, next) => { res.locals.user = req.user; next(); -}); +} +); app.get("/signup", getSignup); app.post("/signup", postSignup); app.get("/login", getLogin); app.post("/login", postLogin); - -let FieldStore: ObservableMap = new ObservableMap(); - +let FieldStore: ObservableMap = new ObservableMap(); // define a route handler for the default home page app.get("/", (req, res) => { res.sendFile(path.join(__dirname, '../../deploy/index.html')); -}); +} +); app.get("/hello", (req, res) => { res.send("

Hello

"); -}) +} +); app.get("/delete", (req, res) => { deleteAll(); res.redirect("/"); -}); +} +); app.use(wdm(compiler, { publicPath: config.output.publicPath -})) - -app.use(whm(compiler)) +} -// start the Express server +)) +app.use(whm(compiler)) // start the Express server app.listen(port, () => { - console.log(`server started at http://localhost:${port}`); -}) + console.log(`server started at http: //localhost:${port}`); +} +) const server = io(); interface Map { [key: string]: Client; } + let clients: Map = {} server.on("connection", function (socket: Socket) { console.log("a user has connected") - Utils.Emit(socket, MessageStore.Foo, "handshooken") - Utils.AddServerHandler(socket, MessageStore.Bar, barReceived) Utils.AddServerHandler(socket, MessageStore.SetField, (args) => setField(socket, args)) Utils.AddServerHandlerCallback(socket, MessageStore.GetField, getField) Utils.AddServerHandlerCallback(socket, MessageStore.GetFields, getFields) Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteAll) -}) +} +) function deleteAll() { Database.Instance.deleteAll(); } @@ -127,9 +193,7 @@ function barReceived(guid: String) { clients[guid.toString()] = new Client(guid.toString()); } -function addDocument(document: Document) { - -} +function addDocument(document: Document) { } function getField([id, callback]: [string, (result: any) => void]) { Database.Instance.getDocument(id, (result: any) => { @@ -139,7 +203,8 @@ function getField([id, callback]: [string, (result: any) => void]) { else { callback(undefined) } - }) + } + ) } function getFields([ids, callback]: [string[], (result: any) => void]) { @@ -147,11 +212,18 @@ function getFields([ids, callback]: [string[], (result: any) => void]) { } function setField(socket: Socket, newValue: Transferable) { - let val = { ...newValue }; + let val = { + ...newValue + } + ; delete val._id; Database.Instance.update(newValue._id, val) socket.broadcast.emit(MessageStore.SetField.Message, newValue) } server.listen(serverPort); -console.log(`listening on port ${serverPort}`); \ No newline at end of file +console.log(`listening on port $ { + serverPort +} + +`); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9351426356e06a5c6a7777b1edd118273e29072e Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Tue, 12 Mar 2019 17:45:57 -0400 Subject: working submenu; dimensions use vw, vh --- package-lock.json | 236 +++++++++++++++------------- src/client/views/ContextMenu.scss | 1 - src/client/views/ContextMenu.tsx | 6 +- src/client/views/nodes/FormattedTextBox.tsx | 21 +-- 4 files changed, 140 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 75c02628e..8c9bf9c0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1138,7 +1138,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -1655,7 +1655,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -1692,7 +1692,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -1731,7 +1731,7 @@ }, "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -1852,7 +1852,7 @@ }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "requires": { "camelcase": "^2.0.0", @@ -2282,7 +2282,7 @@ }, "content-disposition": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" }, "content-type": { @@ -2401,7 +2401,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -2414,7 +2414,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -2540,7 +2540,7 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { @@ -2763,7 +2763,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -3306,7 +3306,7 @@ "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "statuses": { @@ -3500,7 +3500,7 @@ }, "finalhandler": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", @@ -3574,14 +3574,18 @@ }, "dependencies": { "readable-stream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", - "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } } } @@ -3703,24 +3707,24 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": false, "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "resolved": false, "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "optional": true, "requires": { @@ -3730,12 +3734,12 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "resolved": false, "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "^1.0.0", @@ -3744,34 +3748,34 @@ }, "chownr": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "resolved": false, "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "resolved": false, "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "resolved": false, "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "optional": true, "requires": { @@ -3780,25 +3784,25 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": false, "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "resolved": false, "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "resolved": false, "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "resolved": false, "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "optional": true, "requires": { @@ -3807,13 +3811,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": false, "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "optional": true, "requires": { @@ -3829,7 +3833,7 @@ }, "glob": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "resolved": false, "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "optional": true, "requires": { @@ -3843,13 +3847,13 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "resolved": false, "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "resolved": false, "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "optional": true, "requires": { @@ -3858,7 +3862,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "resolved": false, "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "optional": true, "requires": { @@ -3867,7 +3871,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "optional": true, "requires": { @@ -3877,18 +3881,18 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "resolved": false, "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { "number-is-nan": "^1.0.0" @@ -3896,13 +3900,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": false, "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "^1.1.7" @@ -3910,12 +3914,12 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "resolved": false, "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "requires": { "safe-buffer": "^5.1.2", @@ -3924,7 +3928,7 @@ }, "minizlib": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "resolved": false, "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "optional": true, "requires": { @@ -3933,7 +3937,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -3941,13 +3945,13 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "resolved": false, "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "optional": true }, "needle": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", + "resolved": false, "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", "optional": true, "requires": { @@ -3958,7 +3962,7 @@ }, "node-pre-gyp": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", + "resolved": false, "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", "optional": true, "requires": { @@ -3976,7 +3980,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "optional": true, "requires": { @@ -3986,13 +3990,13 @@ }, "npm-bundled": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", + "resolved": false, "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", "optional": true }, "npm-packlist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.2.0.tgz", + "resolved": false, "integrity": "sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ==", "optional": true, "requires": { @@ -4002,7 +4006,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "optional": true, "requires": { @@ -4014,18 +4018,18 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "resolved": false, "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" @@ -4033,19 +4037,19 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "resolved": false, "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "optional": true, "requires": { @@ -4055,19 +4059,19 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": false, "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "resolved": false, "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "optional": true }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "resolved": false, "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "optional": true, "requires": { @@ -4079,7 +4083,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "optional": true } @@ -4087,7 +4091,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": false, "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "optional": true, "requires": { @@ -4102,7 +4106,7 @@ }, "rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "resolved": false, "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "optional": true, "requires": { @@ -4111,42 +4115,42 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": false, "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "resolved": false, "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "optional": true }, "semver": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "resolved": false, "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -4156,7 +4160,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": false, "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "optional": true, "requires": { @@ -4165,7 +4169,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -4173,13 +4177,13 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": false, "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "optional": true }, "tar": { "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "resolved": false, "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "optional": true, "requires": { @@ -4194,13 +4198,13 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": false, "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "resolved": false, "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "optional": true, "requires": { @@ -4209,12 +4213,12 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "yallist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "resolved": false, "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" } } @@ -4640,7 +4644,7 @@ }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { "depd": "~1.1.2", @@ -4943,7 +4947,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { "kind-of": "^3.0.2" @@ -4987,7 +4991,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { "kind-of": "^3.0.2" @@ -5466,7 +5470,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { "graceful-fs": "^4.1.2", @@ -5767,7 +5771,7 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "mem": { @@ -5799,7 +5803,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "requires": { "camelcase-keys": "^2.0.0", @@ -5965,7 +5969,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" @@ -6243,7 +6247,7 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, @@ -6302,7 +6306,7 @@ }, "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" }, "tar": { @@ -9685,12 +9689,12 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { @@ -9856,7 +9860,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -9875,7 +9879,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { @@ -10888,7 +10892,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -11149,7 +11153,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { "ret": "~0.1.10" @@ -11371,7 +11375,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -11929,11 +11933,31 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -11941,7 +11965,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -11957,7 +11981,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-indent": { @@ -12393,7 +12417,7 @@ }, "tty-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, @@ -12798,7 +12822,7 @@ }, "vm-browserify": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", "dev": true, "requires": { @@ -13587,7 +13611,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 82e736520..bfd643caf 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -12,7 +12,6 @@ z-index: 1000; box-shadow: #AAAAAA .2vw .2vw .4vw; flex-direction: column; - left: 100%; //should make this appear 100% to the right of the parent element (the original context menu) } .contextMenu-item { diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 8a8403c62..ce9023352 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -9,7 +9,6 @@ export class ContextMenu extends React.Component { static Instance: ContextMenu @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }]; - //need to add a subitems component? @observable private _pageX: number = 0; @observable private _pageY: number = 0; @observable private _display: string = "none"; @@ -37,6 +36,7 @@ export class ContextMenu extends React.Component { if (this._items.indexOf(item) === -1) { this._items.push(item); } + console.log(`After adding, there are ${this._items.length} items`); } getItems() { @@ -81,6 +81,4 @@ export class ContextMenu extends React.Component { onChange = (e: React.ChangeEvent) => { this._searchString = e.target.value; } -} - -// \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 411b43cd5..dfc7e9096 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -122,22 +122,17 @@ export class FormattedTextBox extends React.Component { textCapability = (e: React.MouseEvent): void => { } + @action specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); ContextMenu.Instance.addItem({ - description: "Submenu", subitems: - [{ description: "Sub 1", event: this.textCapability }] - // [{ description: "Sub 2", event: this.textCapability }] - // { - // description: "item 1", event: - // }, - // { - // description: "item 2", event: - // } - // ] - }) - // e.stopPropagation() - + description: "Submenu", subitems: [ + { description: "Subitem 1", event: this.textCapability }, + { description: "Subitem 2", event: this.textCapability }, + { description: "Subitem 3", event: this.textCapability }, + { description: "Submenu", subitems: [{ description: "Inner Subitem", event: this.textCapability }] } + ] + }); } onPointerWheel = (e: React.WheelEvent): void => { -- cgit v1.2.3-70-g09d2 From 02f0311a868decd92af53d1ffbb6f03bdaa912db Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Sat, 16 Mar 2019 16:53:46 -0400 Subject: submenus overlapping --- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenu.tsx | 11 ++++++++++- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index bcf856d48..265cdefca 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -16,7 +16,7 @@ .contextMenu-item { width: 10vw; //10vw - height: auto; //4vh + height: 2vh; background: #DDDDDD; display: flex; justify-content: left; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 31c165373..73bad477b 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -3,6 +3,11 @@ import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem"; import { observable, action } from "mobx"; import { observer } from "mobx-react" import "./ContextMenu.scss" +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faSearch } from '@fortawesome/free-solid-svg-icons'; + +library.add(faSearch); @observer export class ContextMenu extends React.Component { @@ -67,7 +72,11 @@ export class ContextMenu extends React.Component { render() { return (
- +
+ + {/* */} + +
{this._items.filter(prop => { return prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1; }).map(prop => { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 67bbc3082..6bd370152 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -38,7 +38,7 @@ export class ContextMenuItem extends React.Component { else { let submenu = null; if (this.overItem) { - submenu = (
+ submenu = (
{this._items.map(prop => { return })} diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index dfc7e9096..e402392a7 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -126,7 +126,7 @@ export class FormattedTextBox extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); ContextMenu.Instance.addItem({ - description: "Submenu", subitems: [ + description: "Sub", subitems: [ { description: "Subitem 1", event: this.textCapability }, { description: "Subitem 2", event: this.textCapability }, { description: "Subitem 3", event: this.textCapability }, -- cgit v1.2.3-70-g09d2 From e1574e421be8a7b7733cdb4a3867cb613df05d2b Mon Sep 17 00:00:00 2001 From: _stanleyyip <33562077+yipstanley@users.noreply.github.com> Date: Sat, 16 Mar 2019 17:26:38 -0400 Subject: fixed --- package-lock.json | 16 ++++++++++------ src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenuItem.tsx | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 8c9bf9c0a..8253c8526 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3735,12 +3735,14 @@ "balanced-match": { "version": "1.0.0", "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true }, "brace-expansion": { "version": "1.1.11", "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3760,7 +3762,8 @@ "concat-map": { "version": "0.0.1", "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true }, "console-control-strings": { "version": "1.1.0", @@ -3908,6 +3911,7 @@ "version": "3.0.4", "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4256,7 +4260,7 @@ "dependencies": { "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", @@ -5490,7 +5494,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } @@ -6385,7 +6389,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "requires": { "ansi-styles": "^2.2.1", @@ -13620,7 +13624,7 @@ "dependencies": { "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { "code-point-at": "^1.0.0", diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 265cdefca..43e5033fd 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -7,7 +7,7 @@ } .subMenu-cont { - position: relative; + position: absolute; display: flex; z-index: 1000; box-shadow: #AAAAAA .2vw .2vw .4vw; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 6bd370152..6b17c5c19 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -38,7 +38,7 @@ export class ContextMenuItem extends React.Component { else { let submenu = null; if (this.overItem) { - submenu = (
+ submenu = (
{this._items.map(prop => { return })} -- cgit v1.2.3-70-g09d2 From 2411f3700c19cea1b2ac52e32ecd64c6e7343284 Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Sat, 16 Mar 2019 17:34:14 -0400 Subject: commit to pull --- package-lock.json | 6 ++++++ package.json | 1 + src/client/views/ContextMenu.tsx | 6 +++--- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 8c9bf9c0a..cc9f55338 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,6 +100,12 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.15.tgz", "integrity": "sha512-ATBRyKJw1d2ko+0DWN9+BXau0EK3I/Q6pPzPv3LhJD7r052YFAkAdfb1Bd7ZqhBsJrdse/S7jKxWUOZ61qBD4g==" }, + "@fortawesome/fontawesome-free": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.7.2.tgz", + "integrity": "sha512-Ha4HshKdCVKgu4TVCtG8XyPPYdzTzNW4/fvPnn+LT7AosRABryhlRv4cc4+o84dgpvVJN9reN7jo/c+nYujFug==", + "dev": true + }, "@fortawesome/fontawesome-free-solid": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free-solid/-/fontawesome-free-solid-5.0.13.tgz", diff --git a/package.json b/package.json index 3bbaf72ad..6509fa449 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "tsc": "tsc" }, "devDependencies": { + "@fortawesome/fontawesome-free": "^5.7.2", "@types/chai": "^4.1.7", "@types/mocha": "^5.2.6", "@types/react-dom": "^16.8.2", diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 73bad477b..2396ce762 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -73,9 +73,9 @@ export class ContextMenu extends React.Component { return (
- - {/* */} - + {/* */} + +
{this._items.filter(prop => { return prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1; -- cgit v1.2.3-70-g09d2 From 7db0071a1f1232112597176b0b077e6b7e37679d Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Mon, 18 Mar 2019 19:00:13 -0400 Subject: Added icons --- src/client/views/ContextMenu.scss | 12 +++++--- src/client/views/ContextMenu.tsx | 14 +++++---- src/client/views/ContextMenuItem.tsx | 11 ++++++-- src/client/views/collections/CollectionPDFView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 19 ++++++++++--- src/client/views/nodes/DocumentView.tsx | 33 ++++++++++++++++------ src/client/views/nodes/FormattedTextBox.tsx | 18 +++++++----- src/client/views/nodes/ImageBox.tsx | 2 +- 8 files changed, 77 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 43e5033fd..5c40c3c43 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -15,10 +15,9 @@ } .contextMenu-item { - width: 10vw; //10vw - height: 2vh; - background: #DDDDDD; - display: flex; + width: 11vw; //10vw + height: 2.5vh; //2vh + background: #DDDDDD; // display: flex; justify-content: left; align-items: center; -webkit-touch-callout: none; @@ -46,4 +45,9 @@ font-size: 1.5vw; text-align: left; width: 8vw; + display: inline; //need this? +} + +.icon-background { + background-color: #DDDDDD; } \ No newline at end of file diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 2396ce762..39ccb55b0 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -13,7 +13,7 @@ library.add(faSearch); export class ContextMenu extends React.Component { static Instance: ContextMenu - @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault() }]; + @observable private _items: Array = [{ description: "test", event: (e: React.MouseEvent) => e.preventDefault(), icon: "smile" }]; @observable private _pageX: number = 0; @observable private _pageY: number = 0; @observable private _display: string = "none"; @@ -72,11 +72,13 @@ export class ContextMenu extends React.Component { render() { return (
-
- {/* */} - - -
+ + + + + + + {this._items.filter(prop => { return prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1; }).map(prop => { diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 6b17c5c19..80d9ff6a5 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,10 +1,13 @@ import React = require("react"); import { observable, action } from "mobx"; import { observer } from "mobx-react"; +import { library, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; export interface OriginalMenuProps { description: string; event: (e: React.MouseEvent) => void; + icon: IconProp; //maybe should be optional (icon?) } export interface SubmenuProps { @@ -17,8 +20,6 @@ export type ContextMenuProps = OriginalMenuProps | SubmenuProps; @observer export class ContextMenuItem extends React.Component { @observable private _items: Array = []; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; @observable private overItem = false; constructor(props: ContextMenuProps) { @@ -32,13 +33,17 @@ export class ContextMenuItem extends React.Component { if ("event" in this.props) { return (
+ + + +
{this.props.description}
) } else { let submenu = null; if (this.overItem) { - submenu = (
+ submenu = (
{this._items.map(prop => { return })} diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index f22c07060..bcb1cd2f7 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -41,7 +41,7 @@ export class CollectionPDFView extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { } }); + ContextMenu.Instance.addItem({ description: "PDFOptions", event: () => { }, icon: "file-pdf" }); } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 548a51bf1..b76426429 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -13,6 +13,17 @@ import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionViewProps } from "./CollectionViewBase"; import { CollectionTreeView } from "./CollectionTreeView"; import { Field, FieldId } from "../../../fields/Field"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTh } from '@fortawesome/free-solid-svg-icons'; +import { faTree } from '@fortawesome/free-solid-svg-icons'; +import { faSquare } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram } from '@fortawesome/free-solid-svg-icons'; + +library.add(faTh); +library.add(faTree); +library.add(faSquare); +library.add(faProjectDiagram); export enum CollectionViewType { Invalid, @@ -96,10 +107,10 @@ export class CollectionView extends React.Component { specificContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document.Id != "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) }) - ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) }) - ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree) }) - ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform), icon: "project-diagram" }) + ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema), icon: "th" }) + ContextMenu.Instance.addItem({ description: "Treeview", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Tree), icon: "tree" }) + ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking), icon: "square" }) } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index dc793c16d..53a3aaa18 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -27,6 +27,23 @@ import React = require("react"); import { TextField } from "../../../fields/TextField"; import { DocumentManager } from "../../util/DocumentManager"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faExpandArrowsAlt } from '@fortawesome/free-solid-svg-icons'; +import { faCompressArrowsAlt } from '@fortawesome/free-solid-svg-icons'; +import { faLayerGroup } from '@fortawesome/free-solid-svg-icons'; +import { faAlignCenter } from '@fortawesome/free-solid-svg-icons'; +import { faCaretSquareRight } from '@fortawesome/free-solid-svg-icons'; +import { faSquare } from '@fortawesome/free-solid-svg-icons'; + +library.add(faTrash); +library.add(faExpandArrowsAlt); +library.add(faCompressArrowsAlt); +library.add(faLayerGroup); +library.add(faAlignCenter); +library.add(faCaretSquareRight); +library.add(faSquare); export interface DocumentViewProps { @@ -212,14 +229,14 @@ export class DocumentView extends React.Component { fullScreenClicked = (e: React.MouseEvent): void => { CollectionDockingView.Instance.OpenFullScreen(this.props.Document); ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); + ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked, icon: "compress-arrows-alt" }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) } closeFullScreenClicked = (e: React.MouseEvent): void => { CollectionDockingView.Instance.CloseFullScreen(); ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "expand-arrows-alt" }) ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) } @@ -261,18 +278,18 @@ export class DocumentView extends React.Component { } e.preventDefault() - ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked }) - ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked }) - ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) }) - ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }) - //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) + ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "expand-arrows-alt" }) + ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked, icon: "layer-group" }) + ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document), icon: "align-center" }) + ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document), icon: "caret-square-right" }) + ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking), icon: "square" }) ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) if (!this.topMost) { // DocumentViews should stop propagation of this event e.stopPropagation(); } - ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }) + ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }) ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15) SelectionManager.SelectDoc(this, e.ctrlKey); } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e402392a7..7a8dbddcc 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -14,9 +14,13 @@ import { Plugin } from 'prosemirror-state' import { Decoration, DecorationSet } from 'prosemirror-view' import { TooltipTextMenu } from "../../util/TooltipTextMenu" import { ContextMenu } from "../../views/ContextMenu"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faEdit } from '@fortawesome/free-solid-svg-icons'; +import { faSmile } from '@fortawesome/free-solid-svg-icons'; - - +library.add(faEdit); +library.add(faSmile); // FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document // @@ -124,13 +128,13 @@ export class FormattedTextBox extends React.Component { @action specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability }); + ContextMenu.Instance.addItem({ description: "Text Capability", event: this.textCapability, icon: "edit" }); ContextMenu.Instance.addItem({ description: "Sub", subitems: [ - { description: "Subitem 1", event: this.textCapability }, - { description: "Subitem 2", event: this.textCapability }, - { description: "Subitem 3", event: this.textCapability }, - { description: "Submenu", subitems: [{ description: "Inner Subitem", event: this.textCapability }] } + { description: "Subitem 1", event: this.textCapability, icon: "smile" }, + { description: "Subitem 2", event: this.textCapability, icon: "smile" }, + { description: "Subitem 3", event: this.textCapability, icon: "smile" }, + { description: "Submenu", subitems: [{ description: "Inner Subitem", event: this.textCapability, icon: "smile" }] } ] }); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 30910fb1f..62ecea583 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -94,7 +94,7 @@ export class ImageBox extends React.Component { } specificContextMenu = (e: React.MouseEvent): void => { - ContextMenu.Instance.addItem({ description: "Image Capability", event: this.imageCapability }); + ContextMenu.Instance.addItem({ description: "Image Capability", event: this.imageCapability, icon: "smile" }); } render() { -- cgit v1.2.3-70-g09d2 From 757413b1affeb0e32dbcd0f04ec661cd908a249c Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 18 Mar 2019 19:11:50 -0400 Subject: fixed --- src/client/views/ContextMenu.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 5c40c3c43..e5d41fcb6 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -17,7 +17,8 @@ .contextMenu-item { width: 11vw; //10vw height: 2.5vh; //2vh - background: #DDDDDD; // display: flex; + background: #DDDDDD; + display: flex; justify-content: left; align-items: center; -webkit-touch-callout: none; -- cgit v1.2.3-70-g09d2 From 19fca408a19c5f7a759ff6c3bfefe27b96ec3563 Mon Sep 17 00:00:00 2001 From: Eleanor Eng Date: Tue, 19 Mar 2019 17:51:25 -0400 Subject: contextmenu --- src/client/views/ContextMenu.scss | 2 +- src/client/views/ContextMenuItem.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 1 - src/client/views/nodes/FormattedTextBox.tsx | 1 - src/client/views/nodes/ImageBox.tsx | 1 - 6 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index e5d41fcb6..8bc7708f7 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -18,7 +18,7 @@ width: 11vw; //10vw height: 2.5vh; //2vh background: #DDDDDD; - display: flex; + display: flex; //comment out to allow search icon to be inline with search text justify-content: left; align-items: center; -webkit-touch-callout: none; diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 80d9ff6a5..fac7342aa 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { observable, action } from "mobx"; import { observer } from "mobx-react"; -import { library, IconProp } from '@fortawesome/fontawesome-svg-core'; +import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; export interface OriginalMenuProps { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b76426429..d0e2162b1 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -14,7 +14,6 @@ import { CollectionViewProps } from "./CollectionViewBase"; import { CollectionTreeView } from "./CollectionTreeView"; import { Field, FieldId } from "../../../fields/Field"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTh } from '@fortawesome/free-solid-svg-icons'; import { faTree } from '@fortawesome/free-solid-svg-icons'; import { faSquare } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 53a3aaa18..907762837 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -28,7 +28,6 @@ import { TextField } from "../../../fields/TextField"; import { DocumentManager } from "../../util/DocumentManager"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { faExpandArrowsAlt } from '@fortawesome/free-solid-svg-icons'; import { faCompressArrowsAlt } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 7a8dbddcc..648037e31 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -15,7 +15,6 @@ import { Decoration, DecorationSet } from 'prosemirror-view' import { TooltipTextMenu } from "../../util/TooltipTextMenu" import { ContextMenu } from "../../views/ContextMenu"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faEdit } from '@fortawesome/free-solid-svg-icons'; import { faSmile } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 62ecea583..7532e23c8 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,4 +1,3 @@ - import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import Lightbox from 'react-image-lightbox'; -- cgit v1.2.3-70-g09d2 From 6e767972574c9cd8a2cd1e10a8fa327839ca3525 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 16 May 2019 01:17:44 -0400 Subject: changes to make maximizing stuff apply to data documents. problem with zooiming after resizing a summarized doc --- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/TemplateMenu.tsx | 2 +- src/client/views/Templates.tsx | 15 ++++++------ .../collections/collectionFreeForm/MarqueeView.tsx | 8 ++++--- .../views/nodes/CollectionFreeFormDocumentView.tsx | 28 ++++++++++------------ 5 files changed, 28 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8d85f7e2c..b2c65a31f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -263,7 +263,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> topDocView.props.Document.subBulletDocs = undefined; } else { topDocView.addTemplate(Templates.Bullet); - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document)); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); } } } @@ -285,7 +285,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> iconDoc.height = Number(MINIMIZED_ICON_SIZE); iconDoc.x = NumCast(doc.x); iconDoc.y = NumCast(doc.y) - 24; - iconDoc.maximizedDocs = new List(selected.map(s => s.props.Document)); + iconDoc.maximizedDocs = new List(selected.map(s => s.props.Document.proto!)); doc.minimizedDoc = iconDoc; selected[0].props.addDocument && selected[0].props.addDocument(iconDoc, false); return iconDoc; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 22c4edc25..cfe1b0663 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -46,7 +46,7 @@ export class TemplateMenu extends React.Component { if (template.Name == "Bullet") { let topDocView = this.props.docs[0]; topDocView.addTemplate(template); - topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document)); + topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); } else { this.props.docs.map(d => d.addTemplate(template)); } diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index ca0c04d1b..f0ee2856b 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -62,18 +62,19 @@ export namespace Templates {
` ); export const Bullet = new Template("Bullet", TemplatePosition.InnerTop, - `
{layout}
-
- -
+ `
+
{layout}
+
+ +
` ); export function ImageOverlay(width: number, height: number, field: string = "thumbnail") { return (`
-
{layout}
-
+
{layout}
+
`); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 865bae729..c063115e7 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -264,7 +264,6 @@ export class MarqueeView extends React.Component // SelectionManager.DeselectAll(); if (e.key === "s" || e.key === "r" || e.key === "p") { e.preventDefault(); - let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); let dataUrl = await htmlToImage.toPng(this._mainCont.current!, { width: bounds.width, height: bounds.height, quality: 1 }); @@ -272,12 +271,15 @@ export class MarqueeView extends React.Component summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); if (e.key === "s" || e.key === "p") { - summary.proto!.maximizeOnRight = true; + // summary.proto!.maximizeOnRight = true; newCollection.proto!.summaryDoc = summary; selected = [newCollection]; + newCollection.proto!.isMinimized = true; + this.props.addDocument(newCollection, false); } - summary.proto!.summarizedDocs = new List(selected); + summary.proto!.summarizedDocs = new List(selected.map(s => s.proto!)); //summary.proto!.isButton = true; + let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); selected.map(summarizedDoc => { let maxx = NumCast(summarizedDoc.x, undefined); let maxy = NumCast(summarizedDoc.y, undefined); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 631bf1ba8..03538ae66 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -87,7 +87,8 @@ export class CollectionFreeFormDocumentView extends DocComponent { let now = Date.now(); @@ -115,13 +116,13 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), isMinimized ? 1 : 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]) } } }); @@ -194,7 +190,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { maxDoc.isMinimized = false; if (!CollectionDockingView.Instance.CloseRightSplit(maxDoc)) { - CollectionDockingView.Instance.AddRightSplit(maxDoc.proto ? Doc.MakeDelegate(maxDoc.proto) : maxDoc); + CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(maxDoc)); } }); } } else { - this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(maxDoc, false)); + //if (altKey) this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(maxDoc, false)); this.toggleIcon(expandedDocs); } } -- cgit v1.2.3-70-g09d2 From 33c7af8d3e09e5add3ae56d5c7a697acee4104c3 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 16 May 2019 10:27:19 -0400 Subject: running into performance problems. fixed some things about summaries. --- src/client/views/PreviewCursor.tsx | 8 ++- src/client/views/Templates.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collections/collectionFreeForm/MarqueeView.tsx | 70 +++++++++++----------- 4 files changed, 42 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 4218ea7c9..7c1d00eb0 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -22,9 +22,11 @@ export class PreviewCursor extends React.Component<{}> { } paste = (e: ClipboardEvent) => { console.log(e.clipboardData); - console.log(e.clipboardData.getData("text/html")); - console.log(e.clipboardData.getData("text/csv")); - console.log(e.clipboardData.getData("text/plain")); + if (e.clipboardData) { + console.log(e.clipboardData.getData("text/html")); + console.log(e.clipboardData.getData("text/csv")); + console.log(e.clipboardData.getData("text/plain")); + } } @action diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index f0ee2856b..8d6bfbefd 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -73,7 +73,7 @@ export namespace Templates { export function ImageOverlay(width: number, height: number, field: string = "thumbnail") { return (`
-
{layout}
+
{layout}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b8bed795d..6e4c79e62 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -134,8 +134,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble) { - let x = this.props.Document.panX || 0; - let y = this.props.Document.panY || 0; + let x = this.Document.panX || 0; + let y = this.Document.panY || 0; let docs = this.children || []; let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay) { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index c063115e7..17d0a533e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -223,27 +223,21 @@ export class MarqueeView extends React.Component this.cleanupInteractions(false); e.stopPropagation(); } - if (e.key === "c" || e.key === "r" || e.key === "s" || e.key === "e" || e.key === "p") { + if (e.key === "c" || e.key === "s" || e.key === "e" || e.key === "p") { this._commandExecuted = true; e.stopPropagation(); (e as any).propagationIsStopped = true; let bounds = this.Bounds; - let selected = this.marqueeSelect().map(d => { - if (e.key === "s") { - let dCopy = Doc.MakeCopy(d); - dCopy.x = NumCast(d.x) - bounds.left - bounds.width / 2; - dCopy.y = NumCast(d.y) - bounds.top - bounds.height / 2; - dCopy.page = -1; - return dCopy; - } - else if (e.key !== "r") { + let selected = this.marqueeSelect(); + if (e.key === "c") { + selected.map(d => { this.props.removeDocument(d); d.x = NumCast(d.x) - bounds.left - bounds.width / 2; d.y = NumCast(d.y) - bounds.top - bounds.height / 2; d.page = -1; - } - return d; - }); + return d; + }); + } let ink = Cast(this.props.container.props.Document.ink, InkField); let inkData = ink ? ink.inkData : undefined; let zoomBasis = NumCast(this.props.container.props.Document.scale, 1); @@ -257,36 +251,40 @@ export class MarqueeView extends React.Component width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined, - title: e.key === "s" ? "-summary-" : e.key === "r" ? "-replacement-" : e.key === "p" ? "-summary-" : "a nested collection", + title: e.key === "s" ? "-summary-" : e.key === "p" ? "-summary-" : "a nested collection", }); - this.marqueeInkDelete(inkData); - // SelectionManager.DeselectAll(); - if (e.key === "s" || e.key === "r" || e.key === "p") { - e.preventDefault(); - let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - let dataUrl = await htmlToImage.toPng(this._mainCont.current!, { width: bounds.width, height: bounds.height, quality: 1 }); - summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); + if (e.key === "s" || e.key === "p") { - summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); - if (e.key === "s" || e.key === "p") { - // summary.proto!.maximizeOnRight = true; + htmlToImage.toPng(this._mainCont.current!, { width: bounds.width, height: bounds.height, quality: 1 }).then((dataUrl) => { + selected.map(d => { + this.props.removeDocument(d); + d.x = NumCast(d.x) - bounds.left - bounds.width / 2; + d.y = NumCast(d.y) - bounds.top - bounds.height / 2; + d.page = -1; + return d; + }); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); + summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); newCollection.proto!.summaryDoc = summary; selected = [newCollection]; - newCollection.proto!.isMinimized = true; + newCollection.x = bounds.left + bounds.width; this.props.addDocument(newCollection, false); - } - summary.proto!.summarizedDocs = new List(selected.map(s => s.proto!)); - //summary.proto!.isButton = true; - let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); - selected.map(summarizedDoc => { - let maxx = NumCast(summarizedDoc.x, undefined); - let maxy = NumCast(summarizedDoc.y, undefined); - let maxw = NumCast(summarizedDoc.width, undefined); - let maxh = NumCast(summarizedDoc.height, undefined); - }); - this.props.addLiveTextDocument(summary); + summary.proto!.summarizedDocs = new List(selected.map(s => s.proto!)); + //summary.proto!.maximizeOnRight = true; + //summary.proto!.isButton = true; + //let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); + // selected.map(summarizedDoc => { + // let maxx = NumCast(summarizedDoc.x, undefined); + // let maxy = NumCast(summarizedDoc.y, undefined); + // let maxw = NumCast(summarizedDoc.width, undefined); + // let maxh = NumCast(summarizedDoc.height, undefined); + // summarizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); + // }); + this.props.addLiveTextDocument(summary); + }) } else { this.props.addDocument(newCollection, false); -- cgit v1.2.3-70-g09d2 From 22d9a6540f2994331c397154f6a1fecd6e46ef8c Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 16 May 2019 11:19:50 -0400 Subject: fixed glitch in unminimizing --- .../views/nodes/CollectionFreeFormDocumentView.tsx | 51 ++++++++++------------ 1 file changed, 24 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 03538ae66..b82d02af5 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -20,7 +20,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { const schema = createSchema({ zoomBasis: "number", - zIndex: "number" + zIndex: "number", }); //TODO Types: The import order is wrong, so positionSchema is undefined @@ -43,9 +43,8 @@ export class CollectionFreeFormDocumentView extends DocComponent this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; panelWidth = () => this.props.PanelWidth(); panelHeight = () => this.props.PanelHeight(); @@ -87,8 +82,8 @@ export class CollectionFreeFormDocumentView extends DocComponent { let now = Date.now(); let progress = Math.min(1, (now - stime) / 200); let pval = maximizing ? [icon[0] + (targ[0] - icon[0]) * progress, icon[1] + (targ[1] - icon[1]) * progress] : [targ[0] + (icon[0] - targ[0]) * progress, targ[1] + (icon[1] - targ[1]) * progress]; - target.width = maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress; - target.height = maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress; - target.x = pval[0]; - target.y = pval[1]; + this.props.Document.width = maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress; + this.props.Document.height = maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress; + this.props.Document.x = pval[0]; + this.props.Document.y = pval[1]; + if (first) { + this.props.Document.proto!.willMaximize = false; + } if (now < stime + 200) { - this.animateBetweenIcon(false, icon, targ, width, height, stime, target, maximizing); + this.animateBetweenIcon(false, icon, targ, width, height, stime, maximizing); } else { if (!maximizing) { - target.proto!.isMinimized = true; - target.x = targ[0]; - target.y = targ[1]; - target.width = width; - target.height = height; + this.props.Document.proto!.isMinimized = true; + this.props.Document.x = targ[0]; + this.props.Document.y = targ[1]; + this.props.Document.width = width; + this.props.Document.height = height; } - target.proto!.isIconAnimating = undefined; + this.props.Document.proto!.isIconAnimating = undefined; } }, 2); @@ -151,7 +147,8 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]) } } @@ -263,7 +260,7 @@ export class CollectionFreeFormDocumentView extends DocComponent {this.docView} -- cgit v1.2.3-70-g09d2 From 5c7926ebe144644814043c43c0cdc2cf8866e4cd Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 16 May 2019 11:36:15 -0400 Subject: fixed highlighting thickness as much as possible. seems to be a minimum width of around 0.1 which is a problem zooming in. --- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index b82d02af5..7c7ca9e25 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -247,11 +247,11 @@ export class CollectionFreeFormDocumentView extends DocComponent Date: Thu, 16 May 2019 12:28:31 -0400 Subject: fixed MakeAlias to check if doc is prototype. fixed summary template to bottom/right + capture image when zoomed, fixed full screen to copy view data on delegate --- src/client/views/Templates.tsx | 2 +- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/new_fields/Doc.ts | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 8d6bfbefd..5d29e68ae 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -74,7 +74,7 @@ export namespace Templates { export function ImageOverlay(width: number, height: number, field: string = "thumbnail") { return (`
{layout}
-
+
`); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 17d0a533e..12edb2c2a 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -257,7 +257,7 @@ export class MarqueeView extends React.Component if (e.key === "s" || e.key === "p") { - htmlToImage.toPng(this._mainCont.current!, { width: bounds.width, height: bounds.height, quality: 1 }).then((dataUrl) => { + htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 1 }).then((dataUrl) => { selected.map(d => { this.props.removeDocument(d); d.x = NumCast(d.x) - bounds.left - bounds.width / 2; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 260630216..cf8bcbb42 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -227,7 +227,7 @@ export class DocumentView extends DocComponent(Docu } } fullScreenClicked = (e: React.MouseEvent): void => { - const doc = Doc.MakeDelegate(FieldValue(this.Document.proto)); + const doc = Doc.MakeCopy(this.props.Document, false); if (doc) { CollectionDockingView.Instance.OpenFullScreen(doc); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 2ae816da4..de72be3ea 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -140,7 +140,7 @@ export namespace Doc { return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult; } export async function SetOnPrototype(doc: Doc, key: string, value: Field) { - const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") == -1 ? doc.proto : doc; + const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto : doc; if (proto) { proto[key] = value; @@ -178,9 +178,10 @@ export namespace Doc { } export function MakeAlias(doc: Doc) { + const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto : undefined; const alias = new Doc; - if (!doc.proto) { + if (!proto) { alias.proto = doc; } else { PromiseValue(Cast(doc.proto, Doc)).then(proto => { -- cgit v1.2.3-70-g09d2 From 171f285b5e61d7a0591578f1499f81b779a3c340 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 16 May 2019 15:54:34 -0400 Subject: fixed ? pdf rendering. freezing text boxes. --- src/client/views/nodes/FormattedTextBox.tsx | 12 ++++++------ src/client/views/nodes/PDFBox.tsx | 25 +++++++++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 8e04071c7..f24d4ae88 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -269,14 +269,14 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } //REPLACE THIS WITH CAPABILITIES SPECIFIC TO THIS TYPE OF NODE - textCapability = (e: React.MouseEvent): void => { + freezeNativeDimensions = (e: React.MouseEvent): void => { if (NumCast(this.props.Document.nativeWidth)) { - this.props.Document.nativeWidth = undefined; - this.props.Document.nativeHeight = undefined; + this.props.Document.proto!.nativeWidth = undefined; + this.props.Document.proto!.nativeHeight = undefined; } else { - this.props.Document.nativeWidth = this.props.Document[WidthSym](); - this.props.Document.nativeHeight = this.props.Document[HeightSym](); + this.props.Document.proto!.nativeWidth = this.props.Document[WidthSym](); + this.props.Document.proto!.nativeHeight = this.props.Document[HeightSym](); } } specificContextMenu = (e: React.MouseEvent): void => { @@ -286,7 +286,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } ContextMenu.Instance.addItem({ description: NumCast(this.props.Document.nativeWidth) ? "Unfreeze" : "Freeze", - event: this.textCapability + event: this.freezeNativeDimensions }); } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 14fe2df80..f6328fa83 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -71,13 +71,14 @@ export class PDFBox extends DocComponent(PdfDocumen @computed private get thumbnailPage() { return NumCast(this.props.Document.thumbnailPage, -1); } componentDidMount() { + let wasSelected = false; this._reactionDisposer = reaction( - () => [SelectionManager.SelectedDocuments().slice()], + () => this.props.isSelected(), () => { - if (this.curPage > 0 && this.thumbnailPage > 0 && this.curPage !== this.thumbnailPage && !this.props.isSelected()) { + if (this.curPage > 0 && this.curPage !== this.thumbnailPage && wasSelected && !this.props.isSelected()) { this.saveThumbnail(); - this._interactive = true; } + wasSelected = this._interactive = this.props.isSelected(); }, { fireImmediately: true }); @@ -256,7 +257,7 @@ export class PDFBox extends DocComponent(PdfDocumen .catch(function (error: any) { console.error('oops, something went wrong!', error); }); - }, 250); + }, 1250); } @action @@ -283,24 +284,27 @@ export class PDFBox extends DocComponent(PdfDocumen } @computed get pdfPage() { - return ; + console.log(this.curPage); + return ; } @computed get pdfContent() { + trace(); let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); if (!pdfUrl) { return

No pdf url to render

; } - let body = NumCast(this.props.Document.nativeHeight) ? - this.pdfPage : + let pdfpage = this.pdfPage; + let body = this.Document.nativeHeight ? + pdfpage : {({ measureRef }) =>
- {this.pdfPage} + {pdfpage}
}
; - let xf = NumCast(this.Document.nativeHeight) / this.renderHeight; + let xf = (this.Document.nativeHeight || 0) / this.renderHeight; return
{body} @@ -336,7 +340,8 @@ export class PDFBox extends DocComponent(PdfDocumen @action onKeyDown = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = true); @action onKeyUp = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = false); render() { - let classname = "pdfBox-cont"; // + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); + trace(); + let classname = "pdfBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
{this.pdfRenderer} -- cgit v1.2.3-70-g09d2 From c96e61de2cea0fee1f6c80caf426535dbdc3d37c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 16 May 2019 16:08:53 -0400 Subject: Changed Clear DB Button --- .vscode/launch.json | 9 +++++++++ src/client/views/Main.tsx | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/.vscode/launch.json b/.vscode/launch.json index e92a4949a..452acc823 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,6 +13,15 @@ "url": "http://localhost:1050/login", "webRoot": "${workspaceFolder}", }, + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against Dash server", + "sourceMaps": true, + "breakOnLoad": true, + "url": "http://dash-web.eastus2.cloudapp.azure.com:1050/login", + "webRoot": "${workspaceFolder}", + }, { "type": "node", "request": "attach", diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 7aef7d3e5..866da010a 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -244,7 +244,7 @@ export class Main extends React.Component { let logoutRef = React.createRef(); return [ - , + ,
-- cgit v1.2.3-70-g09d2 From b29a0d1cef60b55f609fcd94ad38232ae557e681 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 16 May 2019 18:32:57 -0400 Subject: Fixed linter errors --- src/client/goldenLayout.d.ts | 3 +++ src/client/northstar/dash-fields/HistogramField.ts | 2 +- src/client/northstar/model/ModelHelpers.ts | 9 +++---- src/client/util/DragManager.ts | 2 +- src/client/util/RichTextSchema.tsx | 16 +++++------ src/client/util/TooltipTextMenu.tsx | 13 ++++----- src/client/views/DocumentDecorations.tsx | 31 +++++++++++----------- src/client/views/PresentationView.tsx | 4 +-- src/client/views/TemplateMenu.tsx | 4 +-- .../views/collections/CollectionDockingView.tsx | 5 ++-- .../views/collections/CollectionSchemaView.tsx | 10 +++---- .../views/collections/CollectionTreeView.tsx | 9 ++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 13 ++++----- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 8 +++--- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 3 ++- src/client/views/nodes/VideoBox.tsx | 22 +++++++-------- src/new_fields/CursorField.ts | 6 ++--- src/new_fields/Doc.ts | 4 +-- src/new_fields/ObjectField.ts | 2 +- .../authentication/models/current_user_utils.ts | 2 +- 24 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 src/client/goldenLayout.d.ts (limited to 'src') diff --git a/src/client/goldenLayout.d.ts b/src/client/goldenLayout.d.ts new file mode 100644 index 000000000..b50240563 --- /dev/null +++ b/src/client/goldenLayout.d.ts @@ -0,0 +1,3 @@ + +declare const GoldenLayout: any; +export = GoldenLayout; \ No newline at end of file diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index aabc77bb2..1ee2189b9 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -52,7 +52,7 @@ export class HistogramField extends ObjectField { [Copy]() { let y = this.HistoOp; - let z = this.HistoOp["Copy"]; + let z = this.HistoOp.Copy; return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } } \ No newline at end of file diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts index 80bb71224..88e6e72b8 100644 --- a/src/client/northstar/model/ModelHelpers.ts +++ b/src/client/northstar/model/ModelHelpers.ts @@ -32,12 +32,9 @@ export class ModelHelpers { public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number { return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => { - if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) - return true; - if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) - return true; - if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) - return true; + if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) return true; + if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) return true; + if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) return true; return false; }); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 26da34e67..05eb5c38a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -41,7 +41,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; - let draggedFromDocs: Doc[] = [] + let draggedFromDocs: Doc[] = []; if (srcTarg) { let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index c0e6f7899..3e3e98206 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -97,13 +97,13 @@ export const nodes: { [index: string]: NodeSpec } = { title: dom.getAttribute("title"), alt: dom.getAttribute("alt"), width: Math.min(100, Number(dom.getAttribute("width"))), - } + }; } }], // TODO if we don't define toDom, something weird happens: dragging the image will not move it but clone it. Why? toDOM(node) { - const attrs = { style: `width: ${node.attrs.width}` } - return ["img", { ...node.attrs, ...attrs }] + const attrs = { style: `width: ${node.attrs.width}` }; + return ["img", { ...node.attrs, ...attrs }]; } }, @@ -375,7 +375,7 @@ export class ImageResizeView { const currentX = e.pageX; const diffInPx = currentX - startX; self._outer.style.width = `${startWidth + diffInPx}`; - } + }; const onpointerup = () => { document.removeEventListener("pointermove", onpointermove); @@ -384,11 +384,11 @@ export class ImageResizeView { view.state.tr.setNodeMarkup(getPos(), null, { src: node.attrs.src, width: self._outer.style.width }) .setSelection(view.state.selection)); - } + }; - document.addEventListener("pointermove", onpointermove) - document.addEventListener("pointerup", onpointerup) - } + document.addEventListener("pointermove", onpointermove); + document.addEventListener("pointerup", onpointerup); + }; this._outer.appendChild(this._handle); this._outer.appendChild(this._img); diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 6eb654319..223921428 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -175,7 +175,7 @@ export class TooltipTextMenu { this.linkText.style.width = "150px"; this.linkText.style.overflow = "hidden"; this.linkText.style.color = "white"; - this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); } + this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); }; let linkBtn = document.createElement("div"); linkBtn.textContent = ">>"; linkBtn.style.width = "20px"; @@ -192,8 +192,9 @@ export class TooltipTextMenu { let docid = href.replace(DocServer.prepend("/doc/"), ""); DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) + if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); + } else CollectionDockingView.Instance.AddRightSplit(f); } })); @@ -201,7 +202,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.linkDrag = document.createElement("img"); this.linkDrag.src = "https://seogurusnyc.com/wp-content/uploads/2016/12/link-1.png"; this.linkDrag.style.width = "20px"; @@ -216,12 +217,12 @@ export class TooltipTextMenu { { handlers: { dragComplete: action(() => { - let m = dragData.droppedDocuments as Doc[]; + let m = dragData.droppedDocuments; this.makeLink(DocServer.prepend("/doc/" + m[0][Id])); }), }, hideSource: false - }) + }); }; this.linkEditor.appendChild(this.linkDrag); this.linkEditor.appendChild(this.linkText); @@ -239,7 +240,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.tooltip.appendChild(this.linkEditor); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b2c65a31f..7083b1003 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -250,22 +250,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); } if (!this._removeIcon) { - if (selectedDocs.length === 1) + if (selectedDocs.length === 1) { this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized()); - else - if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && - Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { - let docViews = SelectionManager.ViewsSortedVertically(); - let topDocView = docViews[0]; - let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); - if (ind !== -1) { - topDocView.templates.splice(ind, 1); - topDocView.props.Document.subBulletDocs = undefined; - } else { - topDocView.addTemplate(Templates.Bullet); - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); - } + } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && + Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { + let docViews = SelectionManager.ViewsSortedVertically(); + let topDocView = docViews[0]; + let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); + if (ind !== -1) { + topDocView.templates.splice(ind, 1); + topDocView.props.Document.subBulletDocs = undefined; + } else { + topDocView.addTemplate(Templates.Bullet); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); } + } } this._removeIcon = false; } @@ -537,9 +536,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (temp !== Templates.Bullet.Layout || i === 0) { res.push(temp); } - }) + }); } - return res + return res; }, [] as string[]); let checked = false; docTemps.forEach(temp => { diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 098e725c7..7d0dc2913 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; -import React = require("react") +import React = require("react"); import { observable, action, runInAction, reaction } from "mobx"; -import "./PresentationView.scss" +import "./PresentationView.scss"; import "./Main.tsx"; import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index cfe1b0663..e5b679e24 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -43,7 +43,7 @@ export class TemplateMenu extends React.Component { @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { if (event.target.checked) { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.addTemplate(template); topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); @@ -52,7 +52,7 @@ export class TemplateMenu extends React.Component { } this.props.templates.set(template, true); } else { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.removeTemplate(template); topDocView.props.Document.subBulletDocs = undefined; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 58f1e33a1..deec64225 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -83,7 +83,7 @@ export class CollectionDockingView extends React.Component tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) { child.contentItems[j].remove(); @@ -94,8 +94,9 @@ export class CollectionDockingView extends React.Component doc) { let fieldContentView = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => - (this.props.CollectionView!.props.isSelected() ? + (this.props.CollectionView.props.isSelected() ? SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined); let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { const res = run({ this: doc }); @@ -127,7 +127,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } const run = script.run; //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]) + const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); val && val.forEach(doc => applyToDoc(doc, run)); }}> @@ -230,14 +230,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { DocListCast(this.props.Document.data).map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; - }) + }); csv.substring(0, csv.length - 1); let dbName = StrCast(this.props.Document.title); let res = await Gateway.Instance.PostSchema(csv, dbName); if (self.props.CollectionView.props.addDocument) { let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); if (schemaDoc) { - self.props.CollectionView.props.addDocument(schemaDoc, false); + self.props.CollectionView.props.addDocument(schemaDoc, false); } } } @@ -263,7 +263,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewDocument(): Doc | undefined { const children = DocListCast(this.props.Document[this.props.fieldKey]); const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined; - return selected ? (this.previewScript && this.previewScript != "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; + return selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; } get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); } get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 70c09d97c..6acef434e 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -56,7 +56,7 @@ class TreeView extends React.Component { } else { CollectionDockingView.Instance.AddRightSplit(this.props.document); } - }; + } get children() { return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed? .filter(doc => FieldValue(doc)); @@ -184,8 +184,9 @@ class TreeView extends React.Component { {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)}
); - } else + } else { bulletType = BulletType.Collapsed; + } } }); return
{
; } public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) { - return docs.filter(child => child instanceof Doc && !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).filter(doc => FieldValue(doc)).map(child => - ); + return docs.filter(child => !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).map(child => + ); } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 12edb2c2a..c3c4115b8 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -63,7 +63,7 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); for (let i = 0; i < ns.length - 1; i++) { while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || ns[i].endsWith(";\r") || ns[i].endsWith(";") || @@ -80,7 +80,7 @@ export class MarqueeView extends React.Component let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); this.props.addDocument(newBox, false); y += 40 * this.props.getTransform().Scale; - }) + }); })(); } else if (e.key === "b" && e.ctrlKey) { //heuristically converts pasted text into a table. @@ -93,9 +93,10 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); - while (ns.length > 0 && ns[0].split("\t").length < 2) + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + while (ns.length > 0 && ns[0].split("\t").length < 2) { ns.splice(0, 1); + } if (ns.length > 0) { let columns = ns[0].split("\t"); let docList: Doc[] = []; @@ -109,7 +110,7 @@ export class MarqueeView extends React.Component let doc = new Doc(); columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { - doc["_group"] = groupAttr; + doc._group = groupAttr; } doc.title = i.toString(); docList.push(doc); @@ -284,7 +285,7 @@ export class MarqueeView extends React.Component // summarizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); // }); this.props.addLiveTextDocument(summary); - }) + }); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7c7ca9e25..d4f660b3f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]); } } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cf8bcbb42..428dd9b36 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -244,7 +244,7 @@ export class DocumentView extends DocComponent(Docu const protoDest = destDoc.proto; const protoSrc = sourceDoc.proto; - if (de.mods == "Control") { + if (de.mods === "Control") { let src = protoSrc ? protoSrc : sourceDoc; let dst = protoDest ? protoDest : destDoc; dst.data = src; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f24d4ae88..f30022508 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -184,7 +184,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), dispatchTransaction: this.dispatchTransaction, nodeViews: { - image(node, view, getPos) { return new ImageResizeView(node, view, getPos) } + image(node, view, getPos) { return new ImageResizeView(node, view, getPos); } } }); let text = StrCast(this.props.Document.documentText); @@ -232,9 +232,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) + if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); - else CollectionDockingView.Instance.AddRightSplit(f); + } else { + CollectionDockingView.Instance.AddRightSplit(f); + } } })); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6472ae711..3cc60a6c5 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -165,7 +165,7 @@ export class ImageBox extends DocComponent(ImageD else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50); let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; - let id = this.props.id; // bcz: used to set id = "isExpander" in templates.tsx + let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx return (
{ @observable private _keyInput: string = ""; @observable private _valueInput: string = ""; @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); } - get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document } + get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document; } constructor(props: FieldViewProps) { super(props); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 5de660d57..4f7919f50 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -46,8 +46,9 @@ export class KeyValuePair extends React.Component {
, + ,
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index d4f660b3f..001ce3095 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -205,11 +205,12 @@ export class CollectionFreeFormDocumentView extends DocComponent(Docu let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; - const protoDest = destDoc.proto; - const protoSrc = sourceDoc.proto; - if (de.mods === "Control") { + if (de.mods === "AltKey") { + const protoDest = destDoc.proto; + const protoSrc = sourceDoc.proto; let src = protoSrc ? protoSrc : sourceDoc; let dst = protoDest ? protoDest : destDoc; - dst.data = src; + dst.data = (src.data! as ObjectField)[Copy](); dst.nativeWidth = src.nativeWidth; dst.nativeHeight = src.nativeHeight; } else { - Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc); + Doc.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); } e.stopPropagation(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f30022508..bf98fb40b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -111,9 +111,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; - const protoDest = destDoc.proto; - const protoSrc = sourceDoc.proto; - Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc); + Doc.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); e.stopPropagation(); } diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 611cb66b6..68b692aad 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -31,7 +31,7 @@ export class LinkBox extends React.Component { @undoBatch onViewButtonPressed = async (e: React.PointerEvent): Promise => { e.stopPropagation(); - DocumentManager.Instance.jumpToDocument(this.props.pairedDoc); + DocumentManager.Instance.jumpToDocument(this.props.pairedDoc, e.altKey); } onEditButtonPressed = (e: React.PointerEvent): void => { diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 11117122d..4cf798249 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -6,8 +6,7 @@ import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; -import { Cast, FieldValue } from "../../../new_fields/Types"; -import { listSpec } from "../../../new_fields/Schema"; +import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { Id } from "../../../new_fields/RefField"; interface Props { @@ -24,7 +23,7 @@ export class LinkMenu extends React.Component { return links.map(link => { let doc = FieldValue(Cast(link[key], Doc)); if (doc) { - return this._editingLink = link)} type={type} />; + return this._editingLink = link)} type={type} />; } }); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index c898f697b..ad3b880cd 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -216,6 +216,8 @@ export namespace Doc { } export function MakeLink(source: Doc, target: Doc) { + let protoSrc = source.proto ? source.proto : source; + let protoTarg = target.proto ? target.proto : target; UndoManager.RunInBatch(() => { let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); //let linkDoc = new Doc; @@ -226,15 +228,15 @@ export namespace Doc { linkDoc.proto!.linkedTo = target; linkDoc.proto!.linkedFrom = source; - let linkedFrom = Cast(target.linkedFromDocs, listSpec(Doc)); + let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); if (!linkedFrom) { - target.linkedFromDocs = linkedFrom = new List(); + protoTarg.linkedFromDocs = linkedFrom = new List(); } linkedFrom.push(linkDoc); - let linkedTo = Cast(source.linkedToDocs, listSpec(Doc)); + let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); if (!linkedTo) { - source.linkedToDocs = linkedTo = new List(); + protoSrc.linkedToDocs = linkedTo = new List(); } linkedTo.push(linkDoc); return linkDoc; -- cgit v1.2.3-70-g09d2 From 2c8aaae6f026199e3675f5e7b4677724d5089ae7 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 17 May 2019 14:53:09 -0400 Subject: added something to follow links in current tab ? --- src/client/util/DocumentManager.ts | 33 +++++++++++++--------- .../views/collections/CollectionSchemaView.tsx | 7 ----- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- 3 files changed, 20 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index c6962ad8d..d06af6dd5 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,11 +1,14 @@ import { computed, observable } from 'mobx'; import { DocumentView } from '../views/nodes/DocumentView'; -import { Doc, DocListCast } from '../../new_fields/Doc'; +import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; import { undoBatch } from './UndoManager'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { Id } from '../../new_fields/RefField'; +import { CollectionView } from '../views/collections/CollectionView'; +import { CollectionPDFView } from '../views/collections/CollectionPDFView'; +import { CollectionVideoView } from '../views/collections/CollectionVideoView'; export class DocumentManager { @@ -27,31 +30,33 @@ export class DocumentManager { // this.DocumentViews = new Array(); } - public getDocumentViewById(id: string): DocumentView | null { + public getDocumentViewById(id: string, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null { let toReturn: DocumentView | null = null; + let passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - //gets document view that is in a freeform canvas collection - DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id) { - toReturn = view; - return; - } - }); - if (!toReturn) { + for (let i = 0; i < passes.length; i++) { DocumentManager.Instance.DocumentViews.map(view => { - let doc = view.props.Document.proto; - if (doc && doc[Id] === id) { + if (view.props.Document[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; + return; } }); + if (!toReturn) { + DocumentManager.Instance.DocumentViews.map(view => { + let doc = view.props.Document.proto; + if (doc && doc[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { + toReturn = view; + } + }); + } } return toReturn; } - public getDocumentView(toFind: Doc): DocumentView | null { - return this.getDocumentViewById(toFind[Id]); + public getDocumentView(toFind: Doc, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null { + return this.getDocumentViewById(toFind[Id], preferredCollection); } public getDocumentViews(toFind: Doc): DocumentView[] { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 497dfde88..e2b90e26d 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -24,14 +24,7 @@ import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; import { Id } from "../../../new_fields/RefField"; -import { isUndefined } from "typescript-collections/dist/lib/util"; -import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { Gateway } from "../../northstar/manager/Gateway"; -import { DocServer } from "../../DocServer"; -import { ColumnAttributeModel } from "../../northstar/core/attribute/AttributeModel"; -import { HistogramOperation } from "../../northstar/operations/HistogramOperation"; -import { AggregateFunction } from "../../northstar/model/idea/idea"; -import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel"; import { Docs } from "../../documents/Documents"; import { ContextMenu } from "../ContextMenu"; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 001ce3095..00aa71656 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -187,7 +187,7 @@ export class CollectionFreeFormDocumentView extends DocComponent Date: Fri, 17 May 2019 19:50:32 -0400 Subject: added right-click "open Tab" and double-click open tab --- src/client/views/Main.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 20 ++++++++++++++++++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + .../views/nodes/CollectionFreeFormDocumentView.tsx | 19 +++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 2 ++ src/client/views/nodes/FieldView.tsx | 2 ++ src/client/views/nodes/ImageBox.tsx | 4 +++- 7 files changed, 46 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 51ad0aa49..177047a9a 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -166,6 +166,7 @@ export class Main extends React.Component { { @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; - + _stack: any; constructor(props: any) { super(props); + this._stack = (this.props as any).glContainer.parent.parent; DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => this._document = f as Doc)); } @@ -420,6 +432,9 @@ export class DockedFrameRenderer extends React.Component { } get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } + addDocTab = (doc: Doc) => { + CollectionDockingView.Instance.AddTab(this._stack, doc); + } get content() { if (!this._document) { return (null); @@ -441,6 +456,7 @@ export class DockedFrameRenderer extends React.Component { parentActive={returnTrue} whenActiveChanged={emptyFunction} focus={emptyFunction} + addDocTab={this.addDocTab} ContainingCollectionView={undefined} />
); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 6e4c79e62..ad32f70dc 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -300,6 +300,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { parentActive: this.props.active, whenActiveChanged: this.props.whenActiveChanged, bringToFront: this.bringToFront, + addDocTab: this.props.addDocTab, }; } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 00aa71656..a0efc3154 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -159,6 +159,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { this._downX = e.clientX; @@ -166,6 +167,24 @@ export class CollectionFreeFormDocumentView extends DocComponent { + + document.removeEventListener("pointerup", this.onPointerUp); + if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { + this.props.addDocTab(this.props.Document); + } + e.stopPropagation(); } onClick = async (e: React.MouseEvent) => { e.stopPropagation(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5264773b0..9a5d21b49 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -57,6 +57,7 @@ export interface DocumentViewProps { whenActiveChanged: (isActive: boolean) => void; toggleMinimized: () => void; bringToFront: (doc: Doc) => void; + addDocTab: (doc: Doc) => void; } const schema = createSchema({ @@ -307,6 +308,7 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeButton }); cm.addItem({ description: "Fields", event: this.fieldsClicked }); cm.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) }); + cm.addItem({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document) }); cm.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }); cm.addItem({ description: "Find aliases", event: async () => { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 34b6c5e70..b5dfd18eb 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -35,6 +35,7 @@ export interface FieldViewProps { isTopMost: boolean; selectOnLoad: boolean; addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean; + addDocTab: (document: Doc) => boolean; removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; @@ -87,6 +88,7 @@ export class FieldView extends React.Component { return ( (ImageD let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx return ( -
+
Date: Fri, 17 May 2019 22:35:43 -0400 Subject: fixed shift-drag of main collection. --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ad32f70dc..b44a2f527 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -116,7 +116,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || (e.button === 0 && e.altKey)) && this.props.active())) || (!CollectionFreeFormView.RIGHT_BTN_DRAG && - ((e.button === 0 && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && this.props.active()))) { + ((e.button === 0 && !e.shiftKey && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && this.props.active()))) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9a5d21b49..b7d8eda9c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -181,11 +181,7 @@ export class DocumentView extends DocComponent(Docu } this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0; if (e.shiftKey && e.buttons === 1) { - if (this.props.isTopMost) { - this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined, this._hitExpander); - } else if (this.props.Document) { - CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e); - } + CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e); e.stopPropagation(); } else if (this.active) { //e.stopPropagation(); // bcz: doing this will block click events from CollectionFreeFormDocumentView which are needed for iconifying,etc -- cgit v1.2.3-70-g09d2 From 5220b9dc1f416a5e592fd359fb31033c63602e77 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 17 May 2019 23:16:11 -0400 Subject: fixed sorting within Schemas --- src/client/views/collections/CollectionSchemaView.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index e2b90e26d..2b4361e50 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -66,8 +66,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { - Document: rowProps.value[0], - fieldKey: rowProps.value[1], + Document: rowProps.original, + fieldKey: rowProps.column.id as string, ContainingCollectionView: this.props.CollectionView, isSelected: returnFalse, select: emptyFunction, @@ -79,6 +79,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { whenActiveChanged: emptyFunction, PanelHeight: returnZero, PanelWidth: returnZero, + addDocTab: this.props.addDocTab, }; let fieldContentView = ; let reference = React.createRef(); @@ -296,6 +297,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { parentActive={this.props.active} whenActiveChanged={this.props.whenActiveChanged} bringToFront={emptyFunction} + addDocTab={this.props.addDocTab} />
)} doc) { ({ Header: col, - accessor: (doc: Doc) => [doc, col], + accessor: (doc: Doc) => doc ? doc[col] : 0, id: col }))} column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} -- cgit v1.2.3-70-g09d2 From 4d6e5c21c452d4a9423f7925f6117b4f6d97093b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 00:27:32 -0400 Subject: removed some prints --- src/client/views/nodes/ImageBox.tsx | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 3cc60a6c5..881c4553a 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -42,7 +42,6 @@ export class ImageBox extends DocComponent(ImageD onLoad = (target: any) => { var h = this._imgRef.current!.naturalHeight; var w = this._imgRef.current!.naturalWidth; - console.log("title: " + this.Document.title); if (this._photoIndex === 0) { Doc.SetOnPrototype(this.Document, "nativeHeight", FieldValue(this.Document.nativeWidth, 0) * h / w); this.Document.height = FieldValue(this.Document.width, 0) * h / w; @@ -158,7 +157,6 @@ export class ImageBox extends DocComponent(ImageD } render() { - trace(); let field = this.Document[this.props.fieldKey]; let paths: string[] = ["http://www.cs.brown.edu/~bcz/face.gif"]; if (field instanceof ImageField) paths = [field.url.href]; -- cgit v1.2.3-70-g09d2 From c89cd609b9887e9dd5c32b74297699d8c675cc9b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 00:38:07 -0400 Subject: Fixed errors --- package-lock.json | 28 +++++++++++++++++++++------- src/client/views/ContextMenuItem.tsx | 25 +++++++++++++------------ 2 files changed, 34 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 6d4719d29..a1c954ef5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4137,12 +4137,14 @@ "balanced-match": { "version": "1.0.0", "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true }, "brace-expansion": { "version": "1.1.11", "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4157,17 +4159,20 @@ "code-point-at": { "version": "1.1.0", "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true }, "concat-map": { "version": "0.0.1", "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true }, "console-control-strings": { "version": "1.1.0", "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4284,7 +4289,8 @@ "inherits": { "version": "2.0.3", "resolved": false, - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "optional": true }, "ini": { "version": "1.3.5", @@ -4296,6 +4302,7 @@ "version": "1.0.0", "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4310,6 +4317,7 @@ "version": "3.0.4", "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4317,12 +4325,14 @@ "minimist": { "version": "0.0.8", "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "optional": true }, "minipass": { "version": "2.3.5", "resolved": false, "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4341,6 +4351,7 @@ "version": "0.5.1", "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4421,7 +4432,8 @@ "number-is-nan": { "version": "1.0.1", "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4433,6 +4445,7 @@ "version": "1.4.0", "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, "requires": { "wrappy": "1" } @@ -4554,6 +4567,7 @@ "version": "1.0.2", "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index aefc633bc..ed583942a 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -7,7 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; export interface OriginalMenuProps { description: string; event: (e: React.MouseEvent) => void; - icon: IconProp; //maybe should be optional (icon?) + icon?: IconProp; //maybe should be optional (icon?) } export interface SubmenuProps { @@ -38,27 +38,28 @@ export class ContextMenuItem extends React.Component {
- + {this.props.icon ? : null}
{this.props.description}
-
) +
+ ); } else { let submenu = null; if (this.overItem) { - submenu = (
- {this._items.map(prop => { - return - })} -
) + submenu = ( +
+ {this._items.map(prop => )} +
+ ); } return ( -
{ - this.overItem = true - })} onMouseLeave={action(() => this.overItem = false)}> +
{ this.overItem = true; })} + onMouseLeave={action(() => this.overItem = false)}>
{this.props.description}
{submenu} -
) +
+ ); } } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 215e59b22281573f05c42a9376d9b28263ed2518 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 00:40:59 -0400 Subject: deleted print --- src/client/views/ContextMenu.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 30ac23adf..9ccbb7149 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -43,7 +43,6 @@ export class ContextMenu extends React.Component { if (this._items.indexOf(item) === -1) { this._items.push(item); } - console.log(`After adding, there are ${this._items.length} items`); } getItems() { -- cgit v1.2.3-70-g09d2 From 764755f0b025eb3be234d53090ed1fce9a0e1300 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 01:09:15 -0400 Subject: Shrunk context menu text Uncapitalized header of columns in schema Added dragging to columns of schema --- src/client/views/ContextMenu.scss | 31 ++++---- .../views/collections/CollectionSchemaView.scss | 85 +++++++++++++++------- .../views/collections/CollectionSchemaView.tsx | 23 ++++-- 3 files changed, 94 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 3b1b18f88..0a14c8ce7 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -1,24 +1,25 @@ @import "globalCssVariables"; + .contextMenu-cont { - position: absolute; - display: flex; - z-index: $contextMenu-zindex; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; - flex-direction: column; + position: absolute; + display: flex; + z-index: $contextMenu-zindex; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; + flex-direction: column; } .contextMenu-item:first-child { - background: $intermediate-color; - color: $light-color; + background: $intermediate-color; + color: $light-color; } .contextMenu-item:first-child::placeholder { - color: $light-color; + color: $light-color; } .contextMenu-item:first-child:hover { - background: $intermediate-color; - color: $light-color; + background: $intermediate-color; + color: $light-color; } .subMenu-cont { @@ -49,16 +50,16 @@ border-bottom-style: solid; padding: 10px; white-space: nowrap; - font-size: 1.5vw; + font-size: 1vw; } .contextMenu-item:hover { - transition: all 0.1s; - background: $lighter-alt-accent; + transition: all 0.1s; + background: $lighter-alt-accent; } .contextMenu-description { - font-size: 1.5vw; + font-size: 1vw; text-align: left; width: 8vw; display: inline; //need this? @@ -66,4 +67,4 @@ .icon-background { background-color: #DDDDDD; -} +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index 5e9d2ac67..df5c52d01 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -4,7 +4,7 @@ .collectionSchemaView-container { border-width: $COLLECTION_BORDER_WIDTH; - border-color : $intermediate-color; + border-color: $intermediate-color; border-style: solid; border-radius: $border-radius; box-sizing: border-box; @@ -14,46 +14,52 @@ .collectionSchemaView-cellContents { height: $MAX_ROW_HEIGHT; + img { - width:auto; + width: auto; max-height: $MAX_ROW_HEIGHT; } } - + .collectionSchemaView-previewRegion { position: relative; background: $light-color; float: left; height: 100%; + .collectionSchemaView-previewDoc { height: 100%; - width: 100%; + width: 100%; position: absolute; } + .collectionSchemaView-input { position: absolute; max-width: 150px; width: 100%; bottom: 0px; } + .documentView-node:first-child { position: relative; background: $light-color; } } + .collectionSchemaView-previewHandle { position: absolute; height: 15px; - width: 15px; - z-index: 20; - right: 0; - top: 20px; - background: Black ; + width: 15px; + z-index: 20; + right: 0; + top: 20px; + background: Black; } - .collectionSchemaView-dividerDragger{ - position: relative; - background: black; - float: left; + + .collectionSchemaView-dividerDragger { + position: relative; + background: black; + float: left; height: 37px; width: 20px; z-index: 20; @@ -61,6 +67,7 @@ top: 0; background: $main-accent; } + .collectionSchemaView-columnsHandle { position: absolute; height: 37px; @@ -70,6 +77,7 @@ bottom: 0; background: $main-accent; } + .collectionSchemaView-colDividerDragger { position: relative; box-sizing: border-box; @@ -78,6 +86,7 @@ float: top; width: 100%; } + .collectionSchemaView-dividerDragger { position: relative; box-sizing: border-box; @@ -86,11 +95,13 @@ float: left; height: 100%; } + .collectionSchemaView-tableContainer { position: relative; float: left; height: 100%; } + .ReactTable { // position: absolute; // display: inline-block; // overflow: auto; @@ -99,6 +110,7 @@ background: $light-color; box-sizing: border-box; border: none !important; + .rt-table { overflow-y: auto; overflow-x: auto; @@ -107,26 +119,32 @@ direction: ltr; // direction:rtl; // display:block; } + .rt-tbody { //direction: ltr; direction: rtl; } + .rt-tr-group { direction: ltr; max-height: $MAX_ROW_HEIGHT; } + .rt-td { border-width: 1px; border-right-color: $intermediate-color; + .imageBox-cont { position: relative; max-height: 100%; } + .imageBox-cont img { object-fit: contain; max-width: 100%; height: 100%; } + .videoBox-cont { object-fit: contain; width: auto; @@ -134,15 +152,17 @@ } } } + .ReactTable .rt-thead.-header { background: $intermediate-color; color: $light-color; - text-transform: uppercase; + // text-transform: uppercase; letter-spacing: 2px; font-size: 12px; height: 30px; padding-top: 4px; } + .ReactTable .rt-th, .ReactTable .rt-td { max-height: $MAX_ROW_HEIGHT; @@ -150,32 +170,36 @@ font-size: 13px; text-align: center; } + .ReactTable .rt-tbody .rt-tr-group:last-child { border-bottom: $intermediate-color; border-bottom-style: solid; border-bottom-width: 1; } + .documentView-node-topmost { - text-align:left; + text-align: left; transform-origin: center top; display: inline-block; } + .documentView-node:first-child { background: $light-color; } } + //options menu styling #schemaOptionsMenuBtn { position: absolute; height: 20px; width: 20px; border-radius: 50%; - z-index: 21; + z-index: 21; right: 4px; - top: 4px; + top: 4px; pointer-events: auto; - background-color:black; - display:inline-block; + background-color: black; + display: inline-block; padding: 0px; font-size: 100%; } @@ -189,10 +213,12 @@ ul { padding: 0px; margin: 0px; } + .schema-options-subHeader { color: $intermediate-color; margin-bottom: 5px; } + #schemaOptionsMenuBtn:hover { transform: scale(1.15); } @@ -202,15 +228,15 @@ ul { font-size: 12px; } - #options-flyout-div { +#options-flyout-div { text-align: left; - padding:0px; + padding: 0px; z-index: 100; font-family: $sans-serif; padding-left: 5px; - } +} - #schema-col-checklist { +#schema-col-checklist { overflow: scroll; text-align: left; //background-color: $light-color-secondary; @@ -218,8 +244,8 @@ ul { max-height: 175px; font-family: $sans-serif; font-size: 12px; - } - +} + .Resizer { box-sizing: border-box; @@ -227,6 +253,7 @@ ul { opacity: 0.5; z-index: 1; background-clip: padding-box; + &.horizontal { height: 11px; margin: -5px 0; @@ -234,22 +261,26 @@ ul { border-bottom: 5px solid rgba(255, 255, 255, 0); cursor: row-resize; width: 100%; + &:hover { border-top: 5px solid rgba(0, 0, 0, 0.5); border-bottom: 5px solid rgba(0, 0, 0, 0.5); } } + &.vertical { width: 11px; margin: 0 -5px; border-left: 5px solid rgba(255, 255, 255, 0); border-right: 5px solid rgba(255, 255, 255, 0); cursor: col-resize; + &:hover { border-left: 5px solid rgba(0, 0, 0, 0.5); border-right: 5px solid rgba(0, 0, 0, 0.5); } } + &:hover { -webkit-transition: all 2s ease; transition: all 2s ease; @@ -270,10 +301,12 @@ ul { -ms-flex-direction: column; flex-direction: column; } + header { padding: 1rem; background: #eee; } + footer { padding: 1rem; background: #eee; @@ -287,10 +320,12 @@ ul { display: flex; flex-direction: column; } + header { padding: 1rem; background: #eee; } + footer { padding: 1rem; background: #eee; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index c6b0ff014..f15da41ff 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -64,6 +64,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } + @computed get tableColumns() { + return this.columns.map(col => { + const ref = React.createRef(); + return { + Header:

this.onHeaderDrag(col))}>{col}

, + accessor: (doc: Doc) => doc ? doc[col] : 0, + id: col + }; + }); + } + + onHeaderDrag = (columnName: string) => { + return this.props.Document; + } + renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { Document: rowProps.original, @@ -349,6 +364,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
; } + + render() { library.add(faCog); library.add(faPlus); @@ -358,11 +375,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
({ - Header: col, - accessor: (doc: Doc) => doc ? doc[col] : 0, - id: col - }))} + columns={this.tableColumns} column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} /> -- cgit v1.2.3-70-g09d2 From a3fab7b55372dd031a19af0ae583cf6f100c0854 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 02:32:08 -0400 Subject: Added immediate fetching of prototypes --- src/client/DocServer.ts | 13 +++++++++---- src/new_fields/util.ts | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index a288d394a..e2f9b3601 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -21,12 +21,10 @@ export namespace DocServer { export async function GetRefField(id: string): Promise> { let cached = _cache[id]; if (cached === undefined) { - const prom = Utils.EmitCallback(_socket, MessageStore.GetRefField, id).then(fieldJson => { + const prom = Utils.EmitCallback(_socket, MessageStore.GetRefField, id).then(async fieldJson => { const field = SerializationHelper.Deserialize(fieldJson); - if (_cache[id] !== undefined && !(_cache[id] instanceof Promise)) { - id; - } if (field !== undefined) { + await field.proto; _cache[id] = field; } else { delete _cache[id]; @@ -65,6 +63,7 @@ export namespace DocServer { fieldMap[field.id] = SerializationHelper.Deserialize(field); } } + return fieldMap; }); requestedIds.forEach(id => _cache[id] = prom.then(fields => fields[id])); @@ -78,6 +77,12 @@ export namespace DocServer { } map[id] = field; }); + await Promise.all(requestedIds.map(async id => { + const field = fields[id]; + if (field) { + await (field as any).proto; + } + })); const otherFields = await Promise.all(promises); waitingIds.forEach((id, index) => map[id] = otherFields[index]); return map; diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 3a16a6b42..d94994a07 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -73,7 +73,7 @@ export function getField(target: any, prop: string | number, ignoreProto: boolea if (field instanceof ProxyField) { return field.value(callback); } - if (field === undefined && !ignoreProto) { + if (field === undefined && !ignoreProto && prop !== "proto") { const proto = getField(target, "proto", true); if (proto instanceof Doc) { return getProtoField(proto, prop, callback); -- cgit v1.2.3-70-g09d2 From 718269e2fa50e20227bfbb32b1a1b6ec8f78184d Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 18 May 2019 09:42:43 -0400 Subject: fixed font error message. Improved opening summaries as either inTab or inPlace and switching with the alt-key --- src/client/views/ContextMenu.tsx | 3 ++- src/client/views/DocumentDecorations.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 7 +++-- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 30 ++++++++++++---------- src/client/views/nodes/DocumentView.tsx | 4 +-- src/client/views/nodes/FieldView.tsx | 2 +- 7 files changed, 30 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 9ccbb7149..9143c012e 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -5,9 +5,10 @@ import { observer } from "mobx-react" import "./ContextMenu.scss" import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faSearch } from '@fortawesome/free-solid-svg-icons'; +import { faSearch, faCircle } from '@fortawesome/free-solid-svg-icons'; library.add(faSearch); +library.add(faCircle); @observer export class ContextMenu extends React.Component { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 7083b1003..d440ed898 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -279,7 +279,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> iconDoc.proto!.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title); iconDoc.labelField = selected.length > 1 ? undefined : this._fieldKey; iconDoc.proto![this._fieldKey] = selected.length > 1 ? "collection" : undefined; - iconDoc.isMinimized = false; + iconDoc.proto!.isMinimized = false; iconDoc.width = Number(MINIMIZED_ICON_SIZE); iconDoc.height = Number(MINIMIZED_ICON_SIZE); iconDoc.x = NumCast(doc.x); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 28624e020..74f8ad242 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -432,8 +432,11 @@ export class DockedFrameRenderer extends React.Component { } get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } - addDocTab = (doc: Doc) => { - CollectionDockingView.Instance.AddTab(this._stack, doc); + addDocTab = (doc: Doc, location: string) => { + if (location === "onRight") + CollectionDockingView.Instance.AddRightSplit(doc); + else + CollectionDockingView.Instance.AddTab(this._stack, doc); } get content() { if (!this._document) { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index c3c4115b8..6301fd27e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -272,9 +272,9 @@ export class MarqueeView extends React.Component newCollection.proto!.summaryDoc = summary; selected = [newCollection]; newCollection.x = bounds.left + bounds.width; - this.props.addDocument(newCollection, false); + //this.props.addDocument(newCollection, false); summary.proto!.summarizedDocs = new List(selected.map(s => s.proto!)); - //summary.proto!.maximizeOnRight = true; + summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" //summary.proto!.isButton = true; //let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); // selected.map(summarizedDoc => { diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index a0efc3154..833947ac3 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -3,7 +3,7 @@ import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; -import { BoolCast, Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { OmitKeys, Utils } from "../../../Utils"; import { DocumentManager } from "../../util/DocumentManager"; import { SelectionManager } from "../../util/SelectionManager"; @@ -139,7 +139,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { let iconAnimating = Cast(maximizedDoc.isIconAnimating, List); - if (!iconAnimating || (Date.now() - iconAnimating[6] > 1000)) { + if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) { if (isMinimized === undefined) { isMinimized = BoolCast(maximizedDoc.isMinimized, false); } @@ -179,10 +179,9 @@ export class CollectionFreeFormDocumentView extends DocComponent { - document.removeEventListener("pointerup", this.onPointerUp); if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { - this.props.addDocTab(this.props.Document); + this.props.addDocTab(this.props.Document, "inTab"); } e.stopPropagation(); } @@ -193,6 +192,7 @@ export class CollectionFreeFormDocumentView extends DocComponent maxDoc.isMinimized = false); + hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); + maxLocation = this.props.Document.maximizeLocation = (maxLocation === "inPlace" ? "inTab" : "inPlace"); + if (!hasView && maxLocation === "inPlace") { + this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(Doc.MakeDelegate(maxDoc), false)); + expandedDocs.forEach(maxDoc => maxDoc.isMinimized = true); + } + } + if (!hasView && maxLocation !== "inPlace") { let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data); if (dataDocs) { - SelectionManager.DeselectAll(); expandedDocs.forEach(maxDoc => { - maxDoc.isMinimized = false; if (!CollectionDockingView.Instance.CloseRightSplit(maxDoc)) { - CollectionDockingView.Instance.AddRightSplit(Doc.MakeDelegate(maxDoc)); + this.props.addDocTab(Doc.MakeDelegate(maxDoc), maxLocation); } }); } } else { - //if (altKey) this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(maxDoc, false)); this.toggleIcon(expandedDocs); } } else if (linkedToDocs.length || linkedFromDocs.length) { - SelectionManager.DeselectAll(); let linkedFwdDocs = [ linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : expandedDocs[0], linkedFromDocs.length ? linkedFromDocs[0].linkedFrom as Doc : linkedToDocs.length ? linkedToDocs[0].linkedTo as Doc : expandedDocs[0]]; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7167da93b..760e31b49 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -68,7 +68,7 @@ export interface DocumentViewProps { whenActiveChanged: (isActive: boolean) => void; toggleMinimized: () => void; bringToFront: (doc: Doc) => void; - addDocTab: (doc: Doc) => void; + addDocTab: (doc: Doc, where: string) => void; } const schema = createSchema({ @@ -315,7 +315,7 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeButton, icon: "expand-arrows-alt" }); cm.addItem({ description: "Fields", event: this.fieldsClicked, icon: "layer-group" }); cm.addItem({ description: "Center", event: () => this.props.focus(this.props.Document), icon: "align-center" }); - cm.addItem({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document), icon: "expand-arrows-alt" }); + cm.addItem({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "inTab"), icon: "expand-arrows-alt" }); cm.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document), icon: "caret-square-right" }); cm.addItem({ description: "Find aliases", event: async () => { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index b5dfd18eb..5c149af99 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) => boolean; + addDocTab: (document: Doc, where: string) => boolean; removeDocument?: (document: Doc) => boolean; moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; -- cgit v1.2.3-70-g09d2 From 3fd191a2d031e1a186a4eb2e009887399a4bc347 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 18 May 2019 10:50:28 -0400 Subject: more fixes to maximizing docs to default to showing the same prototype each time. --- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 35 ++++++++++++---------- src/new_fields/Doc.ts | 6 ++++ 3 files changed, 26 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6301fd27e..d102c8af2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -273,7 +273,7 @@ export class MarqueeView extends React.Component selected = [newCollection]; newCollection.x = bounds.left + bounds.width; //this.props.addDocument(newCollection, false); - summary.proto!.summarizedDocs = new List(selected.map(s => s.proto!)); + summary.proto!.summarizedDocs = new List(selected); summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" //summary.proto!.isButton = true; //let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 833947ac3..7cb4c1dfe 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -137,7 +137,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { + maximizedDocs.map(d => Doc.GetProto(d)).map(maximizedDoc => { let iconAnimating = Cast(maximizedDoc.isIconAnimating, List); if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) { if (isMinimized === undefined) { @@ -204,28 +204,31 @@ export class CollectionFreeFormDocumentView extends DocComponent Doc.GetProto(doc)) let maxLocation = StrCast(this.props.Document.maximizeLocation, "inPlace"); - if (!hasView && altKey) { - expandedDocs.forEach(maxDoc => maxDoc.isMinimized = false); - hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - maxLocation = this.props.Document.maximizeLocation = (maxLocation === "inPlace" ? "inTab" : "inPlace"); - if (!hasView && maxLocation === "inPlace") { - this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(Doc.MakeDelegate(maxDoc), false)); - expandedDocs.forEach(maxDoc => maxDoc.isMinimized = true); + let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target); + if (altKey) { + maxLocation = this.props.Document.maximizeLocation = (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace"); + if (!maxLocation || maxLocation === "inPlace") { + let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedProtoDocs[0], this.props.ContainingCollectionView); + let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized, false), false); + expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false); + let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedProtoDocs[0], this.props.ContainingCollectionView); + if (!hasView) { + this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(getDispDoc(maxDoc), false)); + } + expandedProtoDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized); } } - if (!hasView && maxLocation !== "inPlace") { + if (maxLocation && maxLocation !== "inPlace") { let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data); if (dataDocs) { - expandedDocs.forEach(maxDoc => { - if (!CollectionDockingView.Instance.CloseRightSplit(maxDoc)) { - this.props.addDocTab(Doc.MakeDelegate(maxDoc), maxLocation); - } - }); + expandedDocs.forEach(maxDoc => + (!CollectionDockingView.Instance.CloseRightSplit(Doc.GetProto(maxDoc)) && + this.props.addDocTab(getDispDoc(maxDoc), maxLocation))); } } else { - this.toggleIcon(expandedDocs); + this.toggleIcon(expandedProtoDocs); } } else if (linkedToDocs.length || linkedFromDocs.length) { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index a7aa571f8..020f764a2 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -177,6 +177,12 @@ export namespace Doc { return r || r2 || r3 || r4 ? true : false; } + // gets the document's prototype or returns the document if it is a prototype + export function GetProto(doc: Doc) { + return Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto! : doc; + } + + export function MakeAlias(doc: Doc) { const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto : undefined; const alias = new Doc; -- cgit v1.2.3-70-g09d2 From ea0b202809a2c4ddddf5f391cdf6fe8bc6523092 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 15:25:42 -0400 Subject: Refactored some things to get Debug viewer working again --- src/client/util/History.ts | 4 +- src/client/views/Main.tsx | 280 +--------------- src/client/views/MainView.tsx | 274 ++++++++++++++++ src/client/views/PresentationView.tsx | 1 - .../views/collections/CollectionTreeView.tsx | 8 +- src/debug/Viewer.tsx | 364 +++++++++++---------- 6 files changed, 468 insertions(+), 463 deletions(-) create mode 100644 src/client/views/MainView.tsx (limited to 'src') diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 92d2b2b44..545ea8629 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -1,7 +1,7 @@ import { Doc, Opt, Field } from "../../new_fields/Doc"; import { DocServer } from "../DocServer"; -import { Main } from "../views/Main"; import { RouteStore } from "../../server/RouteStore"; +import { MainView } from "../views/MainView"; export namespace HistoryUtil { export interface DocInitializerList { @@ -114,7 +114,7 @@ export namespace HistoryUtil { const field = await DocServer.GetRefField(url.docId); await Promise.all(Object.keys(url.initializers).map(id => initDoc(id, url.initializers[id]))); if (field instanceof Doc) { - Main.Instance.openWorkspace(field, true); + MainView.Instance.openWorkspace(field, true); } } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 177047a9a..3d9750a85 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -1,281 +1,11 @@ -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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, configure, observable, runInAction, trace } from 'mobx'; -import { observer } from 'mobx-react'; -import "normalize.css"; -import * as React from 'react'; +import { MainView } from "./MainView"; +import { Docs } from "../documents/Documents"; +import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; import * as ReactDOM from 'react-dom'; -import Measure from 'react-measure'; -import * as request from 'request'; -import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; -import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils'; -import { Docs } from '../documents/Documents'; -import { SetupDrag, DragManager } from '../util/DragManager'; -import { Transform } from '../util/Transform'; -import { UndoManager } from '../util/UndoManager'; -import { PresentationView } from './PresentationView'; -import { CollectionDockingView } from './collections/CollectionDockingView'; -import { ContextMenu } from './ContextMenu'; -import { DocumentDecorations } from './DocumentDecorations'; -import { InkingControl } from './InkingControl'; -import "./Main.scss"; -import { MainOverlayTextBox } from './MainOverlayTextBox'; -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 { Cast, FieldValue, StrCast } from '../../new_fields/Types'; -import { DocServer } from '../DocServer'; -import { listSpec } from '../../new_fields/Schema'; -import { Id } from '../../new_fields/RefField'; -import { HistoryUtil } from '../util/History'; - - -@observer -export class Main extends React.Component { - public static Instance: Main; - @observable private _workspacesShown: boolean = false; - @observable public pwidth: number = 0; - @observable public pheight: number = 0; - - @computed private get mainContainer(): Opt { - return FieldValue(Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc)); - } - private set mainContainer(doc: Opt) { - if (doc) { - if (!("presentationView" in doc)) { - doc.presentationView = new Doc(); - } - CurrentUserUtils.UserDocument.activeWorkspace = doc; - } - } - - constructor(props: Readonly<{}>) { - super(props); - Main.Instance = this; - // causes errors to be generated when modifying an observable outside of an action - configure({ enforceActions: "observed" }); - if (window.location.pathname !== RouteStore.home) { - let pathname = window.location.pathname.split("/"); - if (pathname.length > 1 && pathname[pathname.length - 2] === 'doc') { - CurrentUserUtils.MainDocId = pathname[pathname.length - 1]; - } - } - - library.add(faFont); - library.add(faImage); - library.add(faFilePdf); - library.add(faObjectGroup); - library.add(faTable); - library.add(faGlobeAsia); - library.add(faUndoAlt); - library.add(faRedoAlt); - library.add(faPenNib); - library.add(faFilm); - library.add(faMusic); - library.add(faTree); - this.initEventListeners(); - this.initAuthenticationRouters(); - } - - initEventListeners = () => { - // window.addEventListener("pointermove", (e) => this.reportLocation(e)) - window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler - window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler - window.addEventListener("keydown", (e) => { - if (e.key === "Escape") { - DragManager.AbortDrag(); - SelectionManager.DeselectAll(); - } - }, 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)) { - ContextMenu.Instance.clearItems(); - } - }), true); - } - - initAuthenticationRouters = async () => { - // Load the user's active workspace, or create a new one if initial session after signup - if (!CurrentUserUtils.MainDocId) { - const doc = await Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc); - if (doc) { - this.openWorkspace(doc); - } else { - this.createNewWorkspace(); - } - } else { - DocServer.GetRefField(CurrentUserUtils.MainDocId).then(field => - field instanceof Doc ? this.openWorkspace(field) : - this.createNewWorkspace(CurrentUserUtils.MainDocId)); - } - } - - @action - createNewWorkspace = async (id?: string) => { - const list = Cast(CurrentUserUtils.UserDocument.data, listSpec(Doc)); - if (list) { - let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, title: `WS collection ${list.length + 1}` }); - var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, 600)] }] }; - let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }); - list.push(mainDoc); - // 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; - }, 0); - } - } - - @action - openWorkspace = async (doc: Doc, fromHistory = false) => { - CurrentUserUtils.MainDocId = doc[Id]; - this.mainContainer = doc; - fromHistory || HistoryUtil.pushState({ type: "doc", docId: doc[Id], initializers: {} }); - const col = await Cast(CurrentUserUtils.UserDocument.optionalRightCollection, Doc); - // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized) - setTimeout(async () => { - if (col) { - const l = Cast(col.data, listSpec(Doc)); - if (l && l.length > 0) { - CollectionDockingView.Instance.AddRightSplit(col); - } - } - }, 100); - } - @action - onResize = (r: any) => { - this.pwidth = r.offset.width; - this.pheight = r.offset.height; - } - getPWidth = () => { - return this.pwidth; - } - getPHeight = () => { - return this.pheight; - } - @computed - get mainContent() { - let mainCont = this.mainContainer; - let content = !mainCont ? (null) : - ; - const pres = mainCont ? FieldValue(Cast(mainCont.presentationView, Doc)) : undefined; - return - {({ measureRef }) => -
- {content} - {pres ? : null} -
- } -
; - } - - /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ - nodesMenu() { - - let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; - let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c27211_sample_explain.pdf"; - let weburl = "https://cs.brown.edu/courses/cs166/"; - let audiourl = "http://techslides.com/demos/samples/sample.mp3"; - let videourl = "http://techslides.com/demos/sample-videos/small.mp4"; - - let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" })); - let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); - let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" })); - let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); - // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); - let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" })); - let addPDFNode = action(() => Docs.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" })); - let addImageNode = action(() => Docs.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })); - let addWebNode = action(() => Docs.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" })); - let addAudioNode = action(() => Docs.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" })); - - let btns: [React.RefObject, IconName, string, () => Doc][] = [ - [React.createRef(), "font", "Add Textbox", addTextNode], - [React.createRef(), "image", "Add Image", addImageNode], - [React.createRef(), "file-pdf", "Add PDF", addPDFNode], - [React.createRef(), "film", "Add Video", addVideoNode], - [React.createRef(), "music", "Add Audio", addAudioNode], - [React.createRef(), "globe-asia", "Add Web Clipping", addWebNode], - [React.createRef(), "object-group", "Add Collection", addColNode], - [React.createRef(), "tree", "Add Tree", addTreeNode], - [React.createRef(), "table", "Add Schema", addSchemaNode], - ]; - - return < div id="add-nodes-menu" > - - - -
-
    - {btns.map(btn => -
  • - -
  • )} -
-
-
; - } - - /* @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() { - let logoutRef = React.createRef(); - - return [ - , -
- - - -
, -
, -
-
- ]; - - } - - render() { - return ( -
- - {this.mainContent} - - - {this.nodesMenu()} - {this.miscButtons} - - -
- ); - } -} +import * as React from 'react'; (async () => { await Docs.initProtos(); await CurrentUserUtils.loadCurrentUser(); - ReactDOM.render(
, document.getElementById('root')); + ReactDOM.render(, document.getElementById('root')); })(); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx new file mode 100644 index 000000000..d0d77bbf4 --- /dev/null +++ b/src/client/views/MainView.tsx @@ -0,0 +1,274 @@ +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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, configure, observable, runInAction, trace } from 'mobx'; +import { observer } from 'mobx-react'; +import "normalize.css"; +import * as React from 'react'; +import Measure from 'react-measure'; +import * as request from 'request'; +import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; +import { RouteStore } from '../../server/RouteStore'; +import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils'; +import { Docs } from '../documents/Documents'; +import { SetupDrag, DragManager } from '../util/DragManager'; +import { Transform } from '../util/Transform'; +import { UndoManager } from '../util/UndoManager'; +import { PresentationView } from './PresentationView'; +import { CollectionDockingView } from './collections/CollectionDockingView'; +import { ContextMenu } from './ContextMenu'; +import { DocumentDecorations } from './DocumentDecorations'; +import { InkingControl } from './InkingControl'; +import "./Main.scss"; +import { MainOverlayTextBox } from './MainOverlayTextBox'; +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 { Cast, FieldValue, StrCast } from '../../new_fields/Types'; +import { DocServer } from '../DocServer'; +import { listSpec } from '../../new_fields/Schema'; +import { Id } from '../../new_fields/RefField'; +import { HistoryUtil } from '../util/History'; + + +@observer +export class MainView extends React.Component { + public static Instance: MainView; + @observable private _workspacesShown: boolean = false; + @observable public pwidth: number = 0; + @observable public pheight: number = 0; + + @computed private get mainContainer(): Opt { + return FieldValue(Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc)); + } + private set mainContainer(doc: Opt) { + if (doc) { + if (!("presentationView" in doc)) { + doc.presentationView = new Doc(); + } + CurrentUserUtils.UserDocument.activeWorkspace = doc; + } + } + + constructor(props: Readonly<{}>) { + super(props); + MainView.Instance = this; + // causes errors to be generated when modifying an observable outside of an action + configure({ enforceActions: "observed" }); + if (window.location.pathname !== RouteStore.home) { + let pathname = window.location.pathname.split("/"); + if (pathname.length > 1 && pathname[pathname.length - 2] === 'doc') { + CurrentUserUtils.MainDocId = pathname[pathname.length - 1]; + } + } + + library.add(faFont); + library.add(faImage); + library.add(faFilePdf); + library.add(faObjectGroup); + library.add(faTable); + library.add(faGlobeAsia); + library.add(faUndoAlt); + library.add(faRedoAlt); + library.add(faPenNib); + library.add(faFilm); + library.add(faMusic); + library.add(faTree); + this.initEventListeners(); + this.initAuthenticationRouters(); + } + + initEventListeners = () => { + // window.addEventListener("pointermove", (e) => this.reportLocation(e)) + window.addEventListener("drop", (e) => e.preventDefault(), false); // drop event handler + window.addEventListener("dragover", (e) => e.preventDefault(), false); // drag event handler + window.addEventListener("keydown", (e) => { + if (e.key === "Escape") { + DragManager.AbortDrag(); + SelectionManager.DeselectAll(); + } + }, 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)) { + ContextMenu.Instance.clearItems(); + } + }), true); + } + + initAuthenticationRouters = async () => { + // Load the user's active workspace, or create a new one if initial session after signup + if (!CurrentUserUtils.MainDocId) { + const doc = await Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc); + if (doc) { + this.openWorkspace(doc); + } else { + this.createNewWorkspace(); + } + } else { + DocServer.GetRefField(CurrentUserUtils.MainDocId).then(field => + field instanceof Doc ? this.openWorkspace(field) : + this.createNewWorkspace(CurrentUserUtils.MainDocId)); + } + } + + @action + createNewWorkspace = async (id?: string) => { + const list = Cast(CurrentUserUtils.UserDocument.data, listSpec(Doc)); + if (list) { + let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, title: `WS collection ${list.length + 1}` }); + var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, 600)] }] }; + let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }); + list.push(mainDoc); + // 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; + }, 0); + } + } + + @action + openWorkspace = async (doc: Doc, fromHistory = false) => { + CurrentUserUtils.MainDocId = doc[Id]; + this.mainContainer = doc; + fromHistory || HistoryUtil.pushState({ type: "doc", docId: doc[Id], initializers: {} }); + const col = await Cast(CurrentUserUtils.UserDocument.optionalRightCollection, Doc); + // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized) + setTimeout(async () => { + if (col) { + const l = Cast(col.data, listSpec(Doc)); + if (l && l.length > 0) { + CollectionDockingView.Instance.AddRightSplit(col); + } + } + }, 100); + } + @action + onResize = (r: any) => { + this.pwidth = r.offset.width; + this.pheight = r.offset.height; + } + getPWidth = () => { + return this.pwidth; + } + getPHeight = () => { + return this.pheight; + } + @computed + get mainContent() { + let mainCont = this.mainContainer; + let content = !mainCont ? (null) : + ; + const pres = mainCont ? FieldValue(Cast(mainCont.presentationView, Doc)) : undefined; + return + {({ measureRef }) => +
+ {content} + {pres ? : null} +
+ } +
; + } + + /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ + nodesMenu() { + + let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; + let pdfurl = "http://www.adobe.com/support/products/enterprise/knowledgecenter/media/c27211_sample_explain.pdf"; + let weburl = "https://cs.brown.edu/courses/cs166/"; + let audiourl = "http://techslides.com/demos/samples/sample.mp3"; + let videourl = "http://techslides.com/demos/sample-videos/small.mp4"; + + let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" })); + let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); + let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" })); + let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); + // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); + let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" })); + let addPDFNode = action(() => Docs.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" })); + let addImageNode = action(() => Docs.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })); + let addWebNode = action(() => Docs.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" })); + let addAudioNode = action(() => Docs.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" })); + + let btns: [React.RefObject, IconName, string, () => Doc][] = [ + [React.createRef(), "font", "Add Textbox", addTextNode], + [React.createRef(), "image", "Add Image", addImageNode], + [React.createRef(), "file-pdf", "Add PDF", addPDFNode], + [React.createRef(), "film", "Add Video", addVideoNode], + [React.createRef(), "music", "Add Audio", addAudioNode], + [React.createRef(), "globe-asia", "Add Web Clipping", addWebNode], + [React.createRef(), "object-group", "Add Collection", addColNode], + [React.createRef(), "tree", "Add Tree", addTreeNode], + [React.createRef(), "table", "Add Schema", addSchemaNode], + ]; + + return < div id="add-nodes-menu" > + + + +
+
    + {btns.map(btn => +
  • + +
  • )} +
+
+
; + } + + /* @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() { + let logoutRef = React.createRef(); + + return [ + , +
+ + + +
, +
, +
+
+ ]; + + } + + render() { + return ( +
+ + {this.mainContent} + + + {this.nodesMenu()} + {this.miscButtons} + + +
+ ); + } +} diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 7d0dc2913..9c37e9000 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -2,7 +2,6 @@ import { observer } from "mobx-react"; import React = require("react"); import { observable, action, runInAction, reaction } from "mobx"; import "./PresentationView.scss"; -import "./Main.tsx"; import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; import { Doc, DocListCast, DocListCastAsync } from "../../new_fields/Doc"; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 35a9f34cf..4cc4ae6b6 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -14,12 +14,12 @@ import { Doc, DocListCast } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/RefField'; import { ContextMenu } from '../ContextMenu'; import { undoBatch } from '../../util/UndoManager'; -import { Main } from '../Main'; 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'; export interface TreeViewProps { @@ -52,7 +52,7 @@ class TreeView extends React.Component { @undoBatch openRight = async () => { if (this.props.document.dockingConfig) { - Main.Instance.openWorkspace(this.props.document); + MainView.Instance.openWorkspace(this.props.document); } else { CollectionDockingView.Instance.AddRightSplit(this.props.document); } @@ -140,7 +140,7 @@ class TreeView extends React.Component { 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 - ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => Main.Instance.openWorkspace(this.props.document)) }); + ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.props.document)) }); ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.document) }); ContextMenu.Instance.addItem({ description: "Open Fields", event: () => CollectionDockingView.Instance.AddRightSplit(Docs.KVPDocument(this.props.document, @@ -215,7 +215,7 @@ 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 - ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => Main.Instance.createNewWorkspace()) }); + 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)) }); diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index 4cac09dee..d9b07aac6 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -3,184 +3,186 @@ import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { observer } from 'mobx-react'; - -// configure({ -// enforceActions: "observed" -// }); - -// @observer -// class FieldViewer extends React.Component<{ field: BasicField }> { -// render() { -// return {JSON.stringify(this.props.field.Data)} ({this.props.field.Id}); -// } -// } - -// @observer -// class KeyViewer extends React.Component<{ field: Key }> { -// render() { -// return this.props.field.Name; -// } -// } - -// @observer -// class ListViewer extends React.Component<{ field: ListField }>{ -// @observable -// expanded = false; - -// render() { -// let content; -// if (this.expanded) { -// content = ( -//
-// {this.props.field.Data.map(field => )} -//
-// ); -// } else { -// content = <>[...] ({this.props.field.Id}); -// } -// return ( -//
-// -// {content} -//
-// ); -// } -// } - -// @observer -// class DocumentViewer extends React.Component<{ field: Document }> { -// private keyMap: ObservableMap = new ObservableMap; - -// private disposer?: Lambda; - -// componentDidMount() { -// let f = () => { -// Array.from(this.props.field._proxies.keys()).forEach(id => { -// if (!this.keyMap.has(id)) { -// Server.GetField(id, (field) => { -// if (field && field instanceof Key) { -// this.keyMap.set(id, field); -// } -// }); -// } -// }); -// }; -// this.disposer = this.props.field._proxies.observe(f); -// f(); -// } - -// componentWillUnmount() { -// if (this.disposer) { -// this.disposer(); -// } -// } - -// render() { -// let fields = Array.from(this.props.field._proxies.entries()).map(kv => { -// let key = this.keyMap.get(kv[0]); -// return ( -//
-// ({key ? key.Name : kv[0]}): -// -//
-// ); -// }); -// return ( -//
-// Document ({this.props.field.Id}) -//
-// {fields} -//
-//
-// ); -// } -// } - -// @observer -// class DebugViewer extends React.Component<{ fieldId: string }> { -// @observable -// private field?: Field; - -// @observable -// private error?: string; - -// constructor(props: { fieldId: string }) { -// super(props); -// this.update(); -// } - -// update() { -// Server.GetField(this.props.fieldId, action((field: Opt) => { -// this.field = field; -// if (!field) { -// this.error = `Field with id ${this.props.fieldId} not found`; -// } -// })); - -// } - -// render() { -// let content; -// if (this.field) { -// // content = this.field.ToJson(); -// if (this.field instanceof ListField) { -// content = (); -// } else if (this.field instanceof Document) { -// content = (); -// } else if (this.field instanceof BasicField) { -// content = (); -// } else if (this.field instanceof Key) { -// content = (); -// } else { -// content = (Unrecognized field type); -// } -// } else if (this.error) { -// content = Field {this.props.fieldId} not found ; -// } else { -// content = Field loading: {this.props.fieldId}; -// } -// return content; -// } -// } - -// @observer -// class Viewer extends React.Component { -// @observable -// private idToAdd: string = ''; - -// @observable -// private ids: string[] = []; - -// @action -// inputOnChange = (e: React.ChangeEvent) => { -// this.idToAdd = e.target.value; -// } - -// @action -// onKeyPress = (e: React.KeyboardEvent) => { -// if (e.key === "Enter") { -// this.ids.push(this.idToAdd); -// this.idToAdd = ""; -// } -// } - -// render() { -// return ( -// <> -// -//
-// {this.ids.map(id => )} -//
-// -// ); -// } -// } - -// ReactDOM.render(( -//
-// -//
), -// document.getElementById('root') -// ); \ No newline at end of file +import { CurrentUserUtils } from '../server/authentication/models/current_user_utils'; +import { RouteStore } from '../server/RouteStore'; +import { emptyFunction } from '../Utils'; +import { Docs } from '../client/documents/Documents'; +import { SetupDrag } from '../client/util/DragManager'; +import { Transform } from '../client/util/Transform'; +import { UndoManager } from '../client/util/UndoManager'; +import { PresentationView } from '../client/views/PresentationView'; +import { CollectionDockingView } from '../client/views/collections/CollectionDockingView'; +import { ContextMenu } from '../client/views/ContextMenu'; +import { DocumentDecorations } from '../client/views/DocumentDecorations'; +import { InkingControl } from '../client/views/InkingControl'; +import { MainOverlayTextBox } from '../client/views/MainOverlayTextBox'; +import { DocumentView } from '../client/views/nodes/DocumentView'; +import { PreviewCursor } from '../client/views/PreviewCursor'; +import { SearchBox } from '../client/views/SearchBox'; +import { SelectionManager } from '../client/util/SelectionManager'; +import { Doc, Field, FieldResult } from '../new_fields/Doc'; +import { Cast } from '../new_fields/Types'; +import { DocServer } from '../client/DocServer'; +import { listSpec } from '../new_fields/Schema'; +import { Id } from '../new_fields/RefField'; +import { HistoryUtil } from '../client/util/History'; +import { List } from '../new_fields/List'; +import { URLField } from '../new_fields/URLField'; + +CurrentUserUtils; +RouteStore; +emptyFunction; +Docs; +SetupDrag; +Transform; +UndoManager; +PresentationView; +CollectionDockingView; +ContextMenu; +DocumentDecorations; +InkingControl; +MainOverlayTextBox; +DocumentView; +PreviewCursor; +SearchBox; +SelectionManager; +Doc; +Cast; +DocServer; +listSpec; +Id; +HistoryUtil; + +configure({ + enforceActions: "observed" +}); + +@observer +class ListViewer extends React.Component<{ field: List }>{ + @observable + expanded = false; + + render() { + let content; + if (this.expanded) { + content = ( +
+ {this.props.field.map((field, index) => )} +
+ ); + } else { + content = <>[...]; + } + return ( +
+ + {content} +
+ ); + } +} + +@observer +class DocumentViewer extends React.Component<{ field: Doc }> { + @observable + expanded = false; + render() { + let content; + if (this.expanded) { + const keys = Object.keys(this.props.field); + let fields = keys.map(key => { + return ( +
+ ({key}): + +
+ ); + }); + content = ( +
+ Document ({this.props.field[Id]}) +
+ {fields} +
+
+ ); + } else { + content = <>[...] ({this.props.field[Id]}); + } + return ( +
+ + {content} +
+ ); + } +} + +@observer +class DebugViewer extends React.Component<{ field: FieldResult }> { + + render() { + let content; + const field = this.props.field; + if (field instanceof List) { + content = (); + } else if (field instanceof Doc) { + content = (); + } else if (typeof field === "string") { + content =

"{field}"

; + } else if (typeof field === "number" || typeof field === "boolean") { + content =

{field}

; + } else if (field instanceof URLField) { + content =

{field.url.href}

; + } else { + content =

Unrecognized field type

; + } + return content; + } +} + +@observer +class Viewer extends React.Component { + @observable + private idToAdd: string = ''; + + @observable + private fields: Field[] = []; + + @action + inputOnChange = (e: React.ChangeEvent) => { + this.idToAdd = e.target.value; + } + + @action + onKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + DocServer.GetRefField(this.idToAdd).then(action((field: any) => { + if (field !== undefined) { + this.fields.push(field); + } + })); + this.idToAdd = ""; + } + } + + render() { + return ( + <> + +
+ {this.fields.map((field, index) => )} +
+ + ); + } +} + +ReactDOM.render(( +
+ +
), + document.getElementById('root') +); \ No newline at end of file -- cgit v1.2.3-70-g09d2 From ffecdb309695ac9030626346b21013bcbf2e7731 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 17:06:18 -0400 Subject: server debugging --- src/client/views/collections/CollectionBaseView.tsx | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 31bdf213e..8687442a5 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -39,6 +39,9 @@ export class CollectionBaseView extends React.Component { get collectionViewType(): CollectionViewType | undefined { let Document = this.props.Document; let viewField = Cast(Document.viewType, "number"); + if (viewField === CollectionViewType.Freeform) { + return CollectionViewType.Tree; + } if (viewField !== undefined) { return viewField; } else { -- cgit v1.2.3-70-g09d2 From 5b4ffd962d7f89a40edcb3409b5904a752f13fbb Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 17:16:30 -0400 Subject: More debugging --- src/client/views/collections/CollectionBaseView.tsx | 4 ++++ src/client/views/collections/CollectionView.tsx | 1 + 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 8687442a5..73eb1fbbc 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, + RealFreeform } export interface CollectionRenderProps { @@ -42,6 +43,9 @@ export class CollectionBaseView extends React.Component { if (viewField === CollectionViewType.Freeform) { return CollectionViewType.Tree; } + if (viewField === CollectionViewType.RealFreeform) { + return CollectionViewType.Freeform; + } if (viewField !== undefined) { return viewField; } else { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 3d9b4990a..33427a991 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -41,6 +41,7 @@ export class CollectionView extends React.Component { 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: "project-diagram" }); + ContextMenu.Instance.addItem({ description: "Freeform2", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.RealFreeform), icon: "project-diagram" }); ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema), icon: "project-diagram" }); ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); } -- 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') 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 8b647aec9184f92364d396d755f4b32bd47af67c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 17:33:26 -0400 Subject: more debugging --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 264c89d67..63c090d84 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -138,7 +138,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let y = this.Document.panY || 0; let docs = this.childDocs || []; let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); - if (!this.isAnnotationOverlay) { + if (false && !this.isAnnotationOverlay) { let minx = docs.length ? NumCast(docs[0].x) : 0; let maxx = docs.length ? NumCast(docs[0].width) + minx : minx; let miny = docs.length ? NumCast(docs[0].y) : 0; -- 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') 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 130b5c55f954a011e91355c79ade4b9f91bd84e9 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 18:17:39 -0400 Subject: clamped scale and reverted safe mode --- src/client/views/collections/CollectionBaseView.tsx | 14 +++++++------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 73eb1fbbc..2da8c4e40 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -16,7 +16,7 @@ export enum CollectionViewType { Schema, Docking, Tree, - RealFreeform + // RealFreeform } export interface CollectionRenderProps { @@ -40,12 +40,12 @@ export class CollectionBaseView extends React.Component { get collectionViewType(): CollectionViewType | undefined { let Document = this.props.Document; let viewField = Cast(Document.viewType, "number"); - if (viewField === CollectionViewType.Freeform) { - return CollectionViewType.Tree; - } - if (viewField === CollectionViewType.RealFreeform) { - return CollectionViewType.Freeform; - } + // if (viewField === CollectionViewType.Freeform) { + // return CollectionViewType.Tree; + // } + // if (viewField === CollectionViewType.RealFreeform) { + // return CollectionViewType.Freeform; + // } if (viewField !== undefined) { return viewField; } else { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 264c89d67..956a5668a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -211,7 +211,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let [x, y] = this.getTransform().transformPoint(e.clientX, e.clientY); let localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y); - let safeScale = Math.abs(localTransform.Scale); + let safeScale = Math.max(0.002, localTransform.Scale); this.props.Document.scale = Math.abs(safeScale); this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale); e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From 3be734d7bca7276e173a9c50a1163c697143bb64 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 18 May 2019 19:28:42 -0400 Subject: Clamped scale of collections --- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 956a5668a..33521528f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -211,7 +211,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let [x, y] = this.getTransform().transformPoint(e.clientX, e.clientY); let localTransform = this.getLocalTransform().inverse().scaleAbout(deltaScale, x, y); - let safeScale = Math.max(0.002, localTransform.Scale); + let safeScale = Math.min(Math.max(0.15, localTransform.Scale), 40); this.props.Document.scale = Math.abs(safeScale); this.setPan(-localTransform.TranslateX / safeScale, -localTransform.TranslateY / safeScale); e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From ff3ef22630ad9c32b4ed1b0872bbc8b5753761eb Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 18 May 2019 23:16:36 -0400 Subject: fixed zoomBasis issues with wrapping, text size, and normalizing outlines. --- src/client/views/DocumentDecorations.tsx | 34 ++++++++++------------ .../views/collections/CollectionBaseView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 ++--- 3 files changed, 21 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index d440ed898..5ec090f05 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -431,31 +431,29 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.SelectedDocuments().forEach(element => { const rect = element.ContentDiv ? element.ContentDiv.getBoundingClientRect() : new DOMRect(); - if (rect.width !== 0) { + if (rect.width !== 0 && (dX != 0 || dY != 0 || dW != 0 || dH != 0)) { let doc = PositionDocument(element.props.Document); - let width = FieldValue(doc.width, 0); - let nwidth = FieldValue(doc.nativeWidth, 0); - let nheight = FieldValue(doc.nativeHeight, 0); - let height = FieldValue(doc.height, nwidth ? nheight / nwidth * width : 0); - let x = FieldValue(doc.x, 0); - let y = FieldValue(doc.y, 0); + let nwidth = doc.nativeWidth || 0; + let nheight = doc.nativeHeight || 0; + let zoomBasis = NumCast(doc.zoomBasis, 1); + let width = (doc.width || 0) / zoomBasis; + let height = (doc.height || (nheight / nwidth * width)) / zoomBasis; let scale = width / rect.width; let actualdW = Math.max(width + (dW * scale), 20); let actualdH = Math.max(height + (dH * scale), 20); - x += dX * (actualdW - width); - y += dY * (actualdH - height); - doc.x = x; - doc.y = y; - var nativeWidth = FieldValue(doc.nativeWidth, 0); - var nativeHeight = FieldValue(doc.nativeHeight, 0); - if (nativeWidth > 0 && nativeHeight > 0) { + doc.x = (doc.x || 0) + dX * (actualdW - width); + doc.y = (doc.y || 0) + dY * (actualdH - height); + if (nwidth > 0 && nheight > 0) { if (Math.abs(dW) > Math.abs(dH)) { - actualdH = nativeHeight / nativeWidth * actualdW; + doc.zoomBasis = zoomBasis * width / actualdW; } - else actualdW = nativeWidth / nativeHeight * actualdH; + else { + doc.zoomBasis = zoomBasis * height / actualdH; + } + } else { + doc.width = zoomBasis * actualdW; + doc.height = zoomBasis * actualdH; } - doc.width = actualdW; - doc.height = actualdH; } }); } diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 2da8c4e40..76270f2e8 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -114,7 +114,7 @@ export class CollectionBaseView extends React.Component { } // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument? if (!alreadyAdded && (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid)) { - let zoom = NumCast(this.props.Document.scale, 1); + let zoom = NumCast(this.props.Document.scale, 1) / this.props.ScreenToLocalTransform().Scale;// ; Doc.SetOnPrototype(doc, "zoomBasis", zoom); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 33521528f..b4b811da4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -140,14 +140,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); if (!this.isAnnotationOverlay) { let minx = docs.length ? NumCast(docs[0].x) : 0; - let maxx = docs.length ? NumCast(docs[0].width) + minx : minx; + let maxx = docs.length ? NumCast(docs[0].width) / NumCast(docs[0].zoomBasis) + minx : minx; let miny = docs.length ? NumCast(docs[0].y) : 0; - let maxy = docs.length ? NumCast(docs[0].height) + miny : miny; + let maxy = docs.length ? NumCast(docs[0].height) / NumCast(docs[0].zoomBasis) + miny : miny; let ranges = docs.filter(doc => doc).reduce((range, doc) => { let x = NumCast(doc.x); - let xe = x + NumCast(doc.width); + let xe = x + NumCast(doc.width) / NumCast(doc.zoomBasis); let y = NumCast(doc.y); - let ye = y + NumCast(doc.height); + let ye = y + NumCast(doc.height) / NumCast(doc.zoomBasis); return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]], [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]]; }, [[minx, maxx], [miny, maxy]]); -- cgit v1.2.3-70-g09d2 From a07655cb99cec80cb5d4e670b26e667999d259ec Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 19 May 2019 00:03:46 -0400 Subject: added switching of tabs w/o using the Shift key --- src/client/views/collections/CollectionDockingView.tsx | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 74f8ad242..5aa268e36 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -269,6 +269,10 @@ export class CollectionDockingView extends React.Component) => { if (f instanceof Doc) { DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y, @@ -339,6 +343,7 @@ export class CollectionDockingView extends React.Component Date: Sun, 19 May 2019 01:15:22 -0400 Subject: Reorganized some stuff to hopefully make circular imports harder --- src/client/documents/Documents.ts | 33 ++++++++++++++++++++++ src/client/views/nodes/DocumentView.tsx | 4 +-- src/client/views/nodes/FormattedTextBox.tsx | 3 +- src/debug/Viewer.tsx | 44 ----------------------------- src/new_fields/Doc.ts | 31 -------------------- 5 files changed, 37 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ed260d42e..0ebf6ff75 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -34,6 +34,7 @@ import { StrokeData, InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { schema } from "prosemirror-schema-basic"; +import { UndoManager } from "../util/UndoManager"; export interface DocumentOptions { x?: number; @@ -64,6 +65,38 @@ export interface DocumentOptions { } const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; +export namespace DocUtils { + export function MakeLink(source: Doc, target: Doc) { + let protoSrc = source.proto ? source.proto : source; + let protoTarg = target.proto ? target.proto : target; + UndoManager.RunInBatch(() => { + let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); + //let linkDoc = new Doc; + linkDoc.proto!.title = "-link name-"; + linkDoc.proto!.linkDescription = ""; + linkDoc.proto!.linkTags = "Default"; + + linkDoc.proto!.linkedTo = target; + linkDoc.proto!.linkedFrom = source; + + let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); + if (!linkedFrom) { + protoTarg.linkedFromDocs = linkedFrom = new List(); + } + linkedFrom.push(linkDoc); + + let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); + if (!linkedTo) { + protoSrc.linkedToDocs = linkedTo = new List(); + } + linkedTo.push(linkDoc); + return linkDoc; + }, "make link"); + } + + +} + export namespace Docs { let textProto: Doc; let histoProto: Doc; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 760e31b49..ccf09f999 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -11,7 +11,7 @@ import { BoolCast, Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { Docs } from "../../documents/Documents"; +import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, dropActionType } from "../../util/DragManager"; import { SearchUtil } from "../../util/SearchUtil"; @@ -264,7 +264,7 @@ export class DocumentView extends DocComponent(Docu dst.nativeHeight = src.nativeHeight; } else { - Doc.MakeLink(sourceDoc, destDoc); + DocUtils.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); } e.stopPropagation(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 98abde89e..d15813f9a 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -28,6 +28,7 @@ import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); +import { DocUtils } from '../../documents/Documents'; library.add(faEdit); library.add(faSmile); @@ -116,7 +117,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let sourceDoc = de.data.linkSourceDocument; let destDoc = this.props.Document; - Doc.MakeLink(sourceDoc, destDoc); + DocUtils.MakeLink(sourceDoc, destDoc); de.data.droppedDocuments.push(destDoc); e.stopPropagation(); } diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index d9b07aac6..720e1640a 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -3,56 +3,12 @@ import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { observer } from 'mobx-react'; -import { CurrentUserUtils } from '../server/authentication/models/current_user_utils'; -import { RouteStore } from '../server/RouteStore'; -import { emptyFunction } from '../Utils'; -import { Docs } from '../client/documents/Documents'; -import { SetupDrag } from '../client/util/DragManager'; -import { Transform } from '../client/util/Transform'; -import { UndoManager } from '../client/util/UndoManager'; -import { PresentationView } from '../client/views/PresentationView'; -import { CollectionDockingView } from '../client/views/collections/CollectionDockingView'; -import { ContextMenu } from '../client/views/ContextMenu'; -import { DocumentDecorations } from '../client/views/DocumentDecorations'; -import { InkingControl } from '../client/views/InkingControl'; -import { MainOverlayTextBox } from '../client/views/MainOverlayTextBox'; -import { DocumentView } from '../client/views/nodes/DocumentView'; -import { PreviewCursor } from '../client/views/PreviewCursor'; -import { SearchBox } from '../client/views/SearchBox'; -import { SelectionManager } from '../client/util/SelectionManager'; import { Doc, Field, FieldResult } from '../new_fields/Doc'; -import { Cast } from '../new_fields/Types'; import { DocServer } from '../client/DocServer'; -import { listSpec } from '../new_fields/Schema'; import { Id } from '../new_fields/RefField'; -import { HistoryUtil } from '../client/util/History'; import { List } from '../new_fields/List'; import { URLField } from '../new_fields/URLField'; -CurrentUserUtils; -RouteStore; -emptyFunction; -Docs; -SetupDrag; -Transform; -UndoManager; -PresentationView; -CollectionDockingView; -ContextMenu; -DocumentDecorations; -InkingControl; -MainOverlayTextBox; -DocumentView; -PreviewCursor; -SearchBox; -SelectionManager; -Doc; -Cast; -DocServer; -listSpec; -Id; -HistoryUtil; - configure({ enforceActions: "observed" }); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 020f764a2..c6fa31a99 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -4,12 +4,9 @@ import { autoObject, SerializationHelper, Deserializable } from "../client/util/ import { DocServer } from "../client/DocServer"; import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types"; -import { UndoManager, undoBatch } from "../client/util/UndoManager"; import { listSpec } from "./Schema"; -import { List } from "./List"; import { ObjectField, Parent, OnUpdate } from "./ObjectField"; import { RefField, FieldId, Id, HandleUpdate } from "./RefField"; -import { Docs } from "../client/documents/Documents"; export function IsField(field: any): field is Field { return (typeof field === "string") @@ -221,34 +218,6 @@ export namespace Doc { return copy; } - export function MakeLink(source: Doc, target: Doc) { - let protoSrc = source.proto ? source.proto : source; - let protoTarg = target.proto ? target.proto : target; - UndoManager.RunInBatch(() => { - let linkDoc = Docs.TextDocument({ width: 100, height: 30, borderRounding: -1 }); - //let linkDoc = new Doc; - linkDoc.proto!.title = "-link name-"; - linkDoc.proto!.linkDescription = ""; - linkDoc.proto!.linkTags = "Default"; - - linkDoc.proto!.linkedTo = target; - linkDoc.proto!.linkedFrom = source; - - let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); - if (!linkedFrom) { - protoTarg.linkedFromDocs = linkedFrom = new List(); - } - linkedFrom.push(linkDoc); - - let linkedTo = Cast(protoSrc.linkedToDocs, listSpec(Doc)); - if (!linkedTo) { - protoSrc.linkedToDocs = linkedTo = new List(); - } - linkedTo.push(linkDoc); - return linkDoc; - }, "make link"); - } - export function MakeDelegate(doc: Doc): Doc; export function MakeDelegate(doc: Opt): Opt; export function MakeDelegate(doc: Opt): Opt { -- cgit v1.2.3-70-g09d2 From 4667498586c19f7fff1e411f5842e8ae6903b39a Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 19 May 2019 02:18:50 -0400 Subject: Added readonly mode and fixed being able to set id of new workspace --- src/client/DocServer.ts | 25 ++++++++++++++++++---- src/client/documents/Documents.ts | 12 +++++------ src/client/views/MainView.tsx | 14 ++++++++---- .../views/collections/CollectionDockingView.tsx | 5 +++-- src/new_fields/Doc.ts | 8 +++---- 5 files changed, 44 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index e2f9b3601..f1b50d5a0 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,7 +1,7 @@ import * as OpenSocket from 'socket.io-client'; import { MessageStore } from "./../server/Message"; import { Opt } from '../new_fields/Doc'; -import { Utils } from '../Utils'; +import { Utils, emptyFunction } from '../Utils'; import { SerializationHelper } from './util/SerializationHelper'; import { RefField, HandleUpdate, Id } from '../new_fields/RefField'; @@ -10,6 +10,12 @@ export namespace DocServer { const _socket = OpenSocket(`${window.location.protocol}//${window.location.hostname}:4321`); const GUID: string = Utils.GenerateGuid(); + export function makeReadOnly() { + _CreateField = emptyFunction; + _UpdateField = emptyFunction; + _respondToUpdate = emptyFunction; + } + export function prepend(extension: string): string { return window.location.origin + extension; } @@ -88,21 +94,29 @@ export namespace DocServer { return map; } - export function UpdateField(id: string, diff: any) { + let _UpdateField = (id: string, diff: any) => { if (id === updatingId) { return; } Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); + }; + + export function UpdateField(id: string, diff: any) { + _UpdateField(id, diff); } - export function CreateField(field: RefField) { + let _CreateField = (field: RefField) => { _cache[field[Id]] = field; const initialState = SerializationHelper.Serialize(field); Utils.Emit(_socket, MessageStore.CreateField, initialState); + }; + + export function CreateField(field: RefField) { + _CreateField(field); } let updatingId: string | undefined; - function respondToUpdate(diff: any) { + let _respondToUpdate = (diff: any) => { const id = diff.id; if (id === undefined) { return; @@ -124,6 +138,9 @@ export namespace DocServer { } else { update(field); } + }; + function respondToUpdate(diff: any) { + _respondToUpdate(diff); } function connected() { diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0ebf6ff75..9d2f4d3cd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -142,8 +142,8 @@ export namespace Docs { deleg.data = value; return Doc.assign(deleg, options); } - function SetDelegateOptions(doc: Doc, options: DocumentOptions) { - const deleg = Doc.MakeDelegate(doc); + function SetDelegateOptions(doc: Doc, options: DocumentOptions, id?: string) { + const deleg = Doc.MakeDelegate(doc, id); return Doc.assign(deleg, options); } @@ -200,7 +200,7 @@ export namespace Docs { return audioProto; } - function CreateInstance(proto: Doc, data: Field, options: DocumentOptions) { + function CreateInstance(proto: Doc, data: Field, options: DocumentOptions, delegId?: string) { const { omit: protoProps, extract: delegateProps } = OmitKeys(options, delegateKeys); if (!("author" in protoProps)) { protoProps.author = CurrentUserUtils.email; @@ -210,7 +210,7 @@ export namespace Docs { } protoProps.isPrototype = true; - return SetDelegateOptions(SetInstanceOptions(proto, protoProps, data), delegateProps); + return SetDelegateOptions(SetInstanceOptions(proto, protoProps, data), delegateProps, delegId); } export function ImageDocument(url: string, options: DocumentOptions = {}) { @@ -293,8 +293,8 @@ 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 DockDocument(documents: Array, config: string, options: DocumentOptions) { - return CreateInstance(collProto, new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }); + export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { + return CreateInstance(collProto, new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } export function CaptionDocument(doc: Doc) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d0d77bbf4..c3f3a63de 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -57,10 +57,16 @@ export class MainView extends React.Component { MainView.Instance = this; // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); + if (window.location.search.includes("readonly")) { + DocServer.makeReadOnly(); + } if (window.location.pathname !== RouteStore.home) { - let pathname = window.location.pathname.split("/"); - if (pathname.length > 1 && pathname[pathname.length - 2] === 'doc') { - CurrentUserUtils.MainDocId = pathname[pathname.length - 1]; + let pathname = window.location.pathname.substr(1).split("/"); + if (pathname.length > 1) { + let type = pathname[0]; + if (type === "doc") { + CurrentUserUtils.MainDocId = pathname[1]; + } } } @@ -120,7 +126,7 @@ export class MainView extends React.Component { if (list) { let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, title: `WS collection ${list.length + 1}` }); var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, 600)] }] }; - let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }); + let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }, id); list.push(mainDoc); // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) setTimeout(() => { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 5aa268e36..eeec3eaf0 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -438,10 +438,11 @@ 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 (location === "onRight") { CollectionDockingView.Instance.AddRightSplit(doc); - else + } else { CollectionDockingView.Instance.AddTab(this._stack, doc); + } } get content() { if (!this._document) { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index c6fa31a99..02dd34cb4 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -218,13 +218,13 @@ export namespace Doc { return copy; } - export function MakeDelegate(doc: Doc): Doc; - export function MakeDelegate(doc: Opt): Opt; - export function MakeDelegate(doc: Opt): Opt { + export function MakeDelegate(doc: Doc, id?: string): Doc; + export function MakeDelegate(doc: Opt, id?: string): Opt; + export function MakeDelegate(doc: Opt, id?: string): Opt { if (!doc) { return undefined; } - const delegate = new Doc(); + const delegate = new Doc(id, true); delegate.proto = doc; return delegate; } -- cgit v1.2.3-70-g09d2 From 10d7773dccdc3cada5e7e34926de69b9f3631414 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 19 May 2019 02:43:08 -0400 Subject: Added safe mode --- src/client/views/MainView.tsx | 7 +++++++ src/client/views/collections/CollectionBaseView.tsx | 20 ++++++++++++-------- src/client/views/collections/CollectionView.tsx | 4 +++- 3 files changed, 22 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index c3f3a63de..bdd3e9650 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -31,6 +31,7 @@ import { DocServer } from '../DocServer'; import { listSpec } from '../../new_fields/Schema'; import { Id } from '../../new_fields/RefField'; import { HistoryUtil } from '../util/History'; +import { CollectionBaseView } from './collections/CollectionBaseView'; @observer @@ -60,6 +61,12 @@ export class MainView extends React.Component { if (window.location.search.includes("readonly")) { DocServer.makeReadOnly(); } + if (window.location.search.includes("safe")) { + if (!window.location.search.includes("nro")) { + DocServer.makeReadOnly(); + } + CollectionBaseView.SetSafeMode(true); + } if (window.location.pathname !== RouteStore.home) { let pathname = window.location.pathname.substr(1).split("/"); if (pathname.length > 1) { diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 76270f2e8..9d52ce6ff 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -1,4 +1,4 @@ -import { action, computed } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { ContextMenu } from '../ContextMenu'; @@ -16,7 +16,6 @@ export enum CollectionViewType { Schema, Docking, Tree, - // RealFreeform } export interface CollectionRenderProps { @@ -37,15 +36,20 @@ export interface CollectionViewProps extends FieldViewProps { @observer export class CollectionBaseView extends React.Component { + @observable private static _safeMode = false; + static InSafeMode() { return this._safeMode; } + static SetSafeMode(safeMode: boolean) { this._safeMode = safeMode; } get collectionViewType(): CollectionViewType | undefined { let Document = this.props.Document; let viewField = Cast(Document.viewType, "number"); - // if (viewField === CollectionViewType.Freeform) { - // return CollectionViewType.Tree; - // } - // if (viewField === CollectionViewType.RealFreeform) { - // return CollectionViewType.Freeform; - // } + if (CollectionBaseView._safeMode) { + if (viewField === CollectionViewType.Freeform) { + return CollectionViewType.Tree; + } + if (viewField === CollectionViewType.Invalid) { + return CollectionViewType.Freeform; + } + } if (viewField !== undefined) { return viewField; } else { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 33427a991..b9ffc11a2 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -41,7 +41,9 @@ export class CollectionView extends React.Component { 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: "project-diagram" }); - ContextMenu.Instance.addItem({ description: "Freeform2", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.RealFreeform), icon: "project-diagram" }); + 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: "project-diagram" }); ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree), icon: "tree" }); } -- cgit v1.2.3-70-g09d2 From 12796ace87581ffeac9d67fa5d7ebff8cecd1a52 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 19 May 2019 11:33:42 -0400 Subject: added opaque background for non-annotation collections. fixed marquee view when there's zoomBasis, fixed double-click opening to stopPropagation. got rid of RIGHT_BTN_DRAG stuff. --- .../views/collections/CollectionBaseView.tsx | 4 ++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 11 +++-------- .../collections/collectionFreeForm/MarqueeView.tsx | 23 ++++++++-------------- .../views/nodes/CollectionFreeFormDocumentView.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 5 +---- 5 files changed, 16 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 76270f2e8..54e76fd5e 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -89,7 +89,7 @@ export class CollectionBaseView extends React.Component { } return false; } - @computed get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } + @computed get isAnnotationOverlay() { return this.props.fieldKey === "annotations"; } @action.bound addDocument(doc: Doc, allowDuplicates: boolean = false): boolean { @@ -114,7 +114,7 @@ export class CollectionBaseView extends React.Component { } // set the ZoomBasis only if hasn't already been set -- bcz: maybe set/resetting the ZoomBasis should be a parameter to addDocument? if (!alreadyAdded && (this.collectionViewType === CollectionViewType.Freeform || this.collectionViewType === CollectionViewType.Invalid)) { - let zoom = NumCast(this.props.Document.scale, 1) / this.props.ScreenToLocalTransform().Scale;// ; + let zoom = NumCast(this.props.Document.scale, 1); Doc.SetOnPrototype(doc, "zoomBasis", zoom); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b4b811da4..9cb8443f4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -37,7 +37,6 @@ const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema) @observer export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { - public static RIGHT_BTN_DRAG = false; private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) private _lastX: number = 0; private _lastY: number = 0; @@ -46,8 +45,8 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed get nativeWidth() { return this.Document.nativeWidth || 0; } @computed get nativeHeight() { return this.Document.nativeHeight || 0; } + public get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } - private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } private panX = () => this.Document.panX || 0; private panY = () => this.Document.panY || 0; private zoomScaling = () => this.Document.scale || 1; @@ -66,7 +65,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return true; } private selectDocuments = (docs: Doc[]) => { - SelectionManager.DeselectAll; + SelectionManager.DeselectAll(); docs.map(doc => DocumentManager.Instance.getDocumentView(doc)).filter(dv => dv).map(dv => SelectionManager.SelectDoc(dv!, true)); } @@ -112,11 +111,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action onPointerDown = (e: React.PointerEvent): void => { - if ((CollectionFreeFormView.RIGHT_BTN_DRAG && - (((e.button === 2 && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) || - (e.button === 0 && e.altKey)) && this.props.active())) || - (!CollectionFreeFormView.RIGHT_BTN_DRAG && - ((e.button === 0 && !e.shiftKey && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1)) && this.props.active()))) { + if (e.button === 0 && !e.shiftKey && !e.altKey && (!this.isAnnotationOverlay || this.zoomScaling() !== 1) && this.props.active()) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d102c8af2..4587c2227 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -132,17 +132,18 @@ export class MarqueeView extends React.Component this._downY = this._lastY = e.pageY; this._commandExecuted = false; PreviewCursor.Visible = false; - if ((CollectionFreeFormView.RIGHT_BTN_DRAG && e.button === 0 && !e.altKey && !e.metaKey && this.props.container.props.active()) || - (!CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && this.props.container.props.active())) { + if (e.button === 2 || (e.button === 0 && e.altKey)) { + if (!this.props.container.props.active()) this.props.selectDocuments([this.props.container.props.Document]); document.addEventListener("pointermove", this.onPointerMove, true); document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); - // bcz: do we need this? it kills the context menu on the main collection + if (e.altKey) { + e.stopPropagation(); + e.preventDefault(); + } + // bcz: do we need this? it kills the context menu on the main collection if !altKey // e.stopPropagation(); } - if (e.altKey) { - e.preventDefault(); - } } @action @@ -248,6 +249,7 @@ export class MarqueeView extends React.Component panX: 0, panY: 0, borderRounding: e.key === "e" ? -1 : undefined, + backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white", scale: zoomBasis, width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, @@ -275,15 +277,6 @@ export class MarqueeView extends React.Component //this.props.addDocument(newCollection, false); summary.proto!.summarizedDocs = new List(selected); summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" - //summary.proto!.isButton = true; - //let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); - // selected.map(summarizedDoc => { - // let maxx = NumCast(summarizedDoc.x, undefined); - // let maxy = NumCast(summarizedDoc.y, undefined); - // let maxw = NumCast(summarizedDoc.width, undefined); - // let maxh = NumCast(summarizedDoc.height, undefined); - // summarizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); - // }); this.props.addLiveTextDocument(summary); }); } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7cb4c1dfe..8851e4b93 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -180,8 +180,9 @@ export class CollectionFreeFormDocumentView extends DocComponent { document.removeEventListener("pointerup", this.onPointerUp); - if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { + if (!(e as any).propagationIsStopped && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { this.props.addDocTab(this.props.Document, "inTab"); + (e as any).propagationIsStopped = true; } e.stopPropagation(); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 760e31b49..bb5daaf4e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -187,9 +187,6 @@ export class DocumentView extends DocComponent(Docu onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; this._downY = e.clientY; - if (CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && !this.isSelected()) { - return; - } this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0; if (e.shiftKey && e.buttons === 1) { CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e); @@ -207,7 +204,7 @@ export class DocumentView extends DocComponent(Docu if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - if (!e.altKey && !this.topMost && (!CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 1) || (CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 2)) { + if (!e.altKey && !this.topMost && e.buttons === 1) { this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitExpander); } } -- cgit v1.2.3-70-g09d2 From 01a223f2e6685506cc1e5db69e9062d5ff0d3246 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 19 May 2019 13:43:37 -0400 Subject: fixed dragging out tree view to drag out user document. fixed opening collections in a tab to show same layout as outside the tab. --- src/client/views/MainView.tsx | 3 ++- src/client/views/collections/CollectionDockingView.tsx | 16 ++++++++++++++-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 16 +++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index bdd3e9650..cdb105e21 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -214,7 +214,8 @@ export class MainView extends React.Component { let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" })); let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" })); - let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); + let addTreeNode = action(() => CurrentUserUtils.UserDocument); + //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" })); let addPDFNode = action(() => Docs.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" })); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index eeec3eaf0..06b262d79 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -20,6 +20,7 @@ import { SubCollectionViewProps } from "./CollectionSubView"; import React = require("react"); import { ParentDocSelector } from './ParentDocumentSelector'; import { DocumentManager } from '../../util/DocumentManager'; +import { CollectionViewType } from './CollectionBaseView'; @observer export class CollectionDockingView extends React.Component { @@ -431,10 +432,21 @@ export class DockedFrameRenderer extends React.Component { if (this._mainCont.current && this._mainCont.current.children) { let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current.children[0].firstChild as HTMLElement); scale = Utils.GetScreenTransform(this._mainCont.current).scale; - return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this.contentScaling()); + return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / scale); } return Transform.Identity(); } + get scaleToFitMultiplier() { + let docWidth = NumCast(this._document!.width); + let docHeight = NumCast(this._document!.height); + if (NumCast(this._document!.nativeWidth) || !docWidth || !this._panelWidth || !this._panelHeight) return 1; + if (StrCast(this._document!.layout).indexOf("Collection") === -1 || + NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1; + let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ? + this._panelHeight / docHeight : this._panelWidth / docWidth); + console.log("Scaling = " + scaling); + return scaling; + } get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } addDocTab = (doc: Doc, location: string) => { @@ -450,7 +462,7 @@ export class DockedFrameRenderer extends React.Component { } return (
+ style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px) scale(${this.scaleToFitMultiplier}, ${this.scaleToFitMultiplier})` }}> (); private _downX: number = 0; private _downY: number = 0; + private _doubleTap = false; + private _lastTap: number = 0; _bringToFrontDisposer?: IReactionDisposer; @computed get transform() { @@ -159,18 +161,16 @@ export class CollectionFreeFormDocumentView extends DocComponent { this._downX = e.clientX; this._downY = e.clientY; + this._doubleTap = false; if (e.button === 0 && e.altKey) { e.stopPropagation(); // prevents panning from happening on collection if shift is pressed after a document drag has started } // allow pointer down to go through otherwise so that marquees can be drawn starting over a document if (Date.now() - this._lastTap < 300) { if (e.buttons === 1) { - this._downX = e.clientX; - this._downY = e.clientY; document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); } @@ -180,14 +180,16 @@ export class CollectionFreeFormDocumentView extends DocComponent { document.removeEventListener("pointerup", this.onPointerUp); - if (!(e as any).propagationIsStopped && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { - this.props.addDocTab(this.props.Document, "inTab"); - (e as any).propagationIsStopped = true; + if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { + this._doubleTap = true; } - e.stopPropagation(); } onClick = async (e: React.MouseEvent) => { e.stopPropagation(); + if (this._doubleTap) { + this.props.addDocTab(this.props.Document, "inTab"); + SelectionManager.DeselectAll(); + } let altKey = e.altKey; if (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) { -- cgit v1.2.3-70-g09d2 From f53ba030a86bf3fc384ff3c00efcf3c1f0497b9b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 19 May 2019 18:10:53 -0400 Subject: cleaned up context menu icons. --- src/client/views/ContextMenu.scss | 3 ++- src/client/views/ContextMenu.tsx | 1 - src/client/views/ContextMenuItem.tsx | 3 +-- .../views/collections/CollectionDockingView.tsx | 1 - src/client/views/collections/CollectionView.tsx | 8 ++++--- src/client/views/nodes/DocumentView.tsx | 28 +++++++++++++--------- 6 files changed, 25 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 0a14c8ce7..b12ee3faa 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -48,7 +48,7 @@ border-style: none; border-color: $intermediate-color; // rgb(187, 186, 186); border-bottom-style: solid; - padding: 10px; + padding: 10px 0px 10px 0px; white-space: nowrap; font-size: 1vw; } @@ -67,4 +67,5 @@ .icon-background { background-color: #DDDDDD; + margin-right: 2px; } \ No newline at end of file diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 9143c012e..84c17a642 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -90,7 +90,6 @@ export class ContextMenu extends React.Component {
- diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index ed583942a..b9239dac9 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -37,8 +37,7 @@ export class ContextMenuItem extends React.Component { return (
- - {this.props.icon ? : null} + {this.props.icon ? : }
{this.props.description}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 06b262d79..483209f86 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -444,7 +444,6 @@ export class DockedFrameRenderer extends React.Component { NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1; let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ? this._panelHeight / docHeight : this._panelWidth / docWidth); - console.log("Scaling = " + scaling); return scaling; } get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b9ffc11a2..59c763be8 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faProjectDiagram, faSquare, faTh, faTree } from '@fortawesome/free-solid-svg-icons'; +import { faProjectDiagram, faSquare, faTh, faTree, faSignature, faThList } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; import { Id } from '../../../new_fields/RefField'; @@ -18,6 +18,8 @@ library.add(faTh); library.add(faTree); library.add(faSquare); library.add(faProjectDiagram); +library.add(faSignature); +library.add(faThList); @observer export class CollectionView extends React.Component { @@ -40,11 +42,11 @@ export class CollectionView extends React.Component { 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: "project-diagram" }); + ContextMenu.Instance.addItem({ 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: "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" }); } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 38f3db19f..9e86b411e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons'; import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; @@ -19,7 +19,6 @@ import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; @@ -39,6 +38,13 @@ library.add(faLayerGroup); library.add(faAlignCenter); library.add(faCaretSquareRight); library.add(faSquare); +library.add(faConciergeBell); +library.add(faFolder); +library.add(faMapPin); +library.add(faLink); +library.add(faFingerprint); +library.add(faCrosshairs); +library.add(faDesktop); const linkSchema = createSchema({ title: "string", @@ -308,21 +314,21 @@ export class DocumentView extends DocComponent(Docu e.preventDefault(); const cm = ContextMenu.Instance; - cm.addItem({ description: "Full Screen", event: this.fullScreenClicked, icon: "expand-arrows-alt" }); - cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeButton, icon: "expand-arrows-alt" }); - cm.addItem({ description: "Fields", event: this.fieldsClicked, icon: "layer-group" }); - cm.addItem({ description: "Center", event: () => this.props.focus(this.props.Document), icon: "align-center" }); - cm.addItem({ description: "Open Tab", event: () => this.props.addDocTab && this.props.addDocTab(this.props.Document, "inTab"), icon: "expand-arrows-alt" }); + 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" }); + 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.makeButton, 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, {})); - }, icon: "expand-arrows-alt" + }, icon: "search" }); - cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "expand-arrows-alt" }); - cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "expand-arrows-alt" }); - cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "expand-arrows-alt" }); + cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" }); + cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); + cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); if (!this.topMost) { // DocumentViews should stop propagation of this event -- cgit v1.2.3-70-g09d2 From c103acbe8f8df919e87f9a18872a94eb8bc1a001 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 19 May 2019 19:55:26 -0400 Subject: fixed some small things with presentation and icon --- src/client/views/DocumentDecorations.tsx | 6 +++--- src/client/views/MainView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 3 ++- src/client/views/nodes/IconBox.tsx | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 5ec090f05..319e91337 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -276,16 +276,16 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let doc = selected[0].props.Document; let iconDoc = Docs.IconDocument(layoutString); iconDoc.isButton = true; - iconDoc.proto!.title = selected.length > 1 ? "ICONset" : "ICON" + StrCast(doc.title); + iconDoc.proto!.title = selected.length > 1 ? "-multiple-.icon" : StrCast(doc.title) + ".icon"; iconDoc.labelField = selected.length > 1 ? undefined : this._fieldKey; - iconDoc.proto![this._fieldKey] = selected.length > 1 ? "collection" : undefined; + //iconDoc.proto![this._fieldKey] = selected.length > 1 ? "collection" : undefined; iconDoc.proto!.isMinimized = false; iconDoc.width = Number(MINIMIZED_ICON_SIZE); iconDoc.height = Number(MINIMIZED_ICON_SIZE); iconDoc.x = NumCast(doc.x); iconDoc.y = NumCast(doc.y) - 24; iconDoc.maximizedDocs = new List(selected.map(s => s.props.Document.proto!)); - doc.minimizedDoc = iconDoc; + selected.length === 1 && (doc.minimizedDoc = iconDoc); selected[0].props.addDocument && selected[0].props.addDocument(iconDoc, false); return iconDoc; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cdb105e21..400562f12 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -47,7 +47,7 @@ export class MainView extends React.Component { private set mainContainer(doc: Opt) { if (doc) { if (!("presentationView" in doc)) { - doc.presentationView = new Doc(); + doc.presentationView = Docs.TreeDocument([], { title: "Presentation" }); } CurrentUserUtils.UserDocument.activeWorkspace = doc; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9e86b411e..5f218fd1f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -128,7 +128,8 @@ export class DocumentView extends DocComponent(Docu }); } // bcz: kind of ugly .. setup a reaction to update the title of a summary document's target (maximizedDocs) whenver the summary doc's title changes - this._reactionDisposer = reaction(() => [this.props.Document.maximizedDocs, this.props.Document.summaryDoc, this.props.Document.summaryDoc instanceof Doc ? this.props.Document.summaryDoc.title : ""], + this._reactionDisposer = reaction(() => [DocListCast(this.props.Document.maximizedDocs).map(md => md.title), + this.props.Document.summaryDoc, this.props.Document.summaryDoc instanceof Doc ? this.props.Document.summaryDoc.title : ""], () => { let maxDoc = DocListCast(this.props.Document.maximizedDocs); if (maxDoc.length === 1 && StrCast(this.props.Document.title).startsWith("-") && StrCast(this.props.Document.layout).indexOf("IconBox") !== -1) { diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index b42eb44a5..00021bc78 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -12,7 +12,6 @@ import { IconField } from "../../../new_fields/IconField"; import { ContextMenu } from "../ContextMenu"; import Measure from "react-measure"; import { MINIMIZED_ICON_SIZE } from "../../views/globalCssVariables.scss"; -import { listSpec } from "../../../new_fields/Schema"; library.add(faCaretUp); -- cgit v1.2.3-70-g09d2 From b789ac4cc3fe013139825f811d7574e1d305c2cc Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 19 May 2019 20:30:50 -0400 Subject: Added link follow behavior --- src/client/util/DocumentManager.ts | 7 ++++--- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index d06af6dd5..be448098a 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -115,7 +115,7 @@ export class DocumentManager { } @undoBatch - public jumpToDocument = async (docDelegate: Doc, makeCopy: boolean = true): Promise => { + public jumpToDocument = async (docDelegate: Doc, makeCopy: boolean = true, dockFunc?: (doc: Doc) => void): Promise => { let doc = docDelegate.proto ? docDelegate.proto : docDelegate; const page = NumCast(doc.page, undefined); const contextDoc = await Cast(doc.annotationOn, Doc); @@ -128,14 +128,15 @@ export class DocumentManager { docView.props.focus(docView.props.Document); } else { if (!contextDoc) { - CollectionDockingView.Instance.AddRightSplit(docDelegate ? (makeCopy ? Doc.MakeCopy(docDelegate) : docDelegate) : Doc.MakeDelegate(doc)); + const actualDoc = docDelegate ? (makeCopy ? Doc.MakeCopy(docDelegate) : docDelegate) : Doc.MakeDelegate(doc); + (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); } else { let contextView = DocumentManager.Instance.getDocumentView(contextDoc); if (contextView) { contextDoc.panTransformType = "Ease"; contextView.props.focus(contextDoc); } else { - CollectionDockingView.Instance.AddRightSplit(contextDoc); + (dockFunc || CollectionDockingView.Instance.AddRightSplit)(contextDoc); } } } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index fa44ec9f3..5bff08280 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -239,7 +239,8 @@ export class CollectionFreeFormDocumentView extends DocComponent this.props.addDocTab(document, maxLocation)); } } } -- cgit v1.2.3-70-g09d2 From af2346983eae1145167b70faf96a9aec0ca82427 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 00:09:47 -0400 Subject: Fixed a bunch of demo bugs Moved Field Symbols to separate file Editing is mostly working in debug viewer --- deploy/debug/viewer.html | 1 + src/client/DocServer.ts | 3 +- src/client/northstar/dash-fields/HistogramField.ts | 7 +- src/client/northstar/dash-nodes/HistogramBox.tsx | 2 +- src/client/util/DocumentManager.ts | 2 +- src/client/util/SearchUtil.ts | 2 +- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/util/type_decls.d | 128 +++++++-------------- src/client/views/EditableView.tsx | 10 +- src/client/views/MainView.tsx | 2 +- src/client/views/PresentationView.tsx | 2 +- src/client/views/SearchBox.tsx | 2 +- .../views/collections/CollectionBaseView.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 14 ++- src/client/views/collections/CollectionPDFView.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 2 +- .../views/collections/CollectionVideoView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 2 +- .../views/collections/ParentDocumentSelector.tsx | 2 +- .../CollectionFreeFormLinksView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 3 - src/client/views/nodes/DocumentView.tsx | 4 +- src/client/views/nodes/KeyValueBox.tsx | 4 +- src/client/views/nodes/KeyValuePair.tsx | 4 +- src/client/views/nodes/LinkMenu.tsx | 2 +- src/debug/Viewer.tsx | 53 +++++++-- src/new_fields/CursorField.ts | 7 +- src/new_fields/DateField.ts | 7 +- src/new_fields/Doc.ts | 43 ++++--- src/new_fields/FieldSymbols.ts | 10 ++ src/new_fields/HtmlField.ts | 7 +- src/new_fields/IconField.ts | 7 +- src/new_fields/InkField.ts | 7 +- src/new_fields/List.ts | 16 ++- src/new_fields/ObjectField.ts | 7 +- src/new_fields/Proxy.ts | 9 +- src/new_fields/RefField.ts | 5 +- src/new_fields/RichTextField.ts | 7 +- src/new_fields/URLField.ts | 9 +- src/new_fields/util.ts | 7 +- 42 files changed, 240 insertions(+), 173 deletions(-) create mode 100644 src/new_fields/FieldSymbols.ts (limited to 'src') diff --git a/deploy/debug/viewer.html b/deploy/debug/viewer.html index 3785a6602..8c265ccb8 100644 --- a/deploy/debug/viewer.html +++ b/deploy/debug/viewer.html @@ -3,6 +3,7 @@ Document Debugger + diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index f1b50d5a0..cbcf751ee 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -3,7 +3,8 @@ import { MessageStore } from "./../server/Message"; import { Opt } from '../new_fields/Doc'; import { Utils, emptyFunction } from '../Utils'; import { SerializationHelper } from './util/SerializationHelper'; -import { RefField, HandleUpdate, Id } from '../new_fields/RefField'; +import { RefField } from '../new_fields/RefField'; +import { Id, HandleUpdate } from '../new_fields/FieldSymbols'; export namespace DocServer { const _cache: { [id: string]: RefField | Promise> } = {}; diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index 1ee2189b9..31040a474 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -3,10 +3,11 @@ import { custom, serializable } from "serializr"; import { ColumnAttributeModel } from "../../../client/northstar/core/attribute/AttributeModel"; import { AttributeTransformationModel } from "../../../client/northstar/core/attribute/AttributeTransformationModel"; import { HistogramOperation } from "../../../client/northstar/operations/HistogramOperation"; -import { ObjectField, Copy } from "../../../new_fields/ObjectField"; +import { ObjectField } from "../../../new_fields/ObjectField"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { OmitKeys } from "../../../Utils"; import { Deserializable } from "../../util/SerializationHelper"; +import { Copy, ToScriptString } from "../../../new_fields/FieldSymbols"; function serialize(field: HistogramField) { let obj = OmitKeys(field, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; @@ -55,4 +56,8 @@ export class HistogramField extends ObjectField { let z = this.HistoOp.Copy; return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } + + [ToScriptString]() { + return "invalid"; + } } \ No newline at end of file diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index eb1ad69b7..a9646ed31 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -19,7 +19,7 @@ import { HistogramLabelPrimitives } from "./HistogramLabelPrimitives"; import { StyleConstants } from "../utils/StyleContants"; import { Cast } from "../../../new_fields/Types"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; -import { Id } from "../../../new_fields/RefField"; +import { Id } from "../../../new_fields/FieldSymbols"; @observer diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index be448098a..a5e768dcf 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -5,10 +5,10 @@ import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; import { undoBatch } from './UndoManager'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { Id } from '../../new_fields/RefField'; import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; +import { Id } from '../../new_fields/FieldSymbols'; export class DocumentManager { diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 4ccff0d1b..e8eb70837 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -1,7 +1,7 @@ import * as rp from 'request-promise'; import { DocServer } from '../DocServer'; import { Doc } from '../../new_fields/Doc'; -import { Id } from '../../new_fields/RefField'; +import { Id } from '../../new_fields/FieldSymbols'; export namespace SearchUtil { export function Search(query: string, returnDocs: true): Promise; diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 4d40d09b2..a1f80120f 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -22,12 +22,12 @@ import { throwStatement } from "babel-types"; import { View } from "@react-pdf/renderer"; import { DragManager } from "./DragManager"; import { Doc, Opt, Field } from "../../new_fields/Doc"; -import { Id } from "../../new_fields/RefField"; import { Utils } from "../northstar/utils/Utils"; import { DocServer } from "../DocServer"; import { CollectionFreeFormDocumentView } from "../views/nodes/CollectionFreeFormDocumentView"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { DocumentManager } from "./DocumentManager"; +import { Id } from "../../new_fields/FieldSymbols"; const SVG = "http://www.w3.org/2000/svg"; diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d index 47c3481b2..51114d0e2 100644 --- a/src/client/util/type_decls.d +++ b/src/client/util/type_decls.d @@ -119,104 +119,54 @@ interface URL { username: string; toJSON(): string; } +interface PromiseLike { + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): PromiseLike; +} +interface Promise { + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; +} -declare type FieldId = string; +declare const Update: unique symbol; +declare const Self: unique symbol; +declare const SelfProxy: unique symbol; +declare const HandleUpdate: unique symbol; +declare const Id: unique symbol; +declare const OnUpdate: unique symbol; +declare const Parent: unique symbol; +declare const Copy: unique symbol; +declare const ToScriptString: unique symbol; -declare abstract class Field { - Id: FieldId; - abstract ToScriptString(): string; - abstract TrySetValue(value: any): boolean; - abstract GetValue(): any; - abstract Copy(): Field; -} +declare abstract class RefField { + readonly [Id]: FieldId; + + constructor(id?: FieldId); + protected [HandleUpdate]?(diff: any): void; -declare abstract class BasicField extends Field { - constructor(data: T); - Data: T; - TrySetValue(value: any): boolean; - GetValue(): any; + abstract [ToScriptString](): string; } -declare class TextField extends BasicField{ - constructor(); - constructor(data: string); - ToScriptString(): string; - Copy(): Field; -} -declare class ImageField extends BasicField{ - constructor(); - constructor(data: URL); - ToScriptString(): string; - Copy(): Field; -} -declare class HtmlField extends BasicField{ - constructor(); - constructor(data: string); - ToScriptString(): string; - Copy(): Field; -} -declare class NumberField extends BasicField{ - constructor(); - constructor(data: number); - ToScriptString(): string; - Copy(): Field; -} -declare class WebField extends BasicField{ - constructor(); - constructor(data: URL); - ToScriptString(): string; - Copy(): Field; -} -declare class ListField extends BasicField{ - constructor(); - constructor(data: T[]); - ToScriptString(): string; - Copy(): Field; -} -declare class Key extends Field { - constructor(name:string); - Name: string; - TrySetValue(value: any): boolean; - GetValue(): any; - Copy(): Field; - ToScriptString(): string; -} -declare type FIELD_WAITING = null; -declare type Opt = T | undefined; -declare type FieldValue = Opt | FIELD_WAITING; -// @ts-ignore -declare class Document extends Field { - TrySetValue(value: any): boolean; - GetValue(): any; - Copy(): Field; - ToScriptString(): string; +declare abstract class ObjectField { + protected [OnUpdate](diff?: any): void; + private [Parent]?: RefField | ObjectField; + abstract [Copy](): ObjectField; - Width(): number; - Height(): number; - Scale(): number; - Title: string; + abstract [ToScriptString](): string; +} +declare type FieldId = string; - Get(key: Key): FieldValue; - GetAsync(key: Key, callback: (field: Field) => void): boolean; - GetOrCreateAsync(key: Key, ctor: { new(): T }, callback: (field: T) => void): void; - GetT(key: Key, ctor: { new(): T }): FieldValue; - GetOrCreate(key: Key, ctor: { new(): T }): T; - GetData(key: Key, ctor: { new(): U }, defaultVal: T): T; - GetHtml(key: Key, defaultVal: string): string; - GetNumber(key: Key, defaultVal: number): number; - GetText(key: Key, defaultVal: string): string; - GetList(key: Key, defaultVal: T[]): T[]; - Set(key: Key, field: Field | undefined): void; - SetData(key: Key, value: T, ctor: { new(): U }): void; - SetText(key: Key, value: string): void; - SetNumber(key: Key, value: number): void; - GetPrototype(): FieldValue; - GetAllPrototypes(): Document[]; - MakeDelegate(): Document; +declare type Field = number | string | boolean | ObjectField | RefField; + +declare type Opt = T | undefined; +declare class Doc extends RefField { + [key: string]: Field | undefined; + [ToScriptString](): string; } -declare const KeyStore: { - [name: string]: Key; +declare class ListImpl extends ObjectField { + [index: number]: T | (T extends RefField ? Promise : never); + [ToScriptString](): string; + [Copy](): ObjectField; } // @ts-ignore diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 78143ccda..c946d68e1 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -22,7 +22,7 @@ export interface EditableProps { * The contents to render when not editing */ contents: any; - height: number; + height?: number; display?: string; oneLine?: boolean; } @@ -53,6 +53,12 @@ export class EditableView extends React.Component { } } + @action + onClick = (e: React.MouseEvent) => { + this.editing = true; + e.stopPropagation(); + } + render() { if (this.editing) { return this.editing = false)} @@ -60,7 +66,7 @@ export class EditableView extends React.Component { } else { return (
this.editing = true)} > + onClick={this.onClick} > {this.props.contents}
); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 400562f12..9edbba997 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -29,7 +29,7 @@ import { FieldResult, Field, Doc, Opt } from '../../new_fields/Doc'; import { Cast, FieldValue, StrCast } from '../../new_fields/Types'; import { DocServer } from '../DocServer'; import { listSpec } from '../../new_fields/Schema'; -import { Id } from '../../new_fields/RefField'; +import { Id } from '../../new_fields/FieldSymbols'; import { HistoryUtil } from '../util/History'; import { CollectionBaseView } from './collections/CollectionBaseView'; diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 9c37e9000..ce679aa0a 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -7,7 +7,7 @@ import { Utils } from "../../Utils"; import { Doc, DocListCast, DocListCastAsync } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; import { Cast, NumCast, FieldValue, PromiseValue, StrCast } from "../../new_fields/Types"; -import { Id } from "../../new_fields/RefField"; +import { Id } from "../../new_fields/FieldSymbols"; import { List } from "../../new_fields/List"; import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 6e64e1af1..8efd8d266 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -16,7 +16,7 @@ import { isString } from 'util'; import { constant } from 'async'; import { DocServer } from '../DocServer'; import { Doc } from '../../new_fields/Doc'; -import { Id } from '../../new_fields/RefField'; +import { Id } from '../../new_fields/FieldSymbols'; import { DocumentManager } from '../util/DocumentManager'; import { SetupDrag } from '../util/DragManager'; import { Docs } from '../documents/Documents'; diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 84ffbac36..5686ccfef 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -7,8 +7,8 @@ import { Cast, FieldValue, PromiseValue, NumCast } from '../../../new_fields/Typ import { Doc, FieldResult, Opt, DocListCast } from '../../../new_fields/Doc'; import { listSpec } from '../../../new_fields/Schema'; import { List } from '../../../new_fields/List'; -import { Id } from '../../../new_fields/RefField'; import { SelectionManager } from '../../util/SelectionManager'; +import { Id } from '../../../new_fields/FieldSymbols'; export enum CollectionViewType { Invalid, diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 483209f86..e904358a9 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -6,7 +6,7 @@ import * as ReactDOM from 'react-dom'; import Measure from "react-measure"; import * as GoldenLayout from "../../../client/goldenLayout"; import { Doc, Field, Opt, DocListCast } from "../../../new_fields/Doc"; -import { FieldId, Id } from "../../../new_fields/RefField"; +import { FieldId } from "../../../new_fields/RefField"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, returnTrue, Utils } from "../../../Utils"; @@ -21,6 +21,7 @@ import React = require("react"); import { ParentDocSelector } from './ParentDocumentSelector'; import { DocumentManager } from '../../util/DocumentManager'; import { CollectionViewType } from './CollectionBaseView'; +import { Id } from '../../../new_fields/FieldSymbols'; @observer export class CollectionDockingView extends React.Component { @@ -75,7 +76,7 @@ export class CollectionDockingView extends React.Component { let retVal = false; if (this._goldenLayout.root.contentItems[0].isRow) { retVal = Array.from(this._goldenLayout.root.contentItems[0].contentItems).some((child: any) => { @@ -118,7 +119,7 @@ export class CollectionDockingView extends React.Component { let docs = Cast(this.props.Document.data, listSpec(Doc)); if (docs) { docs.push(document); @@ -155,7 +156,7 @@ export class CollectionDockingView extends React.Component { let docs = Cast(this.props.Document.data, listSpec(Doc)); if (docs) { docs.push(document); @@ -412,10 +413,11 @@ export class DockedFrameRenderer extends React.Component { @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; - _stack: any; + get _stack(): any { + return (this.props as any).glContainer.parent.parent; + } constructor(props: any) { super(props); - this._stack = (this.props as any).glContainer.parent.parent; DocServer.GetRefField(this.props.documentId).then(action((f: Opt) => this._document = f as Doc)); } diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index a6614da21..5e51437a4 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -8,7 +8,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView"; import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView"; import { emptyFunction } from "../../../Utils"; import { NumCast } from "../../../new_fields/Types"; -import { Id } from "../../../new_fields/RefField"; +import { Id } from "../../../new_fields/FieldSymbols"; @observer diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f15da41ff..b25b48339 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -23,7 +23,7 @@ import { Opt, Field, Doc, DocListCastAsync, DocListCast } from "../../../new_fie import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; -import { Id } from "../../../new_fields/RefField"; +import { Id } from "../../../new_fields/FieldSymbols"; import { Gateway } from "../../northstar/manager/Gateway"; import { Docs } from "../../documents/Documents"; import { ContextMenu } from "../ContextMenu"; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 72fa69cb1..8ad495762 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -11,7 +11,7 @@ import React = require("react"); import { Document, listSpec } from '../../../new_fields/Schema'; import { Cast, StrCast, BoolCast, FieldValue } from '../../../new_fields/Types'; import { Doc, DocListCast } from '../../../new_fields/Doc'; -import { Id } from '../../../new_fields/RefField'; +import { Id } from '../../../new_fields/FieldSymbols'; import { ContextMenu } from '../ContextMenu'; import { undoBatch } from '../../util/UndoManager'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index 9ab959f3c..27f23a1a8 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -7,7 +7,7 @@ import "./CollectionVideoView.scss"; import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import { emptyFunction } from "../../../Utils"; -import { Id } from "../../../new_fields/RefField"; +import { Id } from "../../../new_fields/FieldSymbols"; import { VideoBox } from "../nodes/VideoBox"; import { NumCast } from "../../../new_fields/Types"; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 59c763be8..bfdef8e8c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -2,7 +2,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faProjectDiagram, faSquare, faTh, faTree, faSignature, faThList } from '@fortawesome/free-solid-svg-icons'; import { observer } from "mobx-react"; import * as React from 'react'; -import { Id } from '../../../new_fields/RefField'; +import { Id } from '../../../new_fields/FieldSymbols'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../ContextMenu"; diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 52f7914f3..4d07c31a7 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -3,7 +3,7 @@ import './ParentDocumentSelector.scss'; import { Doc } from "../../../new_fields/Doc"; import { observer } from "mobx-react"; import { observable, action, runInAction } from "mobx"; -import { Id } from "../../../new_fields/RefField"; +import { Id } from "../../../new_fields/FieldSymbols"; import { SearchUtil } from "../../util/SearchUtil"; import { CollectionDockingView } from "./CollectionDockingView"; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index d5ce4e1e7..e1ff715d1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -11,7 +11,7 @@ import { Doc, DocListCastAsync, DocListCast } from "../../../../new_fields/Doc"; import { Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types"; import { listSpec } from "../../../../new_fields/Schema"; import { List } from "../../../../new_fields/List"; -import { Id } from "../../../../new_fields/RefField"; +import { Id } from "../../../../new_fields/FieldSymbols"; @observer export class CollectionFreeFormLinksView extends React.Component { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9cb8443f4..ee6f4821f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -22,9 +22,9 @@ import { createSchema, makeInterface, listSpec } from "../../../../new_fields/Sc import { Doc, WidthSym, HeightSym } from "../../../../new_fields/Doc"; import { FieldValue, Cast, NumCast, BoolCast } from "../../../../new_fields/Types"; import { pageSchema } from "../../nodes/ImageBox"; -import { Id } from "../../../../new_fields/RefField"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { HistoryUtil } from "../../../util/History"; +import { Id } from "../../../../new_fields/FieldSymbols"; export const panZoomSchema = createSchema({ panX: "number", diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 4587c2227..2029b91e5 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -17,9 +17,6 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { ImageField } from "../../../../new_fields/URLField"; import { Template, Templates } from "../../Templates"; -import { Gateway } from "../../../northstar/manager/Gateway"; -import { DocServer } from "../../../DocServer"; -import { Id } from "../../../../new_fields/RefField"; interface MarqueeViewProps { getContainerTransform: () => Transform; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5f218fd1f..87c88f57c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -4,8 +4,7 @@ import { action, computed, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; -import { Copy, ObjectField } from "../../../new_fields/ObjectField"; -import { Id } from "../../../new_fields/RefField"; +import { ObjectField } from "../../../new_fields/ObjectField"; import { createSchema, makeInterface } from "../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, StrCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; @@ -29,6 +28,7 @@ import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); +import { Id, Copy } from '../../../new_fields/FieldSymbols'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 86437a6c1..8cb576786 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -8,7 +8,7 @@ import "./KeyValueBox.scss"; import { KeyValuePair } from "./KeyValuePair"; import React = require("react"); import { NumCast, Cast, FieldValue } from "../../../new_fields/Types"; -import { Doc, IsField } from "../../../new_fields/Doc"; +import { Doc, Field } from "../../../new_fields/Doc"; @observer export class KeyValueBox extends React.Component { @@ -41,7 +41,7 @@ export class KeyValueBox extends React.Component { let res = script.run(); if (!res.success) return; const field = res.result; - if (IsField(field)) { + if (Field.IsField(field)) { realDoc[this._keyInput] = field; } this._keyInput = ""; diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 4f7919f50..7a88985c0 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -9,7 +9,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./KeyValueBox.scss"; import "./KeyValuePair.scss"; import React = require("react"); -import { Doc, Opt, IsField } from '../../../new_fields/Doc'; +import { Doc, Opt, Field } from '../../../new_fields/Doc'; import { FieldValue } from '../../../new_fields/Types'; // Represents one row in a key value plane @@ -75,7 +75,7 @@ export class KeyValuePair extends React.Component { let res = script.run(); if (!res.success) return false; const field = res.result; - if (IsField(field)) { + if (Field.IsField(field)) { props.Document[props.fieldKey] = field; return true; } diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 4cf798249..3f09d6214 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -7,7 +7,7 @@ import './LinkMenu.scss'; import React = require("react"); import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Cast, FieldValue, StrCast } from "../../../new_fields/Types"; -import { Id } from "../../../new_fields/RefField"; +import { Id } from "../../../new_fields/FieldSymbols"; interface Props { docView: DocumentView; diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index 720e1640a..4314e2132 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -3,11 +3,27 @@ import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { observer } from 'mobx-react'; -import { Doc, Field, FieldResult } from '../new_fields/Doc'; +import { Doc, Field, FieldResult, Opt } from '../new_fields/Doc'; import { DocServer } from '../client/DocServer'; -import { Id } from '../new_fields/RefField'; +import { Id } from '../new_fields/FieldSymbols'; import { List } from '../new_fields/List'; import { URLField } from '../new_fields/URLField'; +import { EditableView } from '../client/views/EditableView'; +import { CompileScript } from '../client/util/Scripting'; + +function applyToDoc(doc: { [index: string]: FieldResult }, key: string, scriptString: string): boolean; +function applyToDoc(doc: { [index: number]: FieldResult }, key: number, scriptString: string): boolean; +function applyToDoc(doc: any, key: string | number, scriptString: string): boolean { + let script = CompileScript(scriptString, { addReturn: true, params: { this: doc instanceof Doc ? Doc.name : List.name } }); + if (!script.compiled) { + return false; + } + const res = script.run({ this: doc }); + if (!res.success) return false; + if (!Field.IsField(res.result)) return false; + doc[key] = res.result; + return true; +} configure({ enforceActions: "observed" @@ -18,12 +34,18 @@ class ListViewer extends React.Component<{ field: List }>{ @observable expanded = false; + @action + onClick = (e: React.MouseEvent) => { + this.expanded = !this.expanded; + e.stopPropagation(); + } + render() { let content; if (this.expanded) { content = (
- {this.props.field.map((field, index) => )} + {this.props.field.map((field, index) => applyToDoc(this.props.field, index, value)} />)}
); } else { @@ -31,7 +53,7 @@ class ListViewer extends React.Component<{ field: List }>{ } return (
- + {content}
); @@ -42,6 +64,13 @@ class ListViewer extends React.Component<{ field: List }>{ class DocumentViewer extends React.Component<{ field: Doc }> { @observable expanded = false; + + @action + onClick = (e: React.MouseEvent) => { + this.expanded = !this.expanded; + e.stopPropagation(); + } + render() { let content; if (this.expanded) { @@ -50,7 +79,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { return (
({key}): - + applyToDoc(this.props.field, key, value)}>
); }); @@ -67,7 +96,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { } return (
- + {content}
); @@ -75,7 +104,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { } @observer -class DebugViewer extends React.Component<{ field: FieldResult }> { +class DebugViewer extends React.Component<{ field: FieldResult, setValue(value: string): boolean }> { render() { let content; @@ -90,10 +119,14 @@ class DebugViewer extends React.Component<{ field: FieldResult }> { content =

{field}

; } else if (field instanceof URLField) { content =

{field.url.href}

; + } else if (field instanceof Promise) { + return

Field loading

; } else { - content =

Unrecognized field type

; + return

Unrecognized field type

; } - return content; + + return Field.toScriptString(field)} SetValue={this.props.setValue} + contents={content}>; } } @@ -129,7 +162,7 @@ class Viewer extends React.Component { onChange={this.inputOnChange} onKeyDown={this.onKeyPress} />
- {this.fields.map((field, index) => )} + {this.fields.map((field, index) => false}>)}
); diff --git a/src/new_fields/CursorField.ts b/src/new_fields/CursorField.ts index fc144222c..1be1ec3e0 100644 --- a/src/new_fields/CursorField.ts +++ b/src/new_fields/CursorField.ts @@ -1,7 +1,8 @@ -import { ObjectField, Copy, OnUpdate } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; import { observable } from "mobx"; import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, createSimpleSchema, object } from "serializr"; +import { OnUpdate, ToScriptString, Copy } from "./FieldSymbols"; export type CursorPosition = { x: number, @@ -52,4 +53,8 @@ export default class CursorField extends ObjectField { [Copy]() { return new CursorField(this.data); } + + [ToScriptString]() { + return "invalid"; + } } \ No newline at end of file diff --git a/src/new_fields/DateField.ts b/src/new_fields/DateField.ts index c0a79f267..fc8abb9d9 100644 --- a/src/new_fields/DateField.ts +++ b/src/new_fields/DateField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, date } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("date") export class DateField extends ObjectField { @@ -15,4 +16,8 @@ export class DateField extends ObjectField { [Copy]() { return new DateField(this.date); } + + [ToScriptString]() { + return `new DateField(new Date(${this.date.toISOString()}))`; + } } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 02dd34cb4..f4514c33e 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -5,27 +5,33 @@ import { DocServer } from "../client/DocServer"; import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types"; import { listSpec } from "./Schema"; -import { ObjectField, Parent, OnUpdate } from "./ObjectField"; -import { RefField, FieldId, Id, HandleUpdate } from "./RefField"; - -export function IsField(field: any): field is Field { - return (typeof field === "string") - || (typeof field === "number") - || (typeof field === "boolean") - || (field instanceof ObjectField) - || (field instanceof RefField); +import { ObjectField } from "./ObjectField"; +import { RefField, FieldId } from "./RefField"; +import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; + +export namespace Field { + export function toScriptString(field: Field): string { + if (typeof field === "string") { + return `"${field}"`; + } else if (typeof field === "number" || typeof field === "boolean") { + return String(field); + } else { + return field[ToScriptString](); + } + } + export function IsField(field: any): field is Field { + return (typeof field === "string") + || (typeof field === "number") + || (typeof field === "boolean") + || (field instanceof ObjectField) + || (field instanceof RefField); + } } export type Field = number | string | boolean | ObjectField | RefField; export type Opt = T | undefined; export type FieldWaiting = T extends undefined ? never : Promise; export type FieldResult = Opt | FieldWaiting>; -export const Update = Symbol("Update"); -export const Self = Symbol("Self"); -export const SelfProxy = Symbol("SelfProxy"); -export const WidthSym = Symbol("Width"); -export const HeightSym = Symbol("Height"); - /** * Cast any field to either a List of Docs or undefined if the given field isn't a List of Docs. * If a default value is given, that will be returned instead of undefined. @@ -43,6 +49,9 @@ export function DocListCast(field: FieldResult): Doc[] { return Cast(field, listSpec(Doc), []).filter(d => d instanceof Doc) as Doc[]; } +export const WidthSym = Symbol("Width"); +export const HeightSym = Symbol("Height"); + @Deserializable("doc").withFields(["id"]) export class Doc extends RefField { constructor(id?: FieldId, forceSave?: boolean) { @@ -102,6 +111,10 @@ export class Doc extends RefField { public [WidthSym] = () => NumCast(this[SelfProxy].width); // bcz: is this the right way to access width/height? it didn't work with : this.width public [HeightSym] = () => NumCast(this[SelfProxy].height); + [ToScriptString]() { + return "invalid"; + } + public [HandleUpdate](diff: any) { console.log(diff); const set = diff.$set; diff --git a/src/new_fields/FieldSymbols.ts b/src/new_fields/FieldSymbols.ts new file mode 100644 index 000000000..a436dcf2b --- /dev/null +++ b/src/new_fields/FieldSymbols.ts @@ -0,0 +1,10 @@ + +export const Update = Symbol("Update"); +export const Self = Symbol("Self"); +export const SelfProxy = Symbol("SelfProxy"); +export const HandleUpdate = Symbol("HandleUpdate"); +export const Id = Symbol("Id"); +export const OnUpdate = Symbol("OnUpdate"); +export const Parent = Symbol("Parent"); +export const Copy = Symbol("Copy"); +export const ToScriptString = Symbol("Copy"); \ No newline at end of file diff --git a/src/new_fields/HtmlField.ts b/src/new_fields/HtmlField.ts index d998746bb..f952acff9 100644 --- a/src/new_fields/HtmlField.ts +++ b/src/new_fields/HtmlField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, primitive } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("html") export class HtmlField extends ObjectField { @@ -15,4 +16,8 @@ export class HtmlField extends ObjectField { [Copy]() { return new HtmlField(this.html); } + + [ToScriptString]() { + return "invalid"; + } } diff --git a/src/new_fields/IconField.ts b/src/new_fields/IconField.ts index 1a928389d..62b2cd254 100644 --- a/src/new_fields/IconField.ts +++ b/src/new_fields/IconField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, primitive } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("icon") export class IconField extends ObjectField { @@ -15,4 +16,8 @@ export class IconField extends ObjectField { [Copy]() { return new IconField(this.icon); } + + [ToScriptString]() { + return "invalid"; + } } diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts index 2d75f8a19..4e3b7abe0 100644 --- a/src/new_fields/InkField.ts +++ b/src/new_fields/InkField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, custom, createSimpleSchema, list, object, map } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; import { deepCopy } from "../Utils"; export enum InkTool { @@ -40,4 +41,8 @@ export class InkField extends ObjectField { [Copy]() { return new InkField(deepCopy(this.inkData)); } + + [ToScriptString]() { + return "invalid"; + } } diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index 70e36f911..f1e4c4721 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -1,11 +1,12 @@ import { Deserializable, autoObject } from "../client/util/SerializationHelper"; -import { Field, Update, Self, FieldResult, SelfProxy } from "./Doc"; +import { Field } from "./Doc"; import { setter, getter, deleteProperty, updateFunction } from "./util"; import { serializable, alias, list } from "serializr"; import { observable, action } from "mobx"; -import { ObjectField, OnUpdate, Copy, Parent } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; import { RefField } from "./RefField"; import { ProxyField } from "./Proxy"; +import { Self, Update, Parent, OnUpdate, SelfProxy, ToScriptString, Copy } from "./FieldSymbols"; const listHandlers: any = { /// Mutator methods @@ -225,7 +226,7 @@ type StoredType = T extends RefField ? ProxyField : T; @Deserializable("list") class ListImpl extends ObjectField { - constructor(fields: T[] = []) { + constructor(fields?: T[]) { super(); const list = new Proxy(this, { set: setter, @@ -244,7 +245,9 @@ class ListImpl extends ObjectField { defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); }, }); this[SelfProxy] = list; - (list as any).push(...fields); + if (fields) { + (list as any).push(...fields); + } return list; } @@ -284,6 +287,11 @@ class ListImpl extends ObjectField { private [Self] = this; private [SelfProxy]: any; + + [ToScriptString]() { + return "invalid"; + // return `new List([${(this as any).map((field => Field.toScriptString(field))}])`; + } } export type List = ListImpl & (T | (T extends RefField ? Promise : never))[]; export const List: { new (fields?: T[]): List } = ListImpl as any; \ No newline at end of file diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts index 51768c6db..5f4a6f8fb 100644 --- a/src/new_fields/ObjectField.ts +++ b/src/new_fields/ObjectField.ts @@ -1,14 +1,13 @@ import { Doc } from "./Doc"; import { RefField } from "./RefField"; - -export const OnUpdate = Symbol("OnUpdate"); -export const Parent = Symbol("Parent"); -export const Copy = Symbol("Copy"); +import { OnUpdate, Parent, Copy, ToScriptString } from "./FieldSymbols"; export abstract class ObjectField { protected [OnUpdate](diff?: any) { } private [Parent]?: RefField | ObjectField; abstract [Copy](): ObjectField; + + abstract [ToScriptString](): string; } export namespace ObjectField { diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index fd99ae1c0..130ec066e 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -3,8 +3,9 @@ import { FieldWaiting } from "./Doc"; import { primitive, serializable } from "serializr"; import { observable, action } from "mobx"; import { DocServer } from "../client/DocServer"; -import { RefField, Id } from "./RefField"; -import { ObjectField, Copy } from "./ObjectField"; +import { RefField } from "./RefField"; +import { ObjectField } from "./ObjectField"; +import { Id, Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("proxy") export class ProxyField extends ObjectField { @@ -26,6 +27,10 @@ export class ProxyField extends ObjectField { return new ProxyField(this.fieldId); } + [ToScriptString]() { + return "invalid"; + } + @serializable(primitive()) readonly fieldId: string = ""; diff --git a/src/new_fields/RefField.ts b/src/new_fields/RefField.ts index 202c65f21..75ce4287f 100644 --- a/src/new_fields/RefField.ts +++ b/src/new_fields/RefField.ts @@ -1,9 +1,8 @@ import { serializable, primitive, alias } from "serializr"; import { Utils } from "../Utils"; +import { Id, HandleUpdate, ToScriptString } from "./FieldSymbols"; export type FieldId = string; -export const HandleUpdate = Symbol("HandleUpdate"); -export const Id = Symbol("Id"); export abstract class RefField { @serializable(alias("id", primitive())) private __id: FieldId; @@ -15,4 +14,6 @@ export abstract class RefField { } protected [HandleUpdate]?(diff: any): void; + + abstract [ToScriptString](): string; } diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index eb30e76de..89d077a47 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -1,6 +1,7 @@ -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; import { serializable } from "serializr"; import { Deserializable } from "../client/util/SerializationHelper"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("RichTextField") export class RichTextField extends ObjectField { @@ -15,4 +16,8 @@ export class RichTextField extends ObjectField { [Copy]() { return new RichTextField(this.Data); } + + [ToScriptString]() { + return "invalid"; + } } \ No newline at end of file diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts index d00a95a16..a6f8f1cc5 100644 --- a/src/new_fields/URLField.ts +++ b/src/new_fields/URLField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, custom } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { ToScriptString, Copy } from "./FieldSymbols"; function url() { return custom( @@ -13,7 +14,7 @@ function url() { ); } -export class URLField extends ObjectField { +export abstract class URLField extends ObjectField { @serializable(url()) readonly url: URL; @@ -22,6 +23,10 @@ export class URLField extends ObjectField { this.url = url; } + [ToScriptString]() { + return `new ${this.constructor.name}(new URL(${this.url.href}))`; + } + [Copy](): this { return new (this.constructor as any)(this.url); } diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index d94994a07..65a37a0d1 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -1,11 +1,12 @@ import { UndoManager } from "../client/util/UndoManager"; -import { Update, Doc, Field } from "./Doc"; +import { Doc, Field } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField } from "./Proxy"; import { FieldValue } from "./Types"; -import { RefField, Id } from "./RefField"; -import { ObjectField, Parent, OnUpdate } from "./ObjectField"; +import { RefField } from "./RefField"; +import { ObjectField } from "./ObjectField"; import { action } from "mobx"; +import { Parent, OnUpdate, Update, Id } from "./FieldSymbols"; export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { if (SerializationHelper.IsSerializing()) { -- 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') 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 dedcb16fd7ae8211ca60bdf3630a0532525d3646 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 04:36:53 -0400 Subject: Fixed deleting fields --- src/new_fields/util.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 65a37a0d1..2b304c373 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -38,7 +38,11 @@ export const setter = action(function (target: any, prop: string | symbol | numb delete curValue[Parent]; delete curValue[OnUpdate]; } - target.__fields[prop] = value; + if (value === undefined) { + delete target.__fields[prop]; + } else { + target.__fields[prop] = value; + } target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } }); UndoManager.AddEvent({ redo: () => receiver[prop] = value, -- cgit v1.2.3-70-g09d2 From f62f4d92001e775b7248b7e786de733225e107b5 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 11:15:43 -0400 Subject: added switching to low res version based on display size. fixed marqueeing on full size images, fixed bug with kvp pane and image sizing, --- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 38 ++++++++++++++++++---- 3 files changed, 33 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 9edbba997..6169466bc 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -131,7 +131,7 @@ export class MainView extends React.Component { createNewWorkspace = async (id?: string) => { const list = Cast(CurrentUserUtils.UserDocument.data, listSpec(Doc)); if (list) { - let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, title: `WS collection ${list.length + 1}` }); + let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, width: this.pwidth * .7, height: this.pheight, title: `WS collection ${list.length + 1}` }); var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, 600)] }] }; let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }, id); list.push(mainDoc); diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index e904358a9..9721bf804 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -434,7 +434,7 @@ export class DockedFrameRenderer extends React.Component { if (this._mainCont.current && this._mainCont.current.children) { let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current.children[0].firstChild as HTMLElement); scale = Utils.GetScreenTransform(this._mainCont.current).scale; - return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / scale); + return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale); } return Transform.Identity(); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 828ac9bc8..0a479cf41 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -17,6 +17,13 @@ import { ImageField } from '../../../new_fields/URLField'; import { List } from '../../../new_fields/List'; import { InkingControl } from '../InkingControl'; import { Doc } from '../../../new_fields/Doc'; +import { faImage } from '@fortawesome/free-solid-svg-icons'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +var path = require('path'); + +library.add(faImage); + export const pageSchema = createSchema({ curPage: "number" @@ -41,7 +48,7 @@ export class ImageBox extends DocComponent(ImageD onLoad = (target: any) => { var h = this._imgRef.current!.naturalHeight; var w = this._imgRef.current!.naturalWidth; - if (this._photoIndex === 0 && (this.props as any).id !== "isExpander") { + if (this._photoIndex === 0 && (this.props as any).id !== "isExpander" && (!this.Document.nativeHeight || !this.Document.nativeWidth)) { Doc.SetOnPrototype(this.Document, "nativeHeight", FieldValue(this.Document.nativeWidth, 0) * h / w); this.Document.height = FieldValue(this.Document.width, 0) * h / w; } @@ -155,14 +162,30 @@ export class ImageBox extends DocComponent(ImageD ); } + @observable _smallImageMissing = false; render() { - let field = this.Document[this.props.fieldKey]; - let paths: string[] = ["http://www.cs.brown.edu/~bcz/face.gif"]; - if (field instanceof ImageField) paths = [field.url.href]; - else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); - let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50); - let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; + let transform = this.props.ScreenToLocalTransform().inverse(); + let pw = Object.keys(this.props.PanelWidth).length === 0 ? this.props.PanelWidth() : (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50; + var [sptX, sptY] = transform.transformPoint(0, 0); + let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); + let w = bptX - sptX; + let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx + let nativeWidth = FieldValue(this.Document.nativeWidth, pw); + let paths: string[] = ["http://www.cs.brown.edu/~bcz/noImage.png"]; + if (w > 20) { + if (w < 100 && !this._smallImageMissing) { + let field = this.Document[this.props.fieldKey]; + if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_s" + path.extname(field.url.href))]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => + (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_s" + path.extname((p as ImageField).url.href))); + } else { + let field = this.Document[this.props.fieldKey]; + if (field instanceof ImageField) paths = [field.url.href]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); + } + } + let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; return (
(ImageD style={{ objectFit: (this._photoIndex === 0 ? undefined : "contain") }} width={nativeWidth} ref={this._imgRef} + onError={action(() => this._smallImageMissing = true)} onLoad={this.onLoad} /> {paths.length > 1 ? this.dots(paths) : (null)} {this.lightbox(paths)} -- cgit v1.2.3-70-g09d2 From baa57bae05df83c37e4573b7afb92948fc6e910b Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 11:24:54 -0400 Subject: using all image sizes now. --- src/client/views/nodes/ImageBox.tsx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 0a479cf41..b4aae3646 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -163,6 +163,9 @@ export class ImageBox extends DocComponent(ImageD } @observable _smallImageMissing = false; + @observable _mediumImageMissing = false; + @observable _largeImageMissing = false; + _curImageSize = ""; render() { let transform = this.props.ScreenToLocalTransform().inverse(); let pw = Object.keys(this.props.PanelWidth).length === 0 ? this.props.PanelWidth() : (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50; @@ -175,14 +178,23 @@ export class ImageBox extends DocComponent(ImageD let paths: string[] = ["http://www.cs.brown.edu/~bcz/noImage.png"]; if (w > 20) { if (w < 100 && !this._smallImageMissing) { + this._curImageSize = "small"; let field = this.Document[this.props.fieldKey]; if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_s" + path.extname(field.url.href))]; else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_s" + path.extname((p as ImageField).url.href))); - } else { + } else if (w < 600 && !this._mediumImageMissing) { + this._curImageSize = "medium"; let field = this.Document[this.props.fieldKey]; - if (field instanceof ImageField) paths = [field.url.href]; - else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); + if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_m" + path.extname(field.url.href))]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => + (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_m" + path.extname((p as ImageField).url.href))); + } else if (!this._largeImageMissing) { + this._curImageSize = "large"; + let field = this.Document[this.props.fieldKey]; + if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_l" + path.extname(field.url.href))]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => + (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_l" + path.extname((p as ImageField).url.href))); } } let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; @@ -194,7 +206,11 @@ export class ImageBox extends DocComponent(ImageD style={{ objectFit: (this._photoIndex === 0 ? undefined : "contain") }} width={nativeWidth} ref={this._imgRef} - onError={action(() => this._smallImageMissing = true)} + onError={action(() => { + if (this._curImageSize === "small") this._smallImageMissing = true; + if (this._curImageSize === "medium") this._mediumImageMissing = true; + if (this._curImageSize === "large") this._largeImageMissing = true; + })} onLoad={this.onLoad} /> {paths.length > 1 ? this.dots(paths) : (null)} {this.lightbox(paths)} -- cgit v1.2.3-70-g09d2 From e5d71fc1362c77f076c10187625c74fe294669aa Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 12:20:57 -0400 Subject: fixes to caching. lower quality Summary images. --- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 57 +++++++++++----------- 2 files changed, 30 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 2029b91e5..6ea230aab 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -257,7 +257,7 @@ export class MarqueeView extends React.Component if (e.key === "s" || e.key === "p") { - htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 1 }).then((dataUrl) => { + htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { selected.map(d => { this.props.removeDocument(d); d.x = NumCast(d.x) - bounds.left - bounds.width / 2; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index b4aae3646..29a99e53c 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -162,13 +162,25 @@ export class ImageBox extends DocComponent(ImageD ); } - @observable _smallImageMissing = false; - @observable _mediumImageMissing = false; - @observable _largeImageMissing = false; - _curImageSize = ""; + choosePath(url: URL) { + if (url.protocol === "data") + return url.href; + let ext = path.extname(url.href); + return url.href.replace(ext, this._curSuffix + ext); + } + + @observable _smallRetryCount = 1; + @observable _mediumRetryCount = 1; + @observable _largeRetryCount = 1; + @action retryPath = () => { + if (this._curSuffix === "_s") this._smallRetryCount++; + if (this._curSuffix === "_m") this._mediumRetryCount++; + if (this._curSuffix === "_l") this._largeRetryCount++; + } + _curSuffix = ""; render() { let transform = this.props.ScreenToLocalTransform().inverse(); - let pw = Object.keys(this.props.PanelWidth).length === 0 ? this.props.PanelWidth() : (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50; + let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; var [sptX, sptY] = transform.transformPoint(0, 0); let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); let w = bptX - sptX; @@ -176,40 +188,29 @@ export class ImageBox extends DocComponent(ImageD let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx let nativeWidth = FieldValue(this.Document.nativeWidth, pw); let paths: string[] = ["http://www.cs.brown.edu/~bcz/noImage.png"]; + this._curSuffix = ""; if (w > 20) { - if (w < 100 && !this._smallImageMissing) { - this._curImageSize = "small"; - let field = this.Document[this.props.fieldKey]; - if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_s" + path.extname(field.url.href))]; - else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => - (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_s" + path.extname((p as ImageField).url.href))); - } else if (w < 600 && !this._mediumImageMissing) { - this._curImageSize = "medium"; - let field = this.Document[this.props.fieldKey]; - if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_m" + path.extname(field.url.href))]; - else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => - (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_m" + path.extname((p as ImageField).url.href))); - } else if (!this._largeImageMissing) { - this._curImageSize = "large"; - let field = this.Document[this.props.fieldKey]; - if (field instanceof ImageField) paths = [field.url.href.replace(path.extname(field.url.href), "_l" + path.extname(field.url.href))]; - else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => - (p as ImageField).url.href.replace(path.extname((p as ImageField).url.href), "_l" + path.extname((p as ImageField).url.href))); - } + let field = this.Document[this.props.fieldKey]; + if (w < 100) this._curSuffix = "_s"; + else if (w < 600) this._curSuffix = "_m"; + else this._curSuffix = "_l"; + if (field instanceof ImageField) paths = [this.choosePath(field.url)]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => this.choosePath((p as ImageField).url)); } let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; return (
- { - if (this._curImageSize === "small") this._smallImageMissing = true; - if (this._curImageSize === "medium") this._mediumImageMissing = true; - if (this._curImageSize === "large") this._largeImageMissing = true; + let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; + setTimeout(this.retryPath, Math.min(10000, timeout * 5)); })} onLoad={this.onLoad} /> {paths.length > 1 ? this.dots(paths) : (null)} -- cgit v1.2.3-70-g09d2 From 850ac067fb4e62f91a6eee8df40fe95eca3a3326 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 13:15:16 -0400 Subject: changed so that cat image works. --- src/client/views/nodes/ImageBox.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 29a99e53c..1bd1b80a7 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -177,6 +177,11 @@ export class ImageBox extends DocComponent(ImageD if (this._curSuffix === "_m") this._mediumRetryCount++; if (this._curSuffix === "_l") this._largeRetryCount++; } + @action onError = () => { + let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; + if (timeout < 10) + setTimeout(this.retryPath, Math.min(10000, timeout * 5)); + } _curSuffix = ""; render() { let transform = this.props.ScreenToLocalTransform().inverse(); @@ -191,9 +196,9 @@ export class ImageBox extends DocComponent(ImageD this._curSuffix = ""; if (w > 20) { let field = this.Document[this.props.fieldKey]; - if (w < 100) this._curSuffix = "_s"; - else if (w < 600) this._curSuffix = "_m"; - else this._curSuffix = "_l"; + if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; + else if (w < 600 && this._mediumRetryCount < 10) this._curSuffix = "_m"; + else if (this._largeRetryCount < 10) this._curSuffix = "_l"; if (field instanceof ImageField) paths = [this.choosePath(field.url)]; else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => this.choosePath((p as ImageField).url)); } @@ -205,16 +210,13 @@ export class ImageBox extends DocComponent(ImageD { - let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; - setTimeout(this.retryPath, Math.min(10000, timeout * 5)); - })} + onError={this.onError} onLoad={this.onLoad} /> {paths.length > 1 ? this.dots(paths) : (null)} - {this.lightbox(paths)} + {/* {this.lightbox(paths)} */}
); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 9c8cd369019f1da21c75c07abecdbe3cf5da4cfe Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 13:25:06 -0400 Subject: only apply suffixes to urls that are on our server... --- src/client/views/nodes/ImageBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 1bd1b80a7..a2291c7cf 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -163,7 +163,7 @@ export class ImageBox extends DocComponent(ImageD } choosePath(url: URL) { - if (url.protocol === "data") + if (url.protocol === "data" || url.href.indexOf(window.location.origin) === -1) return url.href; let ext = path.extname(url.href); return url.href.replace(ext, this._curSuffix + ext); -- cgit v1.2.3-70-g09d2 From e32ccd138ff70f2225e5c2c13e0003e02593ef09 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 14:14:19 -0400 Subject: minimal change to brushing presentation view. --- src/client/views/PresentationView.tsx | 14 ++++++++++++-- .../views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index ce679aa0a..9d5798ff1 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -6,7 +6,7 @@ import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; import { Doc, DocListCast, DocListCastAsync } from "../../new_fields/Doc"; import { listSpec } from "../../new_fields/Schema"; -import { Cast, NumCast, FieldValue, PromiseValue, StrCast } from "../../new_fields/Types"; +import { Cast, NumCast, FieldValue, PromiseValue, StrCast, BoolCast } from "../../new_fields/Types"; import { Id } from "../../new_fields/FieldSymbols"; import { List } from "../../new_fields/List"; import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; @@ -27,6 +27,7 @@ interface PresListProps extends PresViewProps { */ class PresentationViewList extends React.Component { + /** * Renders a single child document. It will just append a list element. * @param document The document to render. @@ -42,8 +43,17 @@ class PresentationViewList extends React.Component { //this doc is selected className += " presentationView-selected"; } + let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } + let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } return ( -
{ this.props.gotoDocument(index); e.stopPropagation(); }}> +
{ this.props.gotoDocument(index); e.stopPropagation(); }}> {`${index + 1}. ${title}`} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6ea230aab..97e610e13 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -135,7 +135,7 @@ export class MarqueeView extends React.Component document.addEventListener("pointerup", this.onPointerUp, true); document.addEventListener("keydown", this.marqueeCommand, true); if (e.altKey) { - e.stopPropagation(); + //e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors. e.preventDefault(); } // bcz: do we need this? it kills the context menu on the main collection if !altKey -- 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') 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') 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') 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') 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') 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 059faf25a0f8ba80e1d2853dcefa1a70df4cbb6a Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 17:10:21 -0400 Subject: fixed icons for pdfs. fixed activeItem issue for golden layout. --- src/client/goldenLayout.js | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 1 + src/client/views/nodes/PDFBox.tsx | 58 +++++++++++----------- 3 files changed, 31 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js index ab2bcefed..54c9c6068 100644 --- a/src/client/goldenLayout.js +++ b/src/client/goldenLayout.js @@ -4466,7 +4466,7 @@ } if (this.contentItems.length > 0) { - initialItem = this.contentItems[this.config.activeItemIndex || 0]; + initialItem = this.contentItems[Math.min(this.contentItems.length - 1, this.config.activeItemIndex || 0)]; if (!initialItem) { throw new Error('Configured activeItemIndex out of bounds'); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 5bff08280..fa2b09ba7 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -189,6 +189,7 @@ export class CollectionFreeFormDocumentView extends DocComponent(PdfDocumen @computed private get thumbnailPage() { return NumCast(this.props.Document.thumbnailPage, -1); } componentDidMount() { - let wasSelected = false; + let wasSelected = this.props.isSelected(); this._reactionDisposer = reaction( - () => this.props.isSelected(), + () => [this.props.isSelected(), this.curPage], () => { - if (this.curPage > 0 && this.curPage !== this.thumbnailPage && wasSelected && !this.props.isSelected()) { + if (this.curPage > 0 && !this.props.isTopMost && this.curPage !== this.thumbnailPage && wasSelected && !this.props.isSelected()) { this.saveThumbnail(); } wasSelected = this._interactive = this.props.isSelected(); @@ -246,16 +245,19 @@ export class PDFBox extends DocComponent(PdfDocumen @action saveThumbnail = () => { + this.props.Document.thumbnailPage = FieldValue(this.Document.curPage, -1); this._renderAsSvg = false; setTimeout(() => { let nwidth = FieldValue(this.Document.nativeWidth, 0); let nheight = FieldValue(this.Document.nativeHeight, 0); - htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 }) + htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 0.8 }) .then(action((dataUrl: string) => { - 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; + SearchBox.convertDataUri(dataUrl, "icon" + this.Document[Id] + "_" + this.curPage).then((returnedFilename) => { + if (returnedFilename) { + let url = DocServer.prepend(returnedFilename); + this.props.Document.thumbnail = new ImageField(new URL(url)); + } + runInAction(() => this._renderAsSvg = true); }) })) .catch(function (error: any) { @@ -292,7 +294,6 @@ export class PDFBox extends DocComponent(PdfDocumen } @computed get pdfContent() { - trace(); let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); if (!pdfUrl) { return

No pdf url to render

; @@ -309,7 +310,7 @@ export class PDFBox extends DocComponent(PdfDocumen ; let xf = (this.Document.nativeHeight || 0) / this.renderHeight; return
- + {body}
; @@ -317,26 +318,25 @@ export class PDFBox extends DocComponent(PdfDocumen @computed get pdfRenderer() { - let proxy = this._loaded ? (null) : this.imageProxyRenderer; let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); - if ((!this._interactive && proxy) || !pdfUrl) { + let proxy = this.imageProxyRenderer; + if ((!this._interactive && proxy && (!this.props.ContainingCollectionView || !this.props.ContainingCollectionView.props.isTopMost)) || !pdfUrl) { return proxy; } return [ this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element), this._currAnno.map((element: any) => element), - this.pdfContent, - proxy + this.pdfContent ]; } @computed get imageProxyRenderer() { let thumbField = this.props.Document.thumbnail; - if (thumbField) { - let path = this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" : + if (thumbField && this._renderAsSvg) { + let path = // this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" : thumbField instanceof ImageField ? thumbField.url.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; - return ; + return ; } return (null); } -- cgit v1.2.3-70-g09d2 From e5c9ba12e9a50a688e8c1554b525c87b1efbafb8 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 17:23:09 -0400 Subject: added s/m/l icons for pdf rendering. --- src/client/views/nodes/ImageBox.tsx | 1 - src/client/views/nodes/PDFBox.tsx | 43 +++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index a2291c7cf..8156ec872 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -19,7 +19,6 @@ import { InkingControl } from '../InkingControl'; import { Doc } from '../../../new_fields/Doc'; import { faImage } from '@fortawesome/free-solid-svg-icons'; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; var path = require('path'); library.add(faImage); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index d1b9098b0..2a59eb7e5 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -21,6 +21,7 @@ import { positionSchema } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; +var path = require('path'); import React = require("react"); /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx @@ -330,20 +331,54 @@ export class PDFBox extends DocComponent(PdfDocumen ]; } + choosePath(url: URL) { + if (url.protocol === "data" || url.href.indexOf(window.location.origin) === -1) + return url.href; + let ext = path.extname(url.href); + return url.href.replace(ext, this._curSuffix + ext); + } + @observable _smallRetryCount = 1; + @observable _mediumRetryCount = 1; + @observable _largeRetryCount = 1; + @action retryPath = () => { + if (this._curSuffix === "_s") this._smallRetryCount++; + if (this._curSuffix === "_m") this._mediumRetryCount++; + if (this._curSuffix === "_l") this._largeRetryCount++; + } + @action onError = () => { + let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; + if (timeout < 10) + setTimeout(this.retryPath, Math.min(10000, timeout * 5)); + } + _curSuffix = ""; + @computed get imageProxyRenderer() { let thumbField = this.props.Document.thumbnail; if (thumbField && this._renderAsSvg) { - let path = // this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" : - thumbField instanceof ImageField ? thumbField.url.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; - return ; + + let transform = this.props.ScreenToLocalTransform().inverse(); + let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; + var [sptX, sptY] = transform.transformPoint(0, 0); + let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); + let w = bptX - sptX; + + let path = thumbField instanceof ImageField ? thumbField.url.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; + this._curSuffix = ""; + if (w > 20) { + let field = thumbField; + if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; + else if (w < 400 && this._mediumRetryCount < 10) this._curSuffix = "_m"; + else if (this._largeRetryCount < 10) this._curSuffix = "_l"; + if (field instanceof ImageField) path = this.choosePath(field.url); + } + return ; } return (null); } @action onKeyDown = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = true); @action onKeyUp = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = false); render() { - trace(); let classname = "pdfBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
-- 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') 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 70930405f8bdf43c05a77cb3dcbdadcbd3c9ab70 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 20 May 2019 19:10:10 -0400 Subject: PDF and Image test Context work --- .../views/collections/CollectionDockingView.tsx | 3 ++- .../views/collections/ParentDocumentSelector.scss | 10 ++++++++ .../views/collections/ParentDocumentSelector.tsx | 24 ++++++++++++++----- src/client/views/nodes/ImageBox.tsx | 28 +++++++++++----------- src/client/views/nodes/PDFBox.tsx | 26 ++++++++++---------- src/new_fields/Doc.ts | 13 ++++++---- 6 files changed, 65 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 9721bf804..180a8be46 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -332,7 +332,8 @@ export class CollectionDockingView extends React.Component0
`); tab.element.append(counter); let upDiv = document.createElement("span"); - ReactDOM.render(, upDiv); + const stack = tab.contentItem.parent; + ReactDOM.render( CollectionDockingView.Instance.AddTab(stack, doc)} />, upDiv); tab.reactComponents = [upDiv]; tab.element.append(upDiv); counter.DashDocId = tab.contentItem.config.props.documentId; diff --git a/src/client/views/collections/ParentDocumentSelector.scss b/src/client/views/collections/ParentDocumentSelector.scss index f3c605f3e..1ab12bb72 100644 --- a/src/client/views/collections/ParentDocumentSelector.scss +++ b/src/client/views/collections/ParentDocumentSelector.scss @@ -5,4 +5,14 @@ box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); min-width: 150px; color: black; + + hr { + height: 1px; + margin: 0px; + background-color: gray; + border-top: 0px; + border-bottom: 0px; + border-right: 0px; + border-left: 0px; + } } \ No newline at end of file diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 4d07c31a7..65ae7f9ec 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -7,32 +7,44 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { SearchUtil } from "../../util/SearchUtil"; import { CollectionDockingView } from "./CollectionDockingView"; +type SelectorProps = { Document: Doc, addDocTab(doc: Doc, location: string): void }; @observer -export class SelectorContextMenu extends React.Component<{ Document: Doc }> { +export class SelectorContextMenu extends React.Component { @observable private _docs: Doc[] = []; + @observable private _otherDocs: Doc[] = []; - constructor(props: { Document: Doc }) { + constructor(props: SelectorProps) { super(props); this.fetchDocuments(); } async fetchDocuments() { + let aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)).filter(doc => doc !== this.props.Document); const docs = await SearchUtil.Search(`data_l:"${this.props.Document[Id]}"`, true); - runInAction(() => this._docs = docs); + const otherDocs: Set = new Set; + const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search(`data_l:"${doc[Id]}"`, true))); + allDocs.forEach(docs => docs.forEach(doc => otherDocs.add(doc))); + docs.forEach(doc => otherDocs.delete(doc)); + runInAction(() => { + this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)); + this._otherDocs = Array.from(otherDocs).filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)); + }); } render() { return ( <> - {this._docs.map(doc =>

CollectionDockingView.Instance.AddRightSplit(doc)}>{doc.title}

)} + {this._docs.map(doc =>

this.props.addDocTab(Doc.IsPrototype(doc) ? Doc.MakeDelegate(doc) : doc, "inTab")}>{doc.title}

)} + {this._otherDocs.length ?
: null} + {this._otherDocs.map(doc =>

this.props.addDocTab(Doc.IsPrototype(doc) ? Doc.MakeDelegate(doc) : doc, "inTab")}>{doc.title}

)} ); } } @observer -export class ParentDocSelector extends React.Component<{ Document: Doc }> { +export class ParentDocSelector extends React.Component { @observable hover = false; @action @@ -50,7 +62,7 @@ export class ParentDocSelector extends React.Component<{ Document: Doc }> { if (this.hover) { flyout = (
- +
); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 8156ec872..e022793eb 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -181,26 +181,26 @@ export class ImageBox extends DocComponent(ImageD if (timeout < 10) setTimeout(this.retryPath, Math.min(10000, timeout * 5)); } - _curSuffix = ""; + _curSuffix = "_m"; render() { - let transform = this.props.ScreenToLocalTransform().inverse(); + // let transform = this.props.ScreenToLocalTransform().inverse(); let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; - var [sptX, sptY] = transform.transformPoint(0, 0); - let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); - let w = bptX - sptX; + // var [sptX, sptY] = transform.transformPoint(0, 0); + // let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); + // let w = bptX - sptX; let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx let nativeWidth = FieldValue(this.Document.nativeWidth, pw); let paths: string[] = ["http://www.cs.brown.edu/~bcz/noImage.png"]; - this._curSuffix = ""; - if (w > 20) { - let field = this.Document[this.props.fieldKey]; - if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; - else if (w < 600 && this._mediumRetryCount < 10) this._curSuffix = "_m"; - else if (this._largeRetryCount < 10) this._curSuffix = "_l"; - if (field instanceof ImageField) paths = [this.choosePath(field.url)]; - else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => this.choosePath((p as ImageField).url)); - } + // this._curSuffix = ""; + // if (w > 20) { + let field = this.Document[this.props.fieldKey]; + // if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; + // else if (w < 600 && this._mediumRetryCount < 10) this._curSuffix = "_m"; + // else if (this._largeRetryCount < 10) this._curSuffix = "_l"; + if (field instanceof ImageField) paths = [this.choosePath(field.url)]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => this.choosePath((p as ImageField).url)); + // } let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; return (
(PdfDocumen if (timeout < 10) setTimeout(this.retryPath, Math.min(10000, timeout * 5)); } - _curSuffix = ""; + _curSuffix = "_m"; @computed get imageProxyRenderer() { let thumbField = this.props.Document.thumbnail; if (thumbField && this._renderAsSvg) { - let transform = this.props.ScreenToLocalTransform().inverse(); + // let transform = this.props.ScreenToLocalTransform().inverse(); let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; - var [sptX, sptY] = transform.transformPoint(0, 0); - let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); - let w = bptX - sptX; + // var [sptX, sptY] = transform.transformPoint(0, 0); + // let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); + // let w = bptX - sptX; let path = thumbField instanceof ImageField ? thumbField.url.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; - this._curSuffix = ""; - if (w > 20) { - let field = thumbField; - if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; - else if (w < 400 && this._mediumRetryCount < 10) this._curSuffix = "_m"; - else if (this._largeRetryCount < 10) this._curSuffix = "_l"; - if (field instanceof ImageField) path = this.choosePath(field.url); - } + // this._curSuffix = ""; + // if (w > 20) { + let field = thumbField; + // if (w < 100 && this._smallRetryCount < 10) this._curSuffix = "_s"; + // else if (w < 400 && this._mediumRetryCount < 10) this._curSuffix = "_m"; + // else if (this._largeRetryCount < 10) this._curSuffix = "_l"; + if (field instanceof ImageField) path = this.choosePath(field.url); + // } return ; } return (null); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index f4514c33e..92d3c140a 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -149,6 +149,9 @@ export namespace Doc { export function GetT(doc: Doc, key: string, ctor: ToConstructor, ignoreProto: boolean = false): FieldResult { return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult; } + export function IsPrototype(doc: Doc) { + return GetT(doc, "isPrototype", "boolean", true); + } export async function SetOnPrototype(doc: Doc, key: string, value: Field) { const proto = Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto : doc; @@ -180,11 +183,11 @@ export namespace Doc { // compare whether documents or their protos match export function AreProtosEqual(doc: Doc, other: Doc) { - let r = (doc[Id] === other[Id]); - let r2 = (doc.proto && doc.proto.Id === other[Id]); - let r3 = (other.proto && other.proto.Id === doc[Id]); - let r4 = (doc.proto && other.proto && doc.proto[Id] === other.proto[Id]); - return r || r2 || r3 || r4 ? true : false; + let r = (doc === other); + let r2 = (doc.proto === other); + let r3 = (other.proto === doc); + let r4 = (doc.proto === other.proto); + return r || r2 || r3 || r4; } // gets the document's prototype or returns the document if it is a prototype -- cgit v1.2.3-70-g09d2 From 060455feec89c94073636f612ccca54a0aaabb90 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 21:29:17 -0400 Subject: fixed a few things for Firefox - dragging images, typing spaces, scrool speed. and focusing proeprly with zoomBasis. --- .vscode/launch.json | 9 +++++++++ .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 9 +++------ src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 3 +++ src/client/views/nodes/FormattedTextBox.tsx | 4 ++-- 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/.vscode/launch.json b/.vscode/launch.json index d245be2ad..3b6549767 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,6 +13,15 @@ "url": "http://localhost:1050/login", "webRoot": "${workspaceFolder}", }, + { + "type": "firefox", + "request": "launch", + "name": "Launch Firefox against localhost", + "sourceMaps": "client", + "reAttach": true, + "url": "http://localhost:1050/login", + "webRoot": "${workspaceFolder}", + }, { "type": "chrome", "request": "launch", diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ee6f4821f..3ec7184d2 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -183,7 +183,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return; } e.stopPropagation(); - const coefficient = 1000; + const coefficient = 100; if (e.ctrlKey) { let deltaScale = (1 - (e.deltaY / coefficient)); @@ -215,7 +215,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @action setPan(panX: number, panY: number) { - this.panDisposer && clearTimeout(this.panDisposer); this.props.Document.panTransformType = "None"; var scale = this.getLocalTransform().inverse().Scale; const newPanX = Math.min((1 - 1 / scale) * this.nativeWidth, Math.max(0, panX)); @@ -243,7 +242,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { doc.zIndex = docs.length + 1; } - panDisposer?: NodeJS.Timeout; focusDocument = (doc: Doc) => { const panX = this.Document.panX; const panY = this.Document.panY; @@ -265,15 +263,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { } } SelectionManager.DeselectAll(); - const newPanX = NumCast(doc.x) + NumCast(doc.width) / 2; - const newPanY = NumCast(doc.y) + NumCast(doc.height) / 2; + const newPanX = NumCast(doc.x) + NumCast(doc.width) / NumCast(doc.zoomBasis, 1) / 2; + const newPanY = NumCast(doc.y) + NumCast(doc.height) / NumCast(doc.zoomBasis, 1) / 2; const newState = HistoryUtil.getState(); newState.initializers[id] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); this.setPan(newPanX, newPanY); this.props.Document.panTransformType = "Ease"; this.props.focus(this.props.Document); - this.panDisposer = setTimeout(() => this.props.Document.panTransformType = "None", 2000); // wait 3 seconds, then reset to false } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index fa2b09ba7..7c3180496 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -177,6 +177,9 @@ export class CollectionFreeFormDocumentView extends DocComponent { document.removeEventListener("pointerup", this.onPointerUp); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index d15813f9a..5afef221c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -366,7 +366,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe style={{ pointerEvents: interactive ? "all" : "none", }} - onKeyDown={this.onKeyPress} + // onKeyDown={this.onKeyPress} onKeyPress={this.onKeyPress} onFocus={this.onFocused} onClick={this.onClick} @@ -378,7 +378,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe // tfs: do we need this event handler onWheel={this.onPointerWheel} > -
+
); } -- cgit v1.2.3-70-g09d2 From 505676028698f22e46854fdd8ea25ea3118b5d6f Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 20 May 2019 22:31:37 -0400 Subject: fixed annotation pages for videos --- src/Utils.ts | 13 +++++++++++++ src/client/views/InkingCanvas.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 6 ++++-- 4 files changed, 19 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Utils.ts b/src/Utils.ts index 24878a368..611c61135 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -39,6 +39,19 @@ export class Utils { document.body.removeChild(textArea); } + public static GetClipboardText(): string { + var textArea = document.createElement("textarea"); + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + try { document.execCommand('paste'); } catch (err) { } + + const val = textArea.value; + document.body.removeChild(textArea); + return val; + } + public static loggingEnabled: Boolean = false; public static logFilter: number | undefined = undefined; private static log(prefix: string, messageName: string, message: any, receiving: boolean) { diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index afe3e3ecb..42ab08001 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -146,7 +146,7 @@ export class InkingCanvas extends React.Component { get drawnPaths() { let curPage = NumCast(this.props.Document.curPage, -1); let paths = Array.from(this.inkData).reduce((paths, [id, strokeData]) => { - if (strokeData.page === -1 || strokeData.page === curPage) { + if (strokeData.page === -1 || Math.round(strokeData.page) === Math.round(curPage)) { paths.push( { if (!(doc instanceof Doc)) return prev; var page = NumCast(doc.page, -1); - if (page === curPage || page === -1) { + if (Math.round(page) === Math.round(curPage) || page === -1) { let minim = BoolCast(doc.isMinimized, false); if (minim === undefined || !minim) { prev.push(); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 81c429a02..6ae55d151 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -52,7 +52,7 @@ export class VideoBox extends DocComponent(VideoD @action public Play() { this.Playing = true; if (this.player) this.player.play(); - if (!this._playTimer) this._playTimer = setInterval(this.updateTimecode, 1000); + if (!this._playTimer) this._playTimer = setInterval(this.updateTimecode, 500); } @action public Pause() { @@ -70,7 +70,9 @@ export class VideoBox extends DocComponent(VideoD } @action - updateTimecode = () => this.player && (this.props.Document.curPage = this.player.currentTime) + updateTimecode = () => { + this.player && (this.props.Document.curPage = this.player.currentTime); + } componentDidMount() { if (this.props.setVideoBox) this.props.setVideoBox(this); -- cgit v1.2.3-70-g09d2 From c91a87d8e324089166373ec828f101836555585a Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 05:50:22 -0400 Subject: Going up a level now centers on the document --- .../views/collections/ParentDocumentSelector.tsx | 33 ++++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 65ae7f9ec..e6eb51a0c 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -6,12 +6,14 @@ import { observable, action, runInAction } from "mobx"; import { Id } from "../../../new_fields/FieldSymbols"; import { SearchUtil } from "../../util/SearchUtil"; import { CollectionDockingView } from "./CollectionDockingView"; +import { NumCast } from "../../../new_fields/Types"; +import { CollectionViewType } from "./CollectionBaseView"; type SelectorProps = { Document: Doc, addDocTab(doc: Doc, location: string): void }; @observer export class SelectorContextMenu extends React.Component { - @observable private _docs: Doc[] = []; - @observable private _otherDocs: Doc[] = []; + @observable private _docs: { col: Doc, target: Doc }[] = []; + @observable private _otherDocs: { col: Doc, target: Doc }[] = []; constructor(props: SelectorProps) { super(props); @@ -22,22 +24,35 @@ export class SelectorContextMenu extends React.Component { async fetchDocuments() { let aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document)).filter(doc => doc !== this.props.Document); const docs = await SearchUtil.Search(`data_l:"${this.props.Document[Id]}"`, true); - const otherDocs: Set = new Set; + const map: Map = new Map; const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search(`data_l:"${doc[Id]}"`, true))); - allDocs.forEach(docs => docs.forEach(doc => otherDocs.add(doc))); - docs.forEach(doc => otherDocs.delete(doc)); + allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index]))); + docs.forEach(doc => map.delete(doc)); runInAction(() => { - this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)); - this._otherDocs = Array.from(otherDocs).filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)); + this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: this.props.Document })); + this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target })); }); } + getOnClick({ col, target }: { col: Doc, target: Doc }) { + return () => { + col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col; + if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { + const newPanX = NumCast(target.x) + NumCast(target.width) / NumCast(target.zoomBasis, 1) / 2; + const newPanY = NumCast(target.y) + NumCast(target.height) / NumCast(target.zoomBasis, 1) / 2; + col.panX = newPanX; + col.panY = newPanY; + } + this.props.addDocTab(col, "inTab"); + }; + } + render() { return ( <> - {this._docs.map(doc =>

this.props.addDocTab(Doc.IsPrototype(doc) ? Doc.MakeDelegate(doc) : doc, "inTab")}>{doc.title}

)} + {this._docs.map(doc =>

{doc.col.title}

)} {this._otherDocs.length ?
: null} - {this._otherDocs.map(doc =>

this.props.addDocTab(Doc.IsPrototype(doc) ? Doc.MakeDelegate(doc) : doc, "inTab")}>{doc.title}

)} + {this._otherDocs.map(doc =>

{doc.col.title}

)} ); } -- cgit v1.2.3-70-g09d2 From 3abf1b817a5ed0e2bcacaa08f4a15a9193794a3a Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 08:22:24 -0400 Subject: Fixed performance problems --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 6 +++--- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 97e610e13..31864f357 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,5 +1,5 @@ import * as htmlToImage from "html-to-image"; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; import { Docs } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; @@ -344,10 +344,10 @@ export class MarqueeView extends React.Component } render() { - let p = this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); + let p: [number, number] = this._visible ? this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY) : [0, 0]; return
- {!this._visible ? null : this.marqueeDiv} + {this._visible ? this.marqueeDiv : null}
{this.props.children}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7c3180496..bf0c272e3 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, reaction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; @@ -211,7 +211,7 @@ export class CollectionFreeFormDocumentView extends DocComponent Doc.GetProto(doc)) + let expandedProtoDocs = expandedDocs.map(doc => Doc.GetProto(doc)); let maxLocation = StrCast(this.props.Document.maximizeLocation, "inPlace"); let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target); if (altKey) { @@ -286,7 +286,9 @@ export class CollectionFreeFormDocumentView extends DocComponent Date: Tue, 21 May 2019 09:34:10 -0400 Subject: Fixed speed again? --- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 10 +++++----- src/client/views/nodes/DocumentContentsView.tsx | 5 +++-- src/client/views/nodes/ImageBox.tsx | 2 +- src/new_fields/Doc.ts | 1 - 4 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index bf0c272e3..aaaa6a9c5 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -266,15 +266,15 @@ export class CollectionFreeFormDocumentView extends DocComponent 800 ? Math.max(0, Math.min(1, 2 - 5 * (zoom < this.scale ? this.scale / zoom : zoom / this.scale))) : 1; const screenWidth = Math.min(50 * NumCast(this.props.Document.nativeWidth, 0), 1800); let fadeUp = .75 * screenWidth; let fadeDown = (maximizedDoc ? .0075 : .075) * screenWidth; - zoomFade = w < fadeDown /* || w > fadeUp */ ? Math.max(0.1, Math.min(1, 2 - (w < fadeDown ? Math.sqrt(Math.sqrt(fadeDown / w)) : w / fadeUp))) : 1; + // zoomFade = w < fadeDown /* || w > fadeUp */ ? Math.max(0.1, Math.min(1, 2 - (w < fadeDown ? Math.sqrt(Math.sqrt(fadeDown / w)) : w / fadeUp))) : 1; return (
Date: Tue, 21 May 2019 11:44:51 -0400 Subject: Fixed various scripting things --- src/client/util/type_decls.d | 33 ++++++++++++++++------ .../views/collections/CollectionSchemaView.tsx | 10 +++---- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 8 ++---- src/debug/Viewer.tsx | 2 +- src/new_fields/Doc.ts | 7 +++-- src/new_fields/URLField.ts | 9 ++++-- 7 files changed, 46 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d index 51114d0e2..557f6f574 100644 --- a/src/client/util/type_decls.d +++ b/src/client/util/type_decls.d @@ -140,33 +140,50 @@ declare const ToScriptString: unique symbol; declare abstract class RefField { readonly [Id]: FieldId; - constructor(id?: FieldId); - protected [HandleUpdate]?(diff: any): void; + constructor(); + // protected [HandleUpdate]?(diff: any): void; - abstract [ToScriptString](): string; + // abstract [ToScriptString](): string; } declare abstract class ObjectField { protected [OnUpdate](diff?: any): void; private [Parent]?: RefField | ObjectField; - abstract [Copy](): ObjectField; + // abstract [Copy](): ObjectField; - abstract [ToScriptString](): string; + // abstract [ToScriptString](): string; } + +declare abstract class URLField extends ObjectField { + readonly url: URL; + + constructor(url: string); + constructor(url: URL); +} + +declare class AudioField extends URLField { } +declare class VideoField extends URLField { } +declare class ImageField extends URLField { } +declare class WebField extends URLField { } +declare class PdfField extends URLField { } + declare type FieldId = string; declare type Field = number | string | boolean | ObjectField | RefField; declare type Opt = T | undefined; declare class Doc extends RefField { + constructor(); + [key: string]: Field | undefined; - [ToScriptString](): string; + // [ToScriptString](): string; } declare class ListImpl extends ObjectField { + constructor(fields?: T[]); [index: number]: T | (T extends RefField ? Promise : never); - [ToScriptString](): string; - [Copy](): ObjectField; + // [ToScriptString](): string; + // [Copy](): ObjectField; } // @ts-ignore diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b25b48339..488f7d6cb 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -115,22 +115,20 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { height={Number(MAX_ROW_HEIGHT)} GetValue={() => { let field = props.Document[props.fieldKey]; - if (field) { - //TODO Types - // return field.ToScriptString(); - return String(field); + if (Field.IsField(field)) { + return Field.toScriptString(field); } return ""; }} SetValue={(value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Document.name } }); + let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); if (!script.compiled) { return false; } return applyToDoc(props.Document, script.run); }} OnFillDown={async (value: string) => { - let script = CompileScript(value, { addReturn: true, params: { this: Document.name } }); + let script = CompileScript(value, { addReturn: true, params: { this: Doc.name } }); if (!script.compiled) { return; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index ba6a4bbab..7a0a02318 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -183,7 +183,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return; } e.stopPropagation(); - const coefficient = 100; + const coefficient = 1000; if (e.ctrlKey) { let deltaScale = (1 - (e.deltaY / coefficient)); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 7a88985c0..2363553df 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -60,10 +60,8 @@ export class KeyValuePair extends React.Component { { let field = FieldValue(props.Document[props.fieldKey]); - if (field) { - //TODO Types - return String(field); - // return field.ToScriptString(); + if (Field.IsField(field)) { + return Field.toScriptString(field); } return ""; }} @@ -75,7 +73,7 @@ export class KeyValuePair extends React.Component { let res = script.run(); if (!res.success) return false; const field = res.result; - if (Field.IsField(field)) { + if (Field.IsField(field, true)) { props.Document[props.fieldKey] = field; return true; } diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx index 4314e2132..b22300d0b 100644 --- a/src/debug/Viewer.tsx +++ b/src/debug/Viewer.tsx @@ -20,7 +20,7 @@ function applyToDoc(doc: any, key: string | number, scriptString: string): boole } const res = script.run({ this: doc }); if (!res.success) return false; - if (!Field.IsField(res.result)) return false; + if (!Field.IsField(res.result, true)) return false; doc[key] = res.result; return true; } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 08bc2ec4d..b0237d04d 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -19,12 +19,15 @@ export namespace Field { return field[ToScriptString](); } } - export function IsField(field: any): field is Field { + export function IsField(field: any): field is Field; + export function IsField(field: any, includeUndefined: true): field is Field | undefined; + export function IsField(field: any, includeUndefined: boolean = false): field is Field | undefined { return (typeof field === "string") || (typeof field === "number") || (typeof field === "boolean") || (field instanceof ObjectField) - || (field instanceof RefField); + || (field instanceof RefField) + || (includeUndefined && field === undefined); } } export type Field = number | string | boolean | ObjectField | RefField; diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts index a6f8f1cc5..4a2841fb6 100644 --- a/src/new_fields/URLField.ts +++ b/src/new_fields/URLField.ts @@ -18,13 +18,18 @@ export abstract class URLField extends ObjectField { @serializable(url()) readonly url: URL; - constructor(url: URL) { + constructor(url: string); + constructor(url: URL); + constructor(url: URL | string) { super(); + if (typeof url === "string") { + url = new URL(url); + } this.url = url; } [ToScriptString]() { - return `new ${this.constructor.name}(new URL(${this.url.href}))`; + return `new ${this.constructor.name}("${this.url.href}")`; } [Copy](): this { -- cgit v1.2.3-70-g09d2 From cfb7fdb1a7b2db263502677e57ee882a6fe23f13 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 12:29:28 -0400 Subject: Made cursors disappear after 1 second --- package.json | 1 + src/client/views/collections/CollectionSubView.tsx | 6 ++---- .../collectionFreeForm/CollectionFreeFormRemoteCursors.tsx | 5 ++++- src/new_fields/CursorField.ts | 9 ++++++--- 4 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/package.json b/package.json index 790535728..aa4abb0a5 100644 --- a/package.json +++ b/package.json @@ -126,6 +126,7 @@ "mobx": "^5.9.0", "mobx-react": "^5.3.5", "mobx-react-devtools": "^6.1.1", + "mobx-utils": "^5.4.0", "mongodb": "^3.1.13", "mongoose": "^5.4.18", "node-sass": "^4.12.0", diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 864fdfa4b..7800b35df 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -16,9 +16,7 @@ import { listSpec } from "../../../new_fields/Schema"; import { Cast, PromiseValue, FieldValue, ListSpec } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { DocServer } from "../../DocServer"; -import { ObjectField } from "../../../new_fields/ObjectField"; -import CursorField, { CursorPosition, CursorMetadata } from "../../../new_fields/CursorField"; -import { url } from "inspector"; +import CursorField from "../../../new_fields/CursorField"; export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; @@ -72,7 +70,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.data.metadata.id === id)) > -1) { cursors[ind].setPosition(pos); } else { - let entry = new CursorField({ metadata: { id: id, identifier: email }, position: pos }); + let entry = new CursorField({ metadata: { id: id, identifier: email, timestamp: Date.now() }, position: pos }); cursors.push(entry); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx index 642118d75..2838b7905 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx @@ -9,6 +9,7 @@ import CursorField from "../../../../new_fields/CursorField"; import { List } from "../../../../new_fields/List"; import { Cast } from "../../../../new_fields/Types"; import { listSpec } from "../../../../new_fields/Schema"; +import * as mobxUtils from 'mobx-utils'; @observer export class CollectionFreeFormRemoteCursors extends React.Component { @@ -23,7 +24,9 @@ export class CollectionFreeFormRemoteCursors extends React.Component cursor.data.metadata.id !== id); + const now = mobxUtils.now(); + // const now = Date.now(); + return (cursors || []).filter(cursor => cursor.data.metadata.id !== id && (now - cursor.data.metadata.timestamp) < 1000); } private crosshairs?: HTMLCanvasElement; diff --git a/src/new_fields/CursorField.ts b/src/new_fields/CursorField.ts index 1be1ec3e0..fd86031a8 100644 --- a/src/new_fields/CursorField.ts +++ b/src/new_fields/CursorField.ts @@ -1,7 +1,7 @@ import { ObjectField } from "./ObjectField"; import { observable } from "mobx"; import { Deserializable } from "../client/util/SerializationHelper"; -import { serializable, createSimpleSchema, object } from "serializr"; +import { serializable, createSimpleSchema, object, date } from "serializr"; import { OnUpdate, ToScriptString, Copy } from "./FieldSymbols"; export type CursorPosition = { @@ -11,7 +11,8 @@ export type CursorPosition = { export type CursorMetadata = { id: string, - identifier: string + identifier: string, + timestamp: number }; export type CursorData = { @@ -26,7 +27,8 @@ const PositionSchema = createSimpleSchema({ const MetadataSchema = createSimpleSchema({ id: true, - identifier: true + identifier: true, + timestamp: true }); const CursorSchema = createSimpleSchema({ @@ -47,6 +49,7 @@ export default class CursorField extends ObjectField { setPosition(position: CursorPosition) { this.data.position = position; + this.data.metadata.timestamp = Date.now(); this[OnUpdate](); } -- cgit v1.2.3-70-g09d2 From 7bafa21e8c37826686a012151674b71631fa9c8b Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 21 May 2019 12:35:36 -0400 Subject: fixed dragging headers for histograms --- src/client/documents/Documents.ts | 1 - src/client/views/collections/CollectionSchemaView.tsx | 16 +++++++++++++--- .../views/collections/collectionFreeForm/MarqueeView.tsx | 5 ++++- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 9d2f4d3cd..3d65826a9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -33,7 +33,6 @@ import { DocServer } from "../DocServer"; import { StrokeData, InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; -import { schema } from "prosemirror-schema-basic"; import { UndoManager } from "../util/UndoManager"; export interface DocumentOptions { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b25b48339..c42a0332d 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -68,7 +68,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return this.columns.map(col => { const ref = React.createRef(); return { - Header:

this.onHeaderDrag(col))}>{col}

, + Header:

this.onHeaderDrag(col), undefined, "copy")}>{col}

, accessor: (doc: Doc) => doc ? doc[col] : 0, id: col }; @@ -76,6 +76,15 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } onHeaderDrag = (columnName: string) => { + let dbDoc = Cast(this.props.Document.DBDoc, Doc); + if (dbDoc instanceof Doc) { + let columnDocs = DocListCast(dbDoc.data); + if (columnDocs) { + let ddoc = columnDocs.find(doc => doc.title === columnName); + if (ddoc) + return ddoc; + } + } return this.props.Document; } @@ -237,7 +246,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { csv = csv.substr(0, csv.length - 1) + "\n"; let self = this; DocListCast(this.props.Document.data).map(doc => { - csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); + csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "0") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; }); csv.substring(0, csv.length - 1); @@ -246,7 +255,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (self.props.CollectionView.props.addDocument) { let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); if (schemaDoc) { - self.props.CollectionView.props.addDocument(schemaDoc, false); + //self.props.CollectionView.props.addDocument(schemaDoc, false); + self.props.Document.DBDoc = schemaDoc; } } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 31864f357..7ccf480f3 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -98,18 +98,21 @@ export class MarqueeView extends React.Component let columns = ns[0].split("\t"); let docList: Doc[] = []; let groupAttr: string | number = ""; + let rowProto = new Doc(); + rowProto.width = 200; for (let i = 1; i < ns.length - 1; i++) { let values = ns[i].split("\t"); if (values.length === 1 && columns.length > 1) { groupAttr = values[0]; continue; } - let doc = new Doc(); + let doc = Doc.MakeDelegate(rowProto); columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { doc._group = groupAttr; } doc.title = i.toString(); + doc.width = 200; docList.push(doc); } let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); -- cgit v1.2.3-70-g09d2 From 7e5ba95b02e4ead3ee2b41eca1af0acb72d6f7cd Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 21 May 2019 14:15:06 -0400 Subject: fixes for histogram brushing. --- src/client/northstar/dash-fields/HistogramField.ts | 2 +- src/client/northstar/dash-nodes/HistogramBox.tsx | 4 ++- .../CollectionFreeFormLinksView.tsx | 12 +++---- .../collections/collectionFreeForm/MarqueeView.tsx | 38 ++++++++++++---------- src/client/views/nodes/FieldView.tsx | 2 +- 5 files changed, 31 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index 31040a474..e6f32272e 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -58,6 +58,6 @@ export class HistogramField extends ObjectField { } [ToScriptString]() { - return "invalid"; + return this.toString(); } } \ No newline at end of file diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index a9646ed31..d7732ee86 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -125,9 +125,11 @@ export class HistogramBox extends React.Component { let mapped = brushingDocs.map((brush, i) => { brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; let brushed = DocListCast(brush.brushingDocs); + if (!brushed.length) + return null; return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; }); - this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped); + runInAction(() => this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped.filter(m => m) as { l: Doc, b: Doc }[])); } }, { fireImmediately: true }); reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index e1ff715d1..c5f7ad0d1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -32,8 +32,8 @@ export class CollectionFreeFormLinksView extends React.Component)[]) => field.findIndex(brush => { @@ -60,12 +60,12 @@ export class CollectionFreeFormLinksView extends React.Component(); + if (srcTarg.brushingDocs === undefined) srcTarg.brushingDocs = new List(); let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc), []); let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc), []); - if (dstBrushDocs === undefined) dstTarg.brushingDocs = dstBrushDocs = new List(); - else brushAction(dstBrushDocs); - if (srcBrushDocs === undefined) srcTarg.brushingDocs = srcBrushDocs = new List(); - else brushAction(srcBrushDocs); + brushAction(dstBrushDocs); + brushAction(srcBrushDocs); } }); }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 7ccf480f3..f0ccda140 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -228,6 +228,7 @@ export class MarqueeView extends React.Component if (e.key === "c" || e.key === "s" || e.key === "e" || e.key === "p") { this._commandExecuted = true; e.stopPropagation(); + e.preventDefault(); (e as any).propagationIsStopped = true; let bounds = this.Bounds; let selected = this.marqueeSelect(); @@ -260,25 +261,26 @@ export class MarqueeView extends React.Component if (e.key === "s" || e.key === "p") { - htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { - selected.map(d => { - this.props.removeDocument(d); - d.x = NumCast(d.x) - bounds.left - bounds.width / 2; - d.y = NumCast(d.y) - bounds.top - bounds.height / 2; - d.page = -1; - return d; - }); - let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); - summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); - newCollection.proto!.summaryDoc = summary; - selected = [newCollection]; - newCollection.x = bounds.left + bounds.width; - //this.props.addDocument(newCollection, false); - summary.proto!.summarizedDocs = new List(selected); - summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" - this.props.addLiveTextDocument(summary); + // htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { + selected.map(d => { + this.props.removeDocument(d); + d.x = NumCast(d.x) - bounds.left - bounds.width / 2; + d.y = NumCast(d.y) - bounds.top - bounds.height / 2; + d.page = -1; + return d; }); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + // summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); + // summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); + newCollection.proto!.summaryDoc = summary; + selected = [newCollection]; + newCollection.x = bounds.left + bounds.width; + //this.props.addDocument(newCollection, false); + summary.proto!.summarizedDocs = new List(selected); + summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" + + this.props.addLiveTextDocument(summary); + // }); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5c149af99..092ccb9b0 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -117,7 +117,7 @@ export class FieldView extends React.Component { // return // } else if (!(field instanceof Promise)) { - return

{JSON.stringify(field)}

; + return

{field.toString()}

; } else { return

{"Waiting for server..."}

; -- 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') 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 2f1e56285750bcce6820ba2e1f24b7ad112b9db4 Mon Sep 17 00:00:00 2001 From: ab Date: Tue, 21 May 2019 17:11:17 -0400 Subject: search bar ui fixes --- src/client/views/MainView.tsx | 20 +++++++++++++++++++- src/client/views/SearchBox.tsx | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 6169466bc..aa34a12ed 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,6 +40,7 @@ export class MainView extends React.Component { @observable private _workspacesShown: boolean = false; @observable public pwidth: number = 0; @observable public pheight: number = 0; + private searchbox: React.RefObject; @computed private get mainContainer(): Opt { return FieldValue(Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc)); @@ -56,6 +57,7 @@ export class MainView extends React.Component { constructor(props: Readonly<{}>) { super(props); MainView.Instance = this; + this.searchbox = React.createRef(); // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); if (window.location.search.includes("readonly")) { @@ -260,17 +262,33 @@ export class MainView extends React.Component { return [ ,
+
, -
, +
,
]; } + @action + toggleSearch = () => { + const sb = this.searchbox.current; + if (sb !== null) { + console.log("toggle search") + if (sb.style.display === "none") { + sb.style.display = "block"; + } + else { + sb.style.display = "none"; + } + } + + } + render() { return (
diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 0ec1a6758..911fc8d9c 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -171,8 +171,8 @@ export class SearchBox extends React.Component { - - + {/* */} + {/* */}
{this._resultsOpen ? (
-- cgit v1.2.3-70-g09d2 From 2c4026368078e2dc856c1cf4f8fe375cd30fbcdd Mon Sep 17 00:00:00 2001 From: ab Date: Tue, 21 May 2019 18:03:27 -0400 Subject: alt and linking --- src/client/util/DocumentManager.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index a5e768dcf..82776ff59 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -125,10 +125,20 @@ export class DocumentManager { } let docView = DocumentManager.Instance.getDocumentView(doc); if (docView) { - docView.props.focus(docView.props.Document); + console.log("navigating to linked doc..."); + // using makecopy as a flag for splitting linked to doc to the right...can change later if needed + if (makeCopy) { + if (!contextDoc) { + const actualDoc = Doc.MakeAlias(docDelegate); + (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); + } + } + else { + docView.props.focus(docView.props.Document); + } } else { if (!contextDoc) { - const actualDoc = docDelegate ? (makeCopy ? Doc.MakeCopy(docDelegate) : docDelegate) : Doc.MakeDelegate(doc); + const actualDoc = Doc.MakeAlias(docDelegate); (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); } else { let contextView = DocumentManager.Instance.getDocumentView(contextDoc); -- 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') 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 2845bb8a29d4592964b707d82ca3b07ca15b632c Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 18:30:48 -0400 Subject: Added highlighting of target doc --- src/client/util/DocumentManager.ts | 3 ++- src/new_fields/Doc.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index a5e768dcf..94d77f467 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -116,13 +116,14 @@ export class DocumentManager { @undoBatch public jumpToDocument = async (docDelegate: Doc, makeCopy: boolean = true, dockFunc?: (doc: Doc) => void): Promise => { - let doc = docDelegate.proto ? docDelegate.proto : docDelegate; + let doc = Doc.GetProto(docDelegate); const page = NumCast(doc.page, undefined); const contextDoc = await Cast(doc.annotationOn, Doc); if (contextDoc) { const curPage = NumCast(contextDoc.curPage, page); if (page !== curPage) contextDoc.curPage = page; } + docDelegate.libraryBrush = true; let docView = DocumentManager.Instance.getDocumentView(doc); if (docView) { docView.props.focus(docView.props.Document); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index b0237d04d..793a83750 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -194,7 +194,7 @@ export namespace Doc { // gets the document's prototype or returns the document if it is a prototype export function GetProto(doc: Doc) { - return Object.getOwnPropertyNames(doc).indexOf("isPrototype") === -1 ? doc.proto! : doc; + return Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : doc.proto!; } -- cgit v1.2.3-70-g09d2 From 3020cfcf20d187c976a7f386a95bec0c41cba06b Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 18:35:04 -0400 Subject: fixes --- src/client/util/DocumentManager.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 94d77f467..fefd3a972 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -123,16 +123,18 @@ export class DocumentManager { const curPage = NumCast(contextDoc.curPage, page); if (page !== curPage) contextDoc.curPage = page; } - docDelegate.libraryBrush = true; let docView = DocumentManager.Instance.getDocumentView(doc); if (docView) { + docView.props.Document.libraryBrush = true; docView.props.focus(docView.props.Document); } else { if (!contextDoc) { const actualDoc = docDelegate ? (makeCopy ? Doc.MakeCopy(docDelegate) : docDelegate) : Doc.MakeDelegate(doc); + actualDoc.libraryBrush = true; (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); } else { let contextView = DocumentManager.Instance.getDocumentView(contextDoc); + docDelegate.libraryBrush = true; if (contextView) { contextDoc.panTransformType = "Ease"; contextView.props.focus(contextDoc); -- cgit v1.2.3-70-g09d2 From 72fae9407783a6d17d8d5e202ae0a8d379f57da7 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 19:12:10 -0400 Subject: Changes to DocumentManager --- src/client/util/DocumentManager.ts | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index cf470a015..369becccb 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -123,30 +123,20 @@ export class DocumentManager { const curPage = NumCast(contextDoc.curPage, page); if (page !== curPage) contextDoc.curPage = page; } - let docView = DocumentManager.Instance.getDocumentView(doc); - if (docView) { - console.log("navigating to linked doc..."); - // using makecopy as a flag for splitting linked to doc to the right...can change later if needed - if (makeCopy) { - if (!contextDoc) { - const actualDoc = Doc.MakeAlias(docDelegate); - actualDoc.libraryBrush = true; - (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); - } - } - else { - docView.props.Document.libraryBrush = true; - docView.props.focus(docView.props.Document); - } + let docView: DocumentView | null; + // using makecopy as a flag for splitting linked to doc to the right...can change later if needed + if (!makeCopy && (docView = DocumentManager.Instance.getDocumentView(doc))) { + docView.props.Document.libraryBrush = true; + docView.props.focus(docView.props.Document); } else { if (!contextDoc) { const actualDoc = Doc.MakeAlias(docDelegate); - + actualDoc.libraryBrush = true; (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); } else { - let contextView = DocumentManager.Instance.getDocumentView(contextDoc); + let contextView: DocumentView | null; docDelegate.libraryBrush = true; - if (contextView) { + if (!makeCopy && (contextView = DocumentManager.Instance.getDocumentView(contextDoc))) { contextDoc.panTransformType = "Ease"; contextView.props.focus(contextDoc); } else { -- cgit v1.2.3-70-g09d2 From 1f2b6f2ff438be8ea914a431b0efa8198ec23d96 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 19:16:07 -0400 Subject: Changes --- src/client/views/MainView.tsx | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index aa34a12ed..af224747d 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,8 +40,6 @@ export class MainView extends React.Component { @observable private _workspacesShown: boolean = false; @observable public pwidth: number = 0; @observable public pheight: number = 0; - private searchbox: React.RefObject; - @computed private get mainContainer(): Opt { return FieldValue(Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc)); } @@ -57,7 +55,6 @@ export class MainView extends React.Component { constructor(props: Readonly<{}>) { super(props); MainView.Instance = this; - this.searchbox = React.createRef(); // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); if (window.location.search.includes("readonly")) { @@ -267,26 +264,17 @@ export class MainView extends React.Component {
, -
, + this.isSearchVisible ?
: null,
]; } + @observable isSearchVisible = false; @action toggleSearch = () => { - const sb = this.searchbox.current; - if (sb !== null) { - console.log("toggle search") - if (sb.style.display === "none") { - sb.style.display = "block"; - } - else { - sb.style.display = "none"; - } - } - + this.isSearchVisible = !this.isSearchVisible; } render() { -- cgit v1.2.3-70-g09d2 From b08e28ac279c0199d7f828d05e6e346865579592 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 21 May 2019 19:44:27 -0400 Subject: Fixed image upload --- src/mobile/ImageUpload.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 1f9e160ce..690937339 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -20,12 +20,15 @@ import { List } from '../new_fields/List'; // } // } -const onFileLoad = async (file: any) => { +const onFileLoad = async (file: React.ChangeEvent) => { + file.persist(); + await Docs.initProtos(); let imgPrev = document.getElementById("img_preview"); if (imgPrev) { - let files: File[] = file.target.files; - if (files.length !== 0) { + let files: FileList | null = file.target.files; + if (files && files.length !== 0) { console.log(files[0]); + const name = files[0].name; let formData = new FormData(); formData.append("file", files[0]); @@ -37,7 +40,7 @@ const onFileLoad = async (file: any) => { const json = await res.json(); json.map(async (file: any) => { let path = window.location.origin + file; - var doc = Docs.ImageDocument(path, { nativeWidth: 200, width: 200 }); + var doc = Docs.ImageDocument(path, { nativeWidth: 200, width: 200, title: name }); const res = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)); if (!res) { -- 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') 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 b1de1ab5757330950fe0f79749f098ca2a9f14e0 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 21 May 2019 21:13:58 -0400 Subject: fix to annotations/controls for videos? --- src/client/views/InkingCanvas.scss | 6 ++++++ .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 2c550051c..8277ff785 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -2,6 +2,12 @@ .inkingCanvas { opacity:0.99; + .jsx-parser { + position:absolute; + z-index: -1; + width:100%; + height:100%; + } } .inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect { position: absolute; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7a0a02318..ebe1df4de 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -321,7 +321,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } - private childViews = () => [...this.views, ]; + private childViews = () => [, ...this.views]; render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; -- cgit v1.2.3-70-g09d2 From d3ed10ff3ff9f2e7dec577d81a98318c941c9bdc Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 21 May 2019 22:49:23 -0400 Subject: fixed problems with link drawing to doc centers, and wraparound panning caused by zoomBasis --- .../CollectionFreeFormLinkView.tsx | 8 ++++---- .../collectionFreeForm/CollectionFreeFormView.tsx | 22 ++++++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index 63d2f7642..f646c7bde 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -40,10 +40,10 @@ export class CollectionFreeFormLinkView extends React.Component doc).reduce((range, doc) => { let x = NumCast(doc.x); - let xe = x + NumCast(doc.width) / NumCast(doc.zoomBasis); + let xe = x + NumCast(doc.width) / NumCast(doc.zoomBasis, 1); let y = NumCast(doc.y); - let ye = y + NumCast(doc.height) / NumCast(doc.zoomBasis); + let ye = y + NumCast(doc.height) / NumCast(doc.zoomBasis, 1); return [[range[0][0] > x ? x : range[0][0], range[0][1] < xe ? xe : range[0][1]], [range[1][0] > y ? y : range[1][0], range[1][1] < ye ? ye : range[1][1]]]; }, [[minx, maxx], [miny, maxy]]); @@ -155,12 +155,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { }); } - let panelwidth = this._pwidth / this.zoomScaling() / 2; - let panelheight = this._pheight / this.zoomScaling() / 2; - if (x - dx < ranges[0][0] - panelwidth) x = ranges[0][1] + panelwidth + dx; - if (x - dx > ranges[0][1] + panelwidth) x = ranges[0][0] - panelwidth + dx; - if (y - dy < ranges[1][0] - panelheight) y = ranges[1][1] + panelheight + dy; - if (y - dy > ranges[1][1] + panelheight) y = ranges[1][0] - panelheight + dy; + let panelDim = this.props.ScreenToLocalTransform().transformDirection(this._pwidth / this.zoomScaling(), + this._pheight / this.zoomScaling()); + let panelwidth = panelDim[0]; + let panelheight = panelDim[1]; + if (ranges[0][0] - dx > (this.panX() + panelwidth / 2)) x = ranges[0][1] + panelwidth / 2; + if (ranges[0][1] - dx < (this.panX() - panelwidth / 2)) x = ranges[0][0] - panelwidth / 2; + if (ranges[1][0] - dy > (this.panY() + panelheight / 2)) y = ranges[1][1] + panelheight / 2; + if (ranges[1][1] - dy < (this.panY() - panelheight / 2)) y = ranges[1][0] - panelheight / 2; } this.setPan(x - dx, y - dy); this._lastX = e.pageX; -- cgit v1.2.3-70-g09d2 From 54e41cfe7f3538e9cc4b1871a6692b38d21c8c46 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 22 May 2019 10:58:19 -0400 Subject: added shift+ctrl dragging of images natively. changed z-index & ordering to allow videos to swho controls & ink. fixed dragging schema docs to copy --- src/client/documents/Documents.ts | 5 +++-- src/client/views/InkingCanvas.scss | 1 - src/client/views/Main.scss | 2 +- .../views/collections/CollectionSchemaView.tsx | 12 +++++------ .../views/collections/CollectionVideoView.scss | 2 +- .../collectionFreeForm/CollectionFreeFormView.scss | 1 + .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../collections/collectionFreeForm/MarqueeView.tsx | 14 +++++++----- src/client/views/nodes/ImageBox.tsx | 25 ++++++++++++---------- 9 files changed, 36 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b17544229..323534b2b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -60,6 +60,7 @@ export interface DocumentOptions { borderRounding?: number; schemaColumns?: List; dockingConfig?: string; + dbDoc?: Doc; // [key: string]: Opt; } const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; @@ -241,7 +242,7 @@ export namespace Docs { return CreateInstance(pdfProto, new PdfField(new URL(url)), options); } - export async function DBDocument(url: string, options: DocumentOptions = {}) { + export async function DBDocument(url: string, options: DocumentOptions = {}, columnOptions: DocumentOptions = {}) { let schemaName = options.title ? options.title : "-no schema-"; let ctlog = await Gateway.Instance.GetSchema(url, schemaName); if (ctlog && ctlog.schemas) { @@ -263,7 +264,7 @@ export namespace Docs { new AttributeTransformationModel(atmod, AggregateFunction.None), new AttributeTransformationModel(atmod, AggregateFunction.Count), new AttributeTransformationModel(atmod, AggregateFunction.Count)); - docs.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! })); + docs.push(Docs.HistogramDocument(histoOp, { ...columnOptions, width: 200, height: 200, title: attr.displayName! })); } })); }); diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 8277ff785..8bcaf41dd 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -4,7 +4,6 @@ opacity:0.99; .jsx-parser { position:absolute; - z-index: -1; width:100%; height:100%; } diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 302c49c10..385298e18 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -40,7 +40,7 @@ p { ::-webkit-scrollbar { -webkit-appearance: none; - height: 5px; + height: 10px; width: 10px; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index bfd70ceae..b793447ff 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -76,9 +76,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } onHeaderDrag = (columnName: string) => { - let dbDoc = Cast(this.props.Document.DBDoc, Doc); - if (dbDoc instanceof Doc) { - let columnDocs = DocListCast(dbDoc.data); + let schemaDoc = Cast(this.props.Document.schemaDoc, Doc); + if (schemaDoc instanceof Doc) { + let columnDocs = DocListCast(schemaDoc.data); if (columnDocs) { let ddoc = columnDocs.find(doc => doc.title === columnName); if (ddoc) @@ -109,7 +109,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => (this.props.CollectionView.props.isSelected() ? - SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined); + SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e) : undefined); let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { const res = run({ this: doc }); if (!res.success) return false; @@ -251,10 +251,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let dbName = StrCast(this.props.Document.title); let res = await Gateway.Instance.PostSchema(csv, dbName); if (self.props.CollectionView.props.addDocument) { - let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); + let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document }); if (schemaDoc) { //self.props.CollectionView.props.addDocument(schemaDoc, false); - self.props.Document.DBDoc = schemaDoc; + self.props.Document.schemaDoc = schemaDoc; } } } diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss index db8b84832..9d2c23d3e 100644 --- a/src/client/views/collections/CollectionVideoView.scss +++ b/src/client/views/collections/CollectionVideoView.scss @@ -5,7 +5,7 @@ position: inherit; top: 0; left:0; - + z-index: -1; } .collectionVideoView-time{ color : white; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index 063c9e2cf..8557a3db4 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -63,6 +63,7 @@ border-radius: $border-radius; box-sizing: border-box; position:absolute; + z-index: -1; .marqueeView { overflow: hidden; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 778071126..8be0766eb 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -323,7 +323,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } - private childViews = () => [, ...this.views]; + private childViews = () => [...this.views, ]; render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index f0ccda140..6cdb117ff 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -99,19 +99,23 @@ export class MarqueeView extends React.Component let docList: Doc[] = []; let groupAttr: string | number = ""; let rowProto = new Doc(); + rowProto.title = rowProto.Id; rowProto.width = 200; + rowProto.isPrototype = true; for (let i = 1; i < ns.length - 1; i++) { let values = ns[i].split("\t"); if (values.length === 1 && columns.length > 1) { groupAttr = values[0]; continue; } - let doc = Doc.MakeDelegate(rowProto); - columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); + let docDataProto = Doc.MakeDelegate(rowProto); + docDataProto.isPrototype = true; + columns.forEach((col, i) => docDataProto[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { - doc._group = groupAttr; + docDataProto._group = groupAttr; } - doc.title = i.toString(); + docDataProto.title = i.toString(); + let doc = Doc.MakeDelegate(docDataProto); doc.width = 200; docList.push(doc); } @@ -269,7 +273,7 @@ export class MarqueeView extends React.Component d.page = -1; return d; }); - let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); // summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); // summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); newCollection.proto!.summaryDoc = summary; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index d9d964ee9..71bda6fea 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -93,16 +93,19 @@ export class ImageBox extends DocComponent(ImageD } onPointerDown = (e: React.PointerEvent): void => { - if (Date.now() - this._lastTap < 300) { - if (e.buttons === 1) { - this._downX = e.clientX; - this._downY = e.clientY; - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - } else { - this._lastTap = Date.now(); - } + if (e.shiftKey && e.ctrlKey) + e.stopPropagation(); + + // if (Date.now() - this._lastTap < 300) { + // if (e.buttons === 1) { + // this._downX = e.clientX; + // this._downY = e.clientY; + // document.removeEventListener("pointerup", this.onPointerUp); + // document.addEventListener("pointerup", this.onPointerUp); + // } + // } else { + // this._lastTap = Date.now(); + // } } @action onPointerUp = (e: PointerEvent): void => { @@ -204,7 +207,7 @@ export class ImageBox extends DocComponent(ImageD let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; return (
Date: Wed, 22 May 2019 11:07:20 -0400 Subject: fixed presentation view link follow default. --- src/client/util/DocumentManager.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 369becccb..f113ff1d7 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -115,7 +115,7 @@ export class DocumentManager { } @undoBatch - public jumpToDocument = async (docDelegate: Doc, makeCopy: boolean = true, dockFunc?: (doc: Doc) => void): Promise => { + public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void): Promise => { let doc = Doc.GetProto(docDelegate); const page = NumCast(doc.page, undefined); const contextDoc = await Cast(doc.annotationOn, Doc); @@ -124,8 +124,8 @@ export class DocumentManager { if (page !== curPage) contextDoc.curPage = page; } let docView: DocumentView | null; - // using makecopy as a flag for splitting linked to doc to the right...can change later if needed - if (!makeCopy && (docView = DocumentManager.Instance.getDocumentView(doc))) { + // using forceDockFunc as a flag for splitting linked to doc to the right...can change later if needed + if (!forceDockFunc && (docView = DocumentManager.Instance.getDocumentView(doc))) { docView.props.Document.libraryBrush = true; docView.props.focus(docView.props.Document); } else { @@ -136,7 +136,7 @@ export class DocumentManager { } else { let contextView: DocumentView | null; docDelegate.libraryBrush = true; - if (!makeCopy && (contextView = DocumentManager.Instance.getDocumentView(contextDoc))) { + if (!forceDockFunc && (contextView = DocumentManager.Instance.getDocumentView(contextDoc))) { contextDoc.panTransformType = "Ease"; contextView.props.focus(contextDoc); } else { -- cgit v1.2.3-70-g09d2 From 4b0e534e49b36c44e8a3f295bdfd5e3c90a6c612 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 22 May 2019 11:29:24 -0400 Subject: added summary w/ image using capital S instead of 's' --- .../collections/collectionFreeForm/MarqueeView.tsx | 41 +++++++++++++++++----- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6cdb117ff..f898c10d2 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -17,6 +17,9 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { ImageField } from "../../../../new_fields/URLField"; import { Template, Templates } from "../../Templates"; +import { SearchBox } from "../../SearchBox"; +import { DocServer } from "../../../DocServer"; +import { Id } from "../../../../new_fields/FieldSymbols"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -229,7 +232,7 @@ export class MarqueeView extends React.Component this.cleanupInteractions(false); e.stopPropagation(); } - if (e.key === "c" || e.key === "s" || e.key === "e" || e.key === "p") { + if (e.key === "c" || e.key === "s" || e.key === "S" || e.key === "e" || e.key === "p") { this._commandExecuted = true; e.stopPropagation(); e.preventDefault(); @@ -259,13 +262,11 @@ export class MarqueeView extends React.Component width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, ink: inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined, - title: e.key === "s" ? "-summary-" : e.key === "p" ? "-summary-" : "a nested collection", + title: e.key === "s" || e.key === "S" ? "-summary-" : e.key === "p" ? "-summary-" : "a nested collection", }); this.marqueeInkDelete(inkData); - if (e.key === "s" || e.key === "p") { - - // htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { + if (e.key === "s") { selected.map(d => { this.props.removeDocument(d); d.x = NumCast(d.x) - bounds.left - bounds.width / 2; @@ -274,17 +275,41 @@ export class MarqueeView extends React.Component return d; }); let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); - // summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); - // summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); newCollection.proto!.summaryDoc = summary; selected = [newCollection]; newCollection.x = bounds.left + bounds.width; - //this.props.addDocument(newCollection, false); summary.proto!.summarizedDocs = new List(selected); summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" this.props.addLiveTextDocument(summary); // }); + } else if (e.key === "S") { + await htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { + selected.map(d => { + this.props.removeDocument(d); + d.x = NumCast(d.x) - bounds.left - bounds.width / 2; + d.y = NumCast(d.y) - bounds.top - bounds.height / 2; + d.page = -1; + return d; + }); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); + SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => { + if (returnedFilename) { + let url = DocServer.prepend(returnedFilename); + let imageSummary = Docs.ImageDocument(url, { x: bounds.left + bounds.width, y: bounds.top, width: 300 }); + summary.imageSummary = imageSummary; + this.props.addDocument(imageSummary, false); + } + }) + newCollection.proto!.summaryDoc = summary; + selected = [newCollection]; + newCollection.x = bounds.left + bounds.width; + //this.props.addDocument(newCollection, false); + summary.proto!.summarizedDocs = new List(selected); + summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" + + this.props.addLiveTextDocument(summary); + }); } else { this.props.addDocument(newCollection, false); -- cgit v1.2.3-70-g09d2 From e878910abf712f53113994b4d6f242b5c2231453 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 22 May 2019 11:57:37 -0400 Subject: Pdf proxy rendering --- src/client/views/nodes/PDFBox.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 3bffdd02d..5b8b15ed8 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -249,6 +249,7 @@ export class PDFBox extends DocComponent(PdfDocumen this.props.Document.thumbnailPage = FieldValue(this.Document.curPage, -1); this._renderAsSvg = false; setTimeout(() => { + runInAction(() => this._smallRetryCount = this._mediumRetryCount = this._largeRetryCount = 0); let nwidth = FieldValue(this.Document.nativeWidth, 0); let nheight = FieldValue(this.Document.nativeHeight, 0); htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 0.8 }) @@ -325,6 +326,7 @@ export class PDFBox extends DocComponent(PdfDocumen return proxy; } return [ + proxy, this._pageInfo.area.filter(() => this._pageInfo.area).map((element: any) => element), this._currAnno.map((element: any) => element), this.pdfContent @@ -372,7 +374,7 @@ export class PDFBox extends DocComponent(PdfDocumen // else if (this._largeRetryCount < 10) this._curSuffix = "_l"; if (field instanceof ImageField) path = this.choosePath(field.url); // } - return ; + return ; } return (null); } -- cgit v1.2.3-70-g09d2 From bc1271babcce90ef70aa437d7d630b0244a52bb2 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 22 May 2019 12:12:43 -0400 Subject: Thumbnail stuff --- src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index f898c10d2..d72046800 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -296,7 +296,7 @@ export class MarqueeView extends React.Component SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => { if (returnedFilename) { let url = DocServer.prepend(returnedFilename); - let imageSummary = Docs.ImageDocument(url, { x: bounds.left + bounds.width, y: bounds.top, width: 300 }); + let imageSummary = Docs.ImageDocument(url, { x: bounds.left, y: bounds.top + 100 / zoomBasis, width: 150, title: "-summary image-" }); summary.imageSummary = imageSummary; this.props.addDocument(imageSummary, false); } -- 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') 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 30fdae9e869e0f132c76b4fa99b784e75d6c8dae Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 22 May 2019 19:51:49 -0400 Subject: A bunch of fixes/changes --- src/client/documents/Documents.ts | 2 + src/client/util/DocumentManager.ts | 6 ++- src/client/views/InkingCanvas.scss | 42 ++++++++++++-------- src/client/views/SearchBox.tsx | 10 +++-- .../views/collections/CollectionPDFView.scss | 39 ++++++++++-------- src/client/views/collections/CollectionSubView.tsx | 4 ++ .../views/collections/CollectionVideoView.tsx | 46 +++++++++++++++++++++- .../collections/collectionFreeForm/MarqueeView.tsx | 5 ++- .../views/nodes/CollectionFreeFormDocumentView.tsx | 9 ++++- src/client/views/nodes/DocumentView.tsx | 12 +++--- src/client/views/nodes/ImageBox.tsx | 6 ++- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 16 +++++++- src/client/views/nodes/VideoBox.tsx | 8 +++- 14 files changed, 153 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 323534b2b..ae190a989 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -77,7 +77,9 @@ export namespace DocUtils { linkDoc.proto!.linkTags = "Default"; linkDoc.proto!.linkedTo = target; + linkDoc.proto!.linkedToPage = target.curPage; linkDoc.proto!.linkedFrom = source; + linkDoc.proto!.linkedFromPage = source.curPage; let linkedFrom = Cast(protoTarg.linkedFromDocs, listSpec(Doc)); if (!linkedFrom) { diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index f113ff1d7..65c4b9e4b 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -115,11 +115,11 @@ export class DocumentManager { } @undoBatch - public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void): Promise => { + public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number): Promise => { let doc = Doc.GetProto(docDelegate); - const page = NumCast(doc.page, undefined); const contextDoc = await Cast(doc.annotationOn, Doc); if (contextDoc) { + const page = NumCast(doc.page, linkPage || 0); const curPage = NumCast(contextDoc.curPage, page); if (page !== curPage) contextDoc.curPage = page; } @@ -127,11 +127,13 @@ export class DocumentManager { // using forceDockFunc as a flag for splitting linked to doc to the right...can change later if needed if (!forceDockFunc && (docView = DocumentManager.Instance.getDocumentView(doc))) { docView.props.Document.libraryBrush = true; + if (linkPage !== undefined) docView.props.Document.curPage = linkPage; docView.props.focus(docView.props.Document); } else { if (!contextDoc) { const actualDoc = Doc.MakeAlias(docDelegate); actualDoc.libraryBrush = true; + if (linkPage !== undefined) actualDoc.curPage = linkPage; (dockFunc || CollectionDockingView.Instance.AddRightSplit)(actualDoc); } else { let contextView: DocumentView | null; diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 8bcaf41dd..d95398f17 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,40 +1,50 @@ @import "globalCssVariables"; .inkingCanvas { - opacity:0.99; + opacity: 0.99; + .jsx-parser { - position:absolute; - width:100%; - height:100%; + position: absolute; + width: 100%; + height: 100%; + z-index: -1; // allows annotations to appear on videos when screen is full-size & ... } } -.inkingCanvas-paths-ink, .inkingCanvas-paths-markers, .inkingCanvas-noSelect, .inkingCanvas-canSelect { + +.inkingCanvas-paths-ink, +.inkingCanvas-paths-markers, +.inkingCanvas-noSelect, +.inkingCanvas-canSelect { position: absolute; top: 0; - left:0; + left: 0; width: 8192px; height: 8192px; - cursor:"crosshair"; + cursor: "crosshair"; pointer-events: auto; - + } -.inkingCanvas-canSelect, -.inkingCanvas-noSelect { - top:-50000px; - left:-50000px; + +.inkingCanvas-canSelect, +.inkingCanvas-noSelect { + top: -50000px; + left: -50000px; width: 100000px; height: 100000px; } -.inkingCanvas-noSelect { + +.inkingCanvas-noSelect { pointer-events: none; cursor: "arrow"; } -.inkingCanvas-paths-ink, .inkingCanvas-paths-markers { + +.inkingCanvas-paths-ink, +.inkingCanvas-paths-markers { pointer-events: none; z-index: 10000; // overlays ink on top of everything cursor: "arrow"; } + .inkingCanvas-paths-markers { mix-blend-mode: multiply; -} - +} \ No newline at end of file diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx index 911fc8d9c..fa9462acf 100644 --- a/src/client/views/SearchBox.tsx +++ b/src/client/views/SearchBox.tsx @@ -21,6 +21,7 @@ import { DocumentManager } from '../util/DocumentManager'; import { SetupDrag } from '../util/DragManager'; import { Docs } from '../documents/Documents'; import { RouteStore } from '../../server/RouteStore'; +import { NumCast } from '../../new_fields/Types'; library.add(faSearch); library.add(faObjectGroup); @@ -143,18 +144,21 @@ export class SearchBox extends React.Component { }); let x = 0; let y = 0; + let maxy = 300; for (const doc of docs) { doc.x = x; doc.y = y; doc.width = 200; - doc.height = 200; + doc.height = 200 * NumCast(doc.nativeHeight) / NumCast(doc.nativeWidth, 1); + maxy = Math.max(doc.height, maxy); x += 250; if (x > 1000) { + maxy = 300; x = 0; - y += 250; + y += maxy + 25; } } - return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, title: `Search Docs: "${this.searchString}"` }); + return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this.searchString}"` }); } // Useful queries: diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss index f6fb79582..50201bae8 100644 --- a/src/client/views/collections/CollectionPDFView.scss +++ b/src/client/views/collections/CollectionPDFView.scss @@ -1,49 +1,56 @@ .collectionPdfView-buttonTray { - top : 15px; - left : 20px; - position: relative; + top: 15px; + left: 20px; + position: relative; transform-origin: left top; position: absolute; } + .collectionPdfView-thumb { - width:25px; - height:25px; + width: 25px; + height: 25px; transform-origin: left top; position: absolute; background: darkgray; } + .collectionPdfView-slider { - width:25px; - height:25px; + width: 25px; + height: 25px; transform-origin: left top; position: absolute; background: lightgray; } -.collectionPdfView-cont{ + +.collectionPdfView-cont { width: 100%; height: 100%; - position: absolute; + position: absolute; top: 0; - left:0; + left: 0; + z-index: -1; } + .collectionPdfView-cont-dragging { span { user-select: none; } } + .collectionPdfView-backward { - color : white; + color: white; font-size: 24px; - top :0px; - left : 0px; + top: 0px; + left: 0px; position: absolute; background-color: rgba(50, 50, 50, 0.2); } + .collectionPdfView-forward { - color : white; + color: white; font-size: 24px; - top :0px; - left : 45px; + top: 0px; + left: 45px; position: absolute; background-color: rgba(50, 50, 50, 0.2); } \ No newline at end of file diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 7800b35df..4a21e4465 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -153,6 +153,10 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { @undoBatch @action protected onDrop(e: React.DragEvent, options: DocumentOptions): void { + if (e.ctrlKey) { + e.stopPropagation(); // bcz: this is a hack to stop propagation when dropping an image on a text document with shift+ctrl + return; + } let html = e.dataTransfer.getData("text/html"); let text = e.dataTransfer.getData("text/plain"); diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index 27f23a1a8..7853544d5 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -1,4 +1,5 @@ import { action, observable, trace } from "mobx"; +import * as htmlToImage from "html-to-image"; import { observer } from "mobx-react"; import { ContextMenu } from "../ContextMenu"; import { CollectionViewType, CollectionBaseView, CollectionRenderProps } from "./CollectionBaseView"; @@ -6,10 +7,14 @@ import React = require("react"); import "./CollectionVideoView.scss"; import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; -import { emptyFunction } from "../../../Utils"; +import { emptyFunction, Utils } from "../../../Utils"; import { Id } from "../../../new_fields/FieldSymbols"; import { VideoBox } from "../nodes/VideoBox"; -import { NumCast } from "../../../new_fields/Types"; +import { NumCast, Cast, StrCast } from "../../../new_fields/Types"; +import { VideoField } from "../../../new_fields/URLField"; +import { SearchBox } from "../SearchBox"; +import { DocServer } from "../../DocServer"; +import { Docs, DocUtils } from "../../documents/Documents"; @observer @@ -67,6 +72,43 @@ export class CollectionVideoView extends React.Component { onContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 } + + let field = Cast(this.props.Document[this.props.fieldKey], VideoField); + if (field) { + let url = field.url.href; + ContextMenu.Instance.addItem({ + description: "Copy path", event: () => { Utils.CopyText(url); }, icon: "expand-arrows-alt" + }); + } + let width = NumCast(this.props.Document.width); + let height = NumCast(this.props.Document.height); + ContextMenu.Instance.addItem({ + description: "Take Snapshot", event: async () => { + var canvas = document.createElement('canvas'); + canvas.width = 640; + canvas.height = 640 * NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.nativeWidth); + var ctx = canvas.getContext('2d');//draw image to canvas. scale to target dimensions + ctx && ctx.drawImage(this._videoBox!.player!, 0, 0, canvas.width, canvas.height); + + //convert to desired file format + var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png' + // if you want to preview the captured image, + + let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, ""); + SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => { + if (returnedFilename) { + let url = DocServer.prepend(returnedFilename); + let imageSummary = Docs.ImageDocument(url, { + x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y), + width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-" + }); + this.props.addDocument && this.props.addDocument(imageSummary, false); + DocUtils.MakeLink(imageSummary, this.props.Document); + } + }); + }, + icon: "expand-arrows-alt" + }); } setVideoBox = (videoBox: VideoBox) => { this._videoBox = videoBox; }; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index d72046800..973ebfbdd 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -296,7 +296,10 @@ export class MarqueeView extends React.Component SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => { if (returnedFilename) { let url = DocServer.prepend(returnedFilename); - let imageSummary = Docs.ImageDocument(url, { x: bounds.left, y: bounds.top + 100 / zoomBasis, width: 150, title: "-summary image-" }); + let imageSummary = Docs.ImageDocument(url, { + x: bounds.left, y: bounds.top + 100 / zoomBasis, + width: 150, height: bounds.height / bounds.width * 150, title: "-summary image-" + }); summary.imageSummary = imageSummary; this.props.addDocument(imageSummary, false); } diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index aaaa6a9c5..66d91f9c2 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -195,6 +195,7 @@ export class CollectionFreeFormDocumentView extends DocComponent l instanceof Promise)) { let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 0].maximizeLocation, "inTab"); - DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], altKey, document => this.props.addDocTab(document, maxLocation)); + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0]); } } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 87c88f57c..01c4d82fb 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -234,12 +234,14 @@ export class DocumentView extends DocComponent(Docu makeButton = (e: React.MouseEvent): void => { let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document; doc.isButton = !BoolCast(doc.isButton, false); - if (doc.isButton && !doc.nativeWidth) { - doc.nativeWidth = this.props.Document[WidthSym](); - doc.nativeHeight = this.props.Document[HeightSym](); - } else { + if (StrCast(doc.layout).indexOf("Formatted") !== -1) { // only need to freeze the dimensions of text boxes since they don't have a native width and height naturally + if (doc.isButton && !doc.nativeWidth) { + doc.nativeWidth = this.props.Document[WidthSym](); + doc.nativeHeight = this.props.Document[HeightSym](); + } else { - doc.nativeWidth = doc.nativeHeight = undefined; + doc.nativeWidth = doc.nativeHeight = undefined; + } } } fullScreenClicked = (e: React.MouseEvent): void => { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 71bda6fea..cc0dc8220 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -47,7 +47,7 @@ export class ImageBox extends DocComponent(ImageD onLoad = (target: any) => { var h = this._imgRef.current!.naturalHeight; var w = this._imgRef.current!.naturalWidth; - if (this._photoIndex === 0 && (this.props as any).id !== "isExpander" && (!this.Document.nativeHeight || !this.Document.nativeWidth)) { + if (this._photoIndex === 0 && (this.props as any).id !== "isExpander" && (!this.Document.nativeWidth || !this.Document.nativeHeight || Math.abs(this.Document.nativeWidth / this.Document.nativeHeight - w / h) > 0.05)) { Doc.SetOnPrototype(this.Document, "nativeHeight", FieldValue(this.Document.nativeWidth, 0) * h / w); this.Document.height = FieldValue(this.Document.width, 0) * h / w; } @@ -165,8 +165,10 @@ export class ImageBox extends DocComponent(ImageD } choosePath(url: URL) { - if (url.protocol === "data" || url.href.indexOf(window.location.origin) === -1) + const lower = url.href.toLowerCase(); + if (url.protocol === "data" || url.href.indexOf(window.location.origin) === -1 || !(lower.endsWith(".png") || lower.endsWith(".jpg") || lower.endsWith(".jpeg"))) { return url.href; + } let ext = path.extname(url.href); return url.href.replace(ext, this._curSuffix + ext); } diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 8cb576786..849f17aa4 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -78,7 +78,7 @@ export class KeyValueBox extends React.Component { let rows: JSX.Element[] = []; let i = 0; - for (let key in ids) { + for (let key of Object.keys(ids).sort()) { rows.push(); } return rows; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 5b8b15ed8..733bc920f 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -23,6 +23,7 @@ import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; var path = require('path'); import React = require("react"); +import { ContextMenu } from "../ContextMenu"; /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, @@ -357,7 +358,7 @@ export class PDFBox extends DocComponent(PdfDocumen @computed get imageProxyRenderer() { let thumbField = this.props.Document.thumbnail; - if (thumbField && this._renderAsSvg) { + if (thumbField && this._renderAsSvg && NumCast(this.props.Document.thumbnailPage, 0) === this.Document.curPage) { // let transform = this.props.ScreenToLocalTransform().inverse(); let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; @@ -380,10 +381,21 @@ export class PDFBox extends DocComponent(PdfDocumen } @action onKeyDown = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = true); @action onKeyUp = (e: React.KeyboardEvent) => e.key === "Alt" && (this._alt = false); + onContextMenu = (e: React.MouseEvent): void => { + let field = Cast(this.Document[this.props.fieldKey], PdfField); + if (field) { + let url = field.url.href; + ContextMenu.Instance.addItem({ + description: "Copy path", event: () => { + Utils.CopyText(url); + }, icon: "expand-arrows-alt" + }); + } + } render() { let classname = "pdfBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return ( -
+
{this.pdfRenderer}
); diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 6ae55d151..ab57b4b04 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -88,10 +88,14 @@ export class VideoBox extends DocComponent(VideoD if (vref) { vref.onfullscreenchange = action((e) => this._fullScreen = vref.webkitDisplayingFullscreen); if (this._reactionDisposer) this._reactionDisposer(); - this._reactionDisposer = reaction(() => this.props.Document.curPage, () => - vref.currentTime = NumCast(this.props.Document.curPage, 0), { fireImmediately: true }); + this._reactionDisposer = reaction(() => this.props.Document.curPage, () => { + if (!this.Playing) { + vref.currentTime = NumCast(this.props.Document.curPage, 0); + } + }, { fireImmediately: true }); } } + videoContent(path: string) { let style = "videoBox-cont" + (this._fullScreen ? "-fullScreen" : ""); return