From 1708f2b2a19d3d4efc081bcc4ee82b4d5149da08 Mon Sep 17 00:00:00 2001 From: loudonclear Date: Tue, 4 Jun 2019 19:08:01 -0400 Subject: YES --- src/server/index.ts | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'src/server/index.ts') diff --git a/src/server/index.ts b/src/server/index.ts index fd66c90b4..9f95df4e0 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'; +import * as Pdfjs from 'pdfjs-dist'; const imageDataUri = require('image-data-uri'); import * as mobileDetect from 'mobile-detect'; import { ObservableMap } from 'mobx'; @@ -28,6 +29,7 @@ import { MessageStore, Transferable, Types, Diff } from "./Message"; import { RouteStore } from './RouteStore'; const app = express(); const config = require('../../webpack.config'); +import { createCanvas, loadImage, Canvas } from "canvas"; const compiler = webpack(config); const port = 1050; // default port to listen const serverPort = 4321; @@ -168,7 +170,31 @@ addSecureRoute( RouteStore.getCurrUser ); +class NodeCanvasFactory { + create = (width: number, height: number) => { + var canvas = createCanvas(width, height); + var context = canvas.getContext('2d'); + return { + canvas: canvas, + context: context, + }; + } + + reset = (canvasAndContext: any, width: number, height: number) => { + canvasAndContext.canvas.width = width; + canvasAndContext.canvas.height = height; + } + + destroy = (canvasAndContext: any) => { + canvasAndContext.canvas.width = 0; + canvasAndContext.canvas.height = 0; + canvasAndContext.canvas = null; + canvasAndContext.context = null; + } +} + const pngTypes = [".png", ".PNG"]; +const pdfTypes = [".pdf", ".PDF"]; const jpgTypes = [".jpg", ".JPG", ".jpeg", ".JPEG"]; const uploadDir = __dirname + "/public/files/"; // SETTERS @@ -203,6 +229,38 @@ app.post( }); isImage = true; } + else if (pdfTypes.includes(ext)) { + Pdfjs.getDocument(uploadDir + file).promise + .then((pdf: Pdfjs.PDFDocumentProxy) => { + let numPages = pdf.numPages; + let factory = new NodeCanvasFactory(); + for (let pageNum = 0; pageNum < numPages; pageNum++) { + console.log(pageNum); + pdf.getPage(pageNum + 1).then((page: Pdfjs.PDFPageProxy) => { + console.log("reading " + pageNum); + let viewport = page.getViewport(1); + let canvasAndContext = factory.create(viewport.width, viewport.height); + let renderContext = { + canvasContext: canvasAndContext.context, + viewport: viewport, + canvasFactory: factory + } + console.log("read " + pageNum); + + page.render(renderContext).promise + .then(() => { + console.log("saving " + pageNum); + let stream = canvasAndContext.canvas.createPNGStream(); + let out = fs.createWriteStream(uploadDir + file.substring(0, file.length - ext.length) + `-${pageNum + 1}.PNG`); + stream.pipe(out); + out.on("finish", () => console.log(`Success! Saved to ${uploadDir + file.substring(0, file.length - ext.length) + `-${pageNum + 1}.PNG`}`)); + }, (reason: string) => { + console.error(reason + ` ${pageNum}`); + }); + }); + } + }); + } 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)); -- cgit v1.2.3-70-g09d2 From 96f30f9beda568cf4d8687d07cbdd5467ab05b1b Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 16 Jun 2019 19:08:08 -0400 Subject: better virtualization --- package.json | 1 + src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 47 ++++++++------ src/server/index.ts | 122 ++++++++++++++++++++++++++++--------- 4 files changed, 122 insertions(+), 50 deletions(-) (limited to 'src/server/index.ts') diff --git a/package.json b/package.json index 0fe26f16d..7fd6c4ba9 100644 --- a/package.json +++ b/package.json @@ -142,6 +142,7 @@ "passport": "^0.4.0", "passport-local": "^1.0.0", "pdfjs-dist": "^2.0.943", + "probe-image-size": "^4.0.0", "prosemirror-commands": "^1.0.7", "prosemirror-example-setup": "^1.0.1", "prosemirror-history": "^1.0.4", diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 243982a3b..655c12ab3 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -111,7 +111,7 @@ export class PDFBox extends DocComponent(PdfDocumen }} ref={this.createRef} onWheel={(e: React.WheelEvent) => e.stopPropagation()} className={classname}> - + {/*
*/} ); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 55d15893a..75c298f55 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -20,6 +20,9 @@ import { emptyFunction, returnTrue, returnFalse } from "../../../Utils"; import { DocumentView } from "../nodes/DocumentView"; import { DragManager } from "../../util/DragManager"; import { Dictionary } from "typescript-collections"; +import * as rp from "request-promise"; +import { restProperty } from "babel-types"; +import { DocServer } from "../../DocServer"; export const scale = 2; interface IPDFViewerProps { @@ -137,7 +140,8 @@ class Viewer extends React.Component { } setTimeout(() => { - this.renderPages(this.startIndex, this.endIndex, true); + // this.renderPages(this.startIndex, this.endIndex, true); + this.saveThumbnail(); }, 1000); } @@ -204,17 +208,19 @@ class Viewer extends React.Component { } @action - saveThumbnail = () => { + saveThumbnail = async () => { // file address of the pdf const address: string = this.props.url; for (let i = 0; i < this._visibleElements.length; i++) { if (this._isPage[i]) { // change the address to be the file address of the PNG version of each page - let thisAddress = `${address.substring(0, address.length - ".pdf".length)}-${i + 1}.PNG`; - let nWidth = this._pageSizes[i].width; - let nHeight = this._pageSizes[i].height; + let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${i + 1}.PNG`))); + let thisAddress = res.path; + let nWidth = parseInt(res.width); + let nHeight = parseInt(res.height); // replace page with image - this._visibleElements[i] = ; + runInAction(() => + this._visibleElements[i] = ); } } } @@ -236,6 +242,7 @@ class Viewer extends React.Component { if (this.scrollY !== prevProps.scrollY || this._pdf !== this.props.pdf) { this._pdf = this.props.pdf; // render pages if the scorll position changes + console.log(`START: ${this.startIndex}, END: ${this.endIndex}`); this.renderPages(this.startIndex, this.endIndex); } } @@ -269,7 +276,7 @@ class Viewer extends React.Component { // this is only for an initial render to get all of the pages rendered if (this._visibleElements.length !== numPages) { - let divs = Array.from(Array(numPages).keys()).map(i => ( + let divs = Array.from(Array(numPages).keys()).map(i => i < 5 ? ( { makeAnnotationDocuments={this.makeAnnotationDocument} receiveAnnotations={this.sendAnnotations} {...this.props} /> - )); - let arr = Array.from(Array(numPages).keys()).map(() => false); + ) : + (
) + ); + let arr = Array.from(Array(numPages).keys()).map(i => i < 5); this._visibleElements.push(...divs); this._isPage.push(...arr); } @@ -378,16 +387,16 @@ class Viewer extends React.Component { // get the page index that the vertical offset passed in is on getIndex = (vOffset: number) => { - if (this._loaded) { - let numPages = this.props.pdf ? this.props.pdf.numPages : 0; - let index = 0; - let currOffset = vOffset; - while (index < numPages && currOffset - this._pageSizes[index].height > 0) { - currOffset -= this._pageSizes[index].height; - index++; - } - return index; - } + // if (this._loaded) { + let numPages = this.props.pdf ? this.props.pdf.numPages : 0; + let index = 0; + let currOffset = vOffset; + while (index < numPages && currOffset - (this._pageSizes[index] ? this._pageSizes[index].height : 792 * scale) > 0) { + currOffset -= this._pageSizes[index].height; + index++; + } + return index; + // } return 0; } diff --git a/src/server/index.ts b/src/server/index.ts index e22794df1..3e51eb4ff 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -38,8 +38,10 @@ import c = require("crypto"); import { Search } from './Search'; import { debug } from 'util'; import _ = require('lodash'); +import { Response } from 'express-serve-static-core'; const MongoStore = require('connect-mongo')(session); const mongoose = require('mongoose'); +const probe = require("probe-image-size"); const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest)); @@ -134,6 +136,66 @@ app.get("/search", async (req, res) => { res.send(results); }); +app.get("/thumbnail/:filename", (req, res) => { + let filename = req.params.filename; + let noExt = filename.substring(0, filename.length - ".png".length); + let pagenumber = parseInt(noExt[noExt.length - 1]); + fs.exists(uploadDir + filename, (exists: boolean) => { + console.log(`${uploadDir + filename} ${exists ? "exists" : "does not exist"}`); + if (exists) { + let input = fs.createReadStream(uploadDir + filename); + probe(input, (err: any, result: any) => { + if (err) { + console.log(err); + return; + } + console.log(result.width); + console.log(result.height); + res.send({ path: "/files/" + filename, width: result.width, height: result.height }); + }); + } + else { + LoadPage(uploadDir + filename.substring(0, filename.length - "-n.png".length) + ".pdf", pagenumber, res); + } + }); +}); + +function LoadPage(file: string, pageNumber: number, res: Response) { + console.log(file); + Pdfjs.getDocument(file).promise + .then((pdf: Pdfjs.PDFDocumentProxy) => { + let factory = new NodeCanvasFactory(); + console.log(pageNumber); + pdf.getPage(pageNumber).then((page: Pdfjs.PDFPageProxy) => { + console.log("reading " + page); + let viewport = page.getViewport(1); + let canvasAndContext = factory.create(viewport.width, viewport.height); + let renderContext = { + canvasContext: canvasAndContext.context, + viewport: viewport, + canvasFactory: factory + } + console.log("read " + pageNumber); + + page.render(renderContext).promise + .then(() => { + console.log("saving " + pageNumber); + let stream = canvasAndContext.canvas.createPNGStream(); + let pngFile = `${file.substring(0, file.length - ".pdf".length)}-${pageNumber}.PNG`; + let out = fs.createWriteStream(pngFile); + stream.pipe(out); + out.on("finish", () => { + console.log(`Success! Saved to ${pngFile}`); + let name = path.basename(pngFile); + res.send({ path: "/files/" + name, width: viewport.width, height: viewport.height }); + }); + }, (reason: string) => { + console.error(reason + ` ${pageNumber}`); + }); + }); + }); +} + // anyone attempting to navigate to localhost at this port will // first have to login addSecureRoute( @@ -229,36 +291,36 @@ app.post( isImage = true; } else if (pdfTypes.includes(ext)) { - Pdfjs.getDocument(uploadDir + file).promise - .then((pdf: Pdfjs.PDFDocumentProxy) => { - let numPages = pdf.numPages; - let factory = new NodeCanvasFactory(); - for (let pageNum = 0; pageNum < numPages; pageNum++) { - console.log(pageNum); - pdf.getPage(pageNum + 1).then((page: Pdfjs.PDFPageProxy) => { - console.log("reading " + pageNum); - let viewport = page.getViewport(1); - let canvasAndContext = factory.create(viewport.width, viewport.height); - let renderContext = { - canvasContext: canvasAndContext.context, - viewport: viewport, - canvasFactory: factory - } - console.log("read " + pageNum); - - page.render(renderContext).promise - .then(() => { - console.log("saving " + pageNum); - let stream = canvasAndContext.canvas.createPNGStream(); - let out = fs.createWriteStream(uploadDir + file.substring(0, file.length - ext.length) + `-${pageNum + 1}.PNG`); - stream.pipe(out); - out.on("finish", () => console.log(`Success! Saved to ${uploadDir + file.substring(0, file.length - ext.length) + `-${pageNum + 1}.PNG`}`)); - }, (reason: string) => { - console.error(reason + ` ${pageNum}`); - }); - }); - } - }); + // Pdfjs.getDocument(uploadDir + file).promise + // .then((pdf: Pdfjs.PDFDocumentProxy) => { + // let numPages = pdf.numPages; + // let factory = new NodeCanvasFactory(); + // for (let pageNum = 0; pageNum < numPages; pageNum++) { + // console.log(pageNum); + // pdf.getPage(pageNum + 1).then((page: Pdfjs.PDFPageProxy) => { + // console.log("reading " + pageNum); + // let viewport = page.getViewport(1); + // let canvasAndContext = factory.create(viewport.width, viewport.height); + // let renderContext = { + // canvasContext: canvasAndContext.context, + // viewport: viewport, + // canvasFactory: factory + // } + // console.log("read " + pageNum); + + // page.render(renderContext).promise + // .then(() => { + // console.log("saving " + pageNum); + // let stream = canvasAndContext.canvas.createPNGStream(); + // let out = fs.createWriteStream(uploadDir + file.substring(0, file.length - ext.length) + `-${pageNum + 1}.PNG`); + // stream.pipe(out); + // out.on("finish", () => console.log(`Success! Saved to ${uploadDir + file.substring(0, file.length - ext.length) + `-${pageNum + 1}.PNG`}`)); + // }, (reason: string) => { + // console.error(reason + ` ${pageNum}`); + // }); + // }); + // } + // }); } if (isImage) { resizers.forEach(resizer => { -- cgit v1.2.3-70-g09d2 From e1f88e962cce91d9bcd6900163756934bc5a09a8 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 16 Jun 2019 20:12:33 -0400 Subject: fix --- src/server/index.ts | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/server/index.ts') diff --git a/src/server/index.ts b/src/server/index.ts index 3e51eb4ff..b91c91282 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -149,8 +149,6 @@ app.get("/thumbnail/:filename", (req, res) => { console.log(err); return; } - console.log(result.width); - console.log(result.height); res.send({ path: "/files/" + filename, width: result.width, height: result.height }); }); } -- cgit v1.2.3-70-g09d2 From 8c64ffd92e382050bc8727981cf9fb830e4f02a7 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 17 Jun 2019 23:04:07 -0400 Subject: Added share with user functionality --- src/client/views/nodes/DocumentView.tsx | 48 +++++++++++++++++++++++++-------- src/client/views/nodes/FieldView.tsx | 2 +- src/server/RouteStore.ts | 1 + src/server/database.ts | 4 +-- src/server/index.ts | 11 ++++++++ 5 files changed, 52 insertions(+), 14 deletions(-) (limited to 'src/server/index.ts') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9d0206e48..942228e71 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,11 +1,11 @@ import { library } from '@fortawesome/fontawesome-svg-core'; 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, trace, observable } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; -import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, Utils } from "../../../Utils"; @@ -26,10 +26,12 @@ import { DocComponent } from "../DocComponent"; import { PresentationView } from "../PresentationView"; import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; +import * as rp from "request-promise"; import "./DocumentView.scss"; import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { ContextMenuProps } from '../ContextMenuItem'; +import { RouteStore } from '../../../server/RouteStore'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); @@ -452,7 +454,8 @@ export class DocumentView extends DocComponent(Docu } @action - onContextMenu = (e: React.MouseEvent): void => { + onContextMenu = async (e: React.MouseEvent): Promise => { + e.persist(); e.stopPropagation(); if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 || e.isDefaultPrevented()) { @@ -483,14 +486,37 @@ export class DocumentView extends DocComponent(Docu 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 - e.stopPropagation(); - } - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!SelectionManager.IsSelected(this)) { - SelectionManager.SelectDoc(this, false); - } + type User = { email: string, userDocumentId: string }; + const users: User[] = JSON.parse(await rp.get(DocServer.prepend(RouteStore.getUsers))); + let usersMenu: ContextMenuProps[] = users.filter(({ email }) => email !== CurrentUserUtils.email).map(({ email, userDocumentId }) => ({ + description: email, event: async () => { + const userDocument = await Cast(DocServer.GetRefField(userDocumentId), Doc); + if (!userDocument) { + throw new Error(`Couldn't get user document of user ${email}`); + } + const notifDoc = await Cast(userDocument.optionalRightCollection, Doc); + if (notifDoc instanceof Doc) { + const data = await Cast(notifDoc.data, listSpec(Doc)); + const sharedDoc = Doc.MakeAlias(this.props.Document); + if (data) { + data.push(sharedDoc); + } else { + notifDoc.data = new List([sharedDoc]); + } + } + } + })); + runInAction(() => { + cm.addItem({ description: "Share...", subitems: usersMenu }); + if (!this.topMost) { + // DocumentViews should stop propagation of this event + e.stopPropagation(); + } + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + if (!SelectionManager.IsSelected(this)) { + SelectionManager.SelectDoc(this, false); + } + }); } onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index cf6d2012f..4738e90d7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -109,7 +109,7 @@ export class FieldView extends React.Component { } else if (field instanceof List) { return (
- {field.map(f => f instanceof Doc ? f.title : f.toString()).join(", ")} + {field.map(f => f instanceof Doc ? f.title : (f && f.toString && f.toString())).join(", ")}
); } // bcz: this belongs here, but it doesn't render well so taking it out for now diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts index c4af5cdaa..5c13495ff 100644 --- a/src/server/RouteStore.ts +++ b/src/server/RouteStore.ts @@ -16,6 +16,7 @@ export enum RouteStore { // USER AND WORKSPACES getCurrUser = "/getCurrentUser", + getUsers = "/getUsers", getUserDocumentId = "/getUserDocumentId", updateCursor = "/updateCursor", diff --git a/src/server/database.ts b/src/server/database.ts index 70b3efced..d240bd909 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -120,9 +120,9 @@ export class Database { } } - public query(query: any): Promise { + public query(query: any, collectionName = "newDocuments"): Promise { if (this.db) { - return Promise.resolve(this.db.collection('newDocuments').find(query)); + return Promise.resolve(this.db.collection(collectionName).find(query)); } else { return new Promise(res => { this.onConnect.push(() => res(this.query(query))); diff --git a/src/server/index.ts b/src/server/index.ts index b91c91282..7ef542b01 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -203,6 +203,17 @@ addSecureRoute( RouteStore.root ); +addSecureRoute( + Method.GET, + async (_, res) => { + const cursor = await Database.Instance.query({}, "users"); + const results = await cursor.toArray(); + res.send(results.map(user => ({ email: user.email, userDocumentId: user.userDocumentId }))); + }, + undefined, + RouteStore.getUsers +); + addSecureRoute( Method.GET, (user, res, req) => { -- cgit v1.2.3-70-g09d2 From 13e301dea2f537b67b338cc6a98d3f3b5a8e1f36 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Tue, 18 Jun 2019 20:58:32 -0400 Subject: Fixed linter errors --- src/client/northstar/dash-nodes/HistogramBox.tsx | 3 +-- src/client/util/DocumentManager.ts | 6 +++--- src/client/util/DragManager.ts | 4 +++- src/client/util/RichTextSchema.tsx | 10 +++++----- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/views/ContextMenu.tsx | 4 ++-- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/MainOverlayTextBox.tsx | 2 +- src/client/views/MainView.tsx | 7 ++++--- src/client/views/PresentationView.tsx | 4 ++-- src/client/views/collections/CollectionBaseView.tsx | 2 +- src/client/views/collections/CollectionDockingView.tsx | 5 +++-- src/client/views/collections/CollectionPDFView.tsx | 2 +- src/client/views/collections/CollectionSchemaView.tsx | 11 ++++++----- src/client/views/collections/CollectionStackingView.tsx | 4 ++-- src/client/views/collections/CollectionTreeView.tsx | 10 +++++----- .../collectionFreeForm/CollectionFreeFormLinksView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 12 ++++++------ src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 3 ++- src/client/views/pdf/PDFAnnotationLayer.tsx | 2 +- src/client/views/pdf/PDFMenu.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 4 ++-- src/server/index.ts | 2 +- 27 files changed, 59 insertions(+), 54 deletions(-) (limited to 'src/server/index.ts') diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index d7732ee86..a60eaea85 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -125,8 +125,7 @@ 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; + if (!brushed.length) return null; return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; }); runInAction(() => this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped.filter(m => m) as { l: Doc, b: Doc }[])); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index ff0c1560b..862395d74 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -35,9 +35,9 @@ export class DocumentManager { let toReturn: DocumentView | null = null; let passes = preferredCollection ? [preferredCollection, undefined] : [undefined]; - for (let i = 0; i < passes.length; i++) { + for (let pass of passes) { DocumentManager.Instance.DocumentViews.map(view => { - if (view.props.Document[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { + if (view.props.Document[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; return; } @@ -45,7 +45,7 @@ export class DocumentManager { if (!toReturn) { DocumentManager.Instance.DocumentViews.map(view => { let doc = view.props.Document.proto; - if (doc && doc[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) { + if (doc && doc[Id] === id && (!pass || view.props.ContainingCollectionView === preferredCollection)) { toReturn = view; } }); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 89566e777..c3c92daa5 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -282,11 +282,13 @@ export namespace DragManager { // } let set = dragElement.getElementsByTagName('*'); if (dragElement.hasAttribute("style")) (dragElement as any).style.pointerEvents = "none"; - for (let i = 0; i < set.length; i++) + // tslint:disable-next-line: prefer-for-of + for (let i = 0; i < set.length; i++) { if (set[i].hasAttribute("style")) { let s = set[i]; (s as any).style.pointerEvents = "none"; } + } dragDiv.appendChild(dragElement); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index e1e595925..943cdb4d1 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -156,12 +156,12 @@ export const nodes: { [index: string]: NodeSpec } = { title: dom.getAttribute("title"), alt: dom.getAttribute("alt"), width: Math.min(100, Number(dom.getAttribute("width"))), - } + }; } }], toDOM(node) { - const attrs = { style: `width: ${node.attrs.width}` } - return ["video", { ...node.attrs, ...attrs }] + const attrs = { style: `width: ${node.attrs.width}` }; + return ["video", { ...node.attrs, ...attrs }]; } }, @@ -285,7 +285,7 @@ export const marks: { [index: string]: MarkSpec } = { toDOM() { return ['span', { style: 'color: blue' - }] + }]; } }, @@ -536,4 +536,4 @@ schema.nodeFromJSON = (json: any) => { node.attrs.oldtext = Slice.fromJSON(schema, node.attrs.oldtextslice); } return node; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 0a61b7e7d..f2559db74 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -256,7 +256,7 @@ export class TooltipTextMenu { starButton.onclick = () => { let state = this.view.state; this.insertStar(state, this.view.dispatch); - } + }; this.tooltip.appendChild(starButton); } diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index da374455e..eb1937683 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -1,8 +1,8 @@ import React = require("react"); import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem"; import { observable, action } from "mobx"; -import { observer } from "mobx-react" -import "./ContextMenu.scss" +import { observer } from "mobx-react"; +import "./ContextMenu.scss"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSearch, faCircle } from '@fortawesome/free-solid-svg-icons'; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index ceca940b6..e60f8c86c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -466,7 +466,7 @@ 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 && (dX != 0 || dY != 0 || dW != 0 || dH != 0)) { + if (rect.width !== 0 && (dX !== 0 || dY !== 0 || dW !== 0 || dH !== 0)) { let doc = PositionDocument(element.props.Document); let nwidth = doc.nativeWidth || 0; let nheight = doc.nativeHeight || 0; diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 0de880175..b4ad5f4d7 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -40,7 +40,7 @@ export class MainOverlayTextBox extends React.Component this.TextDoc = box.props.Document; let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined); let xf = () => { box.props.ScreenToLocalTransform(); return new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale); }; - this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content") + this.setTextDoc(box.props.fieldKey, box.CurrentDiv, xf, BoolCast(box.props.Document.autoHeight, false) || box.props.height === "min-content"); } else { this.TextDoc = undefined; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index fd76cbbd3..7f979cd3b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -237,10 +237,11 @@ export class MainView extends React.Component { } onColorClick = (e: React.MouseEvent) => { - let target = (e.nativeEvent! as any).path[0]; - let parent = (e.nativeEvent! as any).path[1]; - if (target.localName === "input" || parent.localName === "span") + let target = (e.nativeEvent as any).path[0]; + let parent = (e.nativeEvent as any).path[1]; + if (target.localName === "input" || parent.localName === "span") { e.stopPropagation(); + } } diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index d2d41a4ba..1dacbb663 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -40,8 +40,8 @@ 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; } + let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; }; + let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; }; return (
{ @action.bound removeDocument(doc: Doc): boolean { - let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView) + let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView); docView && SelectionManager.DeselectDoc(docView); const props = this.props; //TODO This won't create the field if it doesn't already exist diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index f2b3528b8..5beb89315 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -347,7 +347,7 @@ export class CollectionDockingView extends React.Component CollectionDockingView.Instance.AddTab(stack, doc)} />, upDiv); tab.reactComponents = [upDiv]; tab.element.append(upDiv); @@ -432,8 +432,9 @@ export class DockedFrameRenderer extends React.Component { @observable private _document: Opt; get _stack(): any { let parent = (this.props as any).glContainer.parent.parent; - if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) + if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1) { return parent.parent.contentItems[1]; + } return parent; } constructor(props: any) { diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index b62d3f7bb..b2d016934 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -40,7 +40,7 @@ export class CollectionPDFView extends React.Component { // console.log(this.props.Document[HeightSym]()); }, { fireImmediately: true } - ) + ); } public static LayoutString(fieldKey: string = "data") { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 14a7d19d0..faea8d44d 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -87,8 +87,9 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let columnDocs = DocListCast(schemaDoc.data); if (columnDocs) { let ddoc = columnDocs.find(doc => doc.title === columnName); - if (ddoc) + if (ddoc) { return ddoc; + } } } return this.props.Document; @@ -285,7 +286,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate( - - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth); + - this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth) get documentKeysCheckList() { @@ -334,7 +335,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { columns={this.tableColumns} column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} - /> + />; } @computed @@ -360,7 +361,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { addDocTab={this.props.addDocTab} setPreviewScript={this.setPreviewScript} previewScript={this.previewScript} - /> + />; } @action setPreviewScript = (script: string) => { @@ -409,7 +410,7 @@ export class CollectionSchemaPreview extends React.Component this.nativeWidth * this.contentScaling(); private PanelHeight = () => this.nativeHeight * this.contentScaling(); - private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling()) + private getTransform = () => this.props.getTransform().translate(-this.centeringOffset, 0).scale(1 / this.contentScaling()); get centeringOffset() { return (this.props.width() - this.nativeWidth * this.contentScaling()) / 2; } @action onPreviewScriptChange = (e: React.ChangeEvent) => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e1ac3505b..f5ad4ee95 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -101,7 +101,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let childFocus = (doc: Doc) => { doc.libraryBrush = true; this.props.focus(this.props.Document); // just focus on this collection, not the underlying document because the API doesn't support adding an offset to focus on and we can't pan zoom our contents to be centered. - } + }; return (
doc) { whenActiveChanged={this.props.whenActiveChanged} />
); - }) + }); } 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 diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index b13694e9d..3e495b734 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -67,8 +67,8 @@ class TreeView extends React.Component { @undoBatch delete = () => this.props.deleteDoc(this.props.document); @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight"); - @action onMouseEnter = () => { this._isOver = true; } - @action onMouseLeave = () => { this._isOver = false; } + @action onMouseEnter = () => { this._isOver = true; }; + @action onMouseLeave = () => { this._isOver = false; }; onPointerEnter = (e: React.PointerEvent): void => { this.props.active() && (this.props.document.libraryBrush = true); @@ -89,8 +89,8 @@ class TreeView extends React.Component { let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); let before = x[1] < bounds[1]; let inside = x[0] > bounds[0] + 75 || (!before && this._bulletType === BulletType.Collapsible); - this._header!.current!.className = "treeViewItem-header" - if (inside && this._bulletType != BulletType.List) this._header!.current!.className += " treeViewItem-header-inside"; + this._header!.current!.className = "treeViewItem-header"; + if (inside && this._bulletType !== BulletType.List) this._header!.current!.className += " treeViewItem-header-inside"; else if (before) this._header!.current!.className += " treeViewItem-header-above"; else if (!before) this._header!.current!.className += " treeViewItem-header-below"; e.stopPropagation(); @@ -192,7 +192,7 @@ class TreeView extends React.Component { if (inside) { let docList = Cast(this.props.document.data, listSpec(Doc)); if (docList !== undefined) { - addDoc = (doc: Doc) => { docList && docList.push(doc); return true; } + addDoc = (doc: Doc) => { docList && docList.push(doc); return true; }; } } let added = false; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index c4dd534ed..be75c6c5c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -109,7 +109,7 @@ export class CollectionFreeFormLinksView extends React.Component [ , ...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 dedcc3172..05dc6f534 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -321,7 +321,7 @@ export class MarqueeView extends React.Component summary.imageSummary = imageSummary; this.props.addDocument(imageSummary, false); } - }) + }); newCollection.proto!.summaryDoc = summary; selected = [newCollection]; newCollection.x = bounds.left + bounds.width; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index f6b1c62ee..858959d81 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -48,7 +48,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.props.PanelHeight(); getTransform = (): Transform => this.props.ScreenToLocalTransform() .translate(-this.X, -this.Y) - .scale(1 / this.contentScaling()).scale(1 / this.zoom); + .scale(1 / this.contentScaling()).scale(1 / this.zoom) animateBetweenIcon = (icon: number[], stime: number, maximizing: boolean) => { this.props.bringToFront(this.props.Document); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7c058d91c..4992669df 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -168,8 +168,8 @@ export class DocumentView extends DocComponent(Docu public static animateBetweenIconFunc = (doc: Doc, width: number, height: number, stime: number, maximizing: boolean, cb?: (progress: number) => void) => { setTimeout(() => { let now = Date.now(); - let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1 - doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress + let progress = now < stime + 200 ? Math.min(1, (now - stime) / 200) : 1; + doc.width = progress === 1 ? width : maximizing ? 25 + (width - 25) * progress : width + (25 - width) * progress; doc.height = progress === 1 ? height : maximizing ? 25 + (height - 25) * progress : height + (25 - height) * progress; cb && cb(progress); if (now < stime + 200) { @@ -229,7 +229,7 @@ export class DocumentView extends DocComponent(Docu if (minimizedDoc) { let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint( NumCast(minimizedDoc.x) - NumCast(this.Document.x), NumCast(minimizedDoc.y) - NumCast(this.Document.y)); - this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)) + this.collapseTargetsToPoint(scrpt, await DocListCastAsync(minimizedDoc.maximizedDocs)); } } @@ -372,8 +372,8 @@ export class DocumentView extends DocComponent(Docu this._lastTap = Date.now(); } - deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); } - fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") }; + deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); }; + fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight"); }; makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); doc.isButton = !BoolCast(doc.isButton, false); @@ -527,7 +527,7 @@ export class DocumentView extends DocComponent(Docu onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; isSelected = () => SelectionManager.IsSelected(this); - @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); } + @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; @computed get nativeWidth() { return this.Document.nativeWidth || 0; } @computed get nativeHeight() { return this.Document.nativeHeight || 0; } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 36d902c4f..df12f261b 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -161,7 +161,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe de.data.moveDocument(de.data.draggedDocuments[0], stackDoc, (doc) => { Cast(stackDoc.data, listSpec(Doc))!.push(doc); return true; - }) + }); } } } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6b8b64c5f..f208ce2ce 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -188,8 +188,9 @@ export class ImageBox extends DocComponent(ImageD } @action onError = () => { let timeout = this._curSuffix === "_s" ? this._smallRetryCount : this._curSuffix === "_m" ? this._mediumRetryCount : this._largeRetryCount; - if (timeout < 10) + if (timeout < 10) { setTimeout(this.retryPath, Math.min(10000, timeout * 5)); + } } _curSuffix = "_m"; render() { diff --git a/src/client/views/pdf/PDFAnnotationLayer.tsx b/src/client/views/pdf/PDFAnnotationLayer.tsx index e92dcacbf..1f49e0d2f 100644 --- a/src/client/views/pdf/PDFAnnotationLayer.tsx +++ b/src/client/views/pdf/PDFAnnotationLayer.tsx @@ -19,6 +19,6 @@ export class PDFAnnotationLayer extends React.Component {
- ) + ); } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 7817e8c26..2ed891131 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -162,6 +162,6 @@ export default class PDFMenu extends React.Component {
- ) + ); } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 69372f43b..8c0aaea00 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -198,7 +198,7 @@ class Viewer extends React.Component { { @action getPageImage = async (page: number) => { let handleError = () => this.getRenderedPage(page); - if (this._isPage[page] != "image") { + if (this._isPage[page] !== "image") { this._isPage[page] = "image"; const address = this.props.url; let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`))); diff --git a/src/server/index.ts b/src/server/index.ts index 7ef542b01..2901f61ed 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -172,7 +172,7 @@ function LoadPage(file: string, pageNumber: number, res: Response) { canvasContext: canvasAndContext.context, viewport: viewport, canvasFactory: factory - } + }; console.log("read " + pageNumber); page.render(renderContext).promise -- cgit v1.2.3-70-g09d2