diff options
author | Bob Zeleznik <zzzman@gmail.com> | 2019-06-20 22:41:47 -0400 |
---|---|---|
committer | Bob Zeleznik <zzzman@gmail.com> | 2019-06-20 22:41:47 -0400 |
commit | 22e0ae1c7677a1fa3411e5ba05922b1d3b914b17 (patch) | |
tree | afc3dd63e1e4099f2d1ccca6bb766860a000ba66 | |
parent | e495d4e32402384dbf7bb72945e83c912fce892b (diff) | |
parent | 179afa6e80631fcb8899408c3961bf1757e5b19b (diff) |
Merge branch 'master' into templates
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | src/client/util/ClientUtils.ts.temp | 3 | ||||
-rw-r--r-- | src/client/views/Templates.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingView.scss | 13 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 62 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 7 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 18 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 32 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 1 | ||||
-rw-r--r-- | src/client/views/pdf/Page.tsx | 5 | ||||
-rw-r--r-- | src/server/index.ts | 34 |
14 files changed, 126 insertions, 62 deletions
diff --git a/.gitignore b/.gitignore index a499c39a3..5d3100dc6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ node_modules package-lock.json dist/ .DS_Store +.env +ClientUtils.ts
\ No newline at end of file diff --git a/package.json b/package.json index 7fd6c4ba9..91d3a3853 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@types/cookie-parser": "^1.4.1", "@types/cookie-session": "^2.0.36", "@types/d3-format": "^1.3.1", + "@types/dotenv": "^6.1.1", "@types/express": "^4.16.1", "@types/express-flash": "0.0.0", "@types/express-session": "^1.15.12", @@ -110,6 +111,7 @@ "cookie-session": "^2.0.0-beta.3", "crypto-browserify": "^3.11.0", "d3-format": "^1.3.2", + "dotenv": "^8.0.0", "express": "^4.16.4", "express-flash": "0.0.2", "express-session": "^1.15.6", diff --git a/src/client/util/ClientUtils.ts.temp b/src/client/util/ClientUtils.ts.temp new file mode 100644 index 000000000..f9fad5ed9 --- /dev/null +++ b/src/client/util/ClientUtils.ts.temp @@ -0,0 +1,3 @@ +export namespace ClientUtils { + export const RELEASE = "mode"; +}
\ No newline at end of file diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 3d5f7b6ea..a227faa71 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -49,7 +49,7 @@ export namespace Templates { export const Title = new Template("Title", TemplatePosition.InnerTop, `<div> - <div style="height:25px; width:100%; background-color: rgba(0, 0, 0, .4); color: white; "> + <div style="height:25px; width:100%; background-color: rgba(0, 0, 0, .4); color: white; z-index: 100"> <span style="text-align:center;width:100%;font-size:20px;position:absolute;overflow:hidden;white-space:nowrap;text-overflow:ellipsis">{props.Document.title}</span> </div> <div style="height:calc(100% - 25px);"> diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 9a25e090c..05c3cdac6 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -259,6 +259,11 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp @action onPointerDown = (e: React.PointerEvent): void => { this._isPointerDown = true; + let onPointerUp = action(() => { + window.removeEventListener("pointerup", onPointerUp) + this._isPointerDown = false + }) + window.addEventListener("pointerup", onPointerUp); var className = (e.target as any).className; if (className === "messageCounter") { e.stopPropagation(); diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index af194aec9..485ecf1de 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -38,4 +38,17 @@ background: $dark-color; color: $light-color; } + + + .collectionStackingView-columnDoc, + .collectionStackingView-masonryDoc { + margin-left: auto; + margin-right: auto; + } + + .collectionStackingView-masonryDoc { + transform-origin: top left; + grid-column-end: span 1; + height: 100%; + } }
\ No newline at end of file diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 8e61181f4..c855cb43a 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,5 +1,5 @@ import React = require("react"); -import { action, computed, IReactionDisposer, reaction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace } from "mobx"; import { observer } from "mobx-react"; import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; @@ -10,7 +10,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { CollectionSchemaPreview } from "./CollectionSchemaView"; import "./CollectionStackingView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { auto } from "async"; +import { Transform } from "../../util/Transform"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -67,18 +67,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let children = this.childDocs.filter(d => !d.isMinimized); return children.map((d, i) => { let dref = React.createRef<HTMLDivElement>(); - let script = undefined; - let colWidth = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; - let rowHeight = () => this.singleColDocHeight(d); let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]()); - return <div className="collectionStackingView-masonryDoc" + let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; + let height = () => this.singleColDocHeight(d); + return <div className="collectionStackingView-columnDoc" key={d[Id]} ref={dref} - style={{ width: colWidth(), height: rowHeight(), marginLeft: "auto", marginRight: "auto" }} > + style={{ width: width(), height: height() }} > <CollectionSchemaPreview Document={d} - width={colWidth} - height={rowHeight} + width={width} + height={height} getTransform={dxf} CollectionView={this.props.CollectionView} addDocument={this.props.addDocument} @@ -88,7 +87,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { whenActiveChanged={this.props.whenActiveChanged} addDocTab={this.props.addDocTab} setPreviewScript={emptyFunction} - previewScript={script}> + previewScript={undefined}> </CollectionSchemaPreview> </div>; }); @@ -96,48 +95,31 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get children() { return this.childDocs.filter(d => !d.isMinimized).map((d, i) => { + let aspect = d.nativeHeight ? NumCast(d.nativeWidth) / NumCast(d.nativeHeight) : undefined; let dref = React.createRef<HTMLDivElement>(); let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]()); - let renderScale = this.columnWidth / NumCast(d.nativeWidth, this.columnWidth); - let aspect = NumCast(d.nativeWidth) / NumCast(d.nativeHeight); - let width = () => this.columnWidth; + let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; let height = () => aspect ? width() / aspect : d[HeightSym]() let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + this.gridGap)); - 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 (<div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} - style={{ - width: width(), - height: height(), - overflow: "auto", - transformOrigin: "top left", - gridRowEnd: `span ${rowSpan}`, - gridColumnEnd: `span 1`, - transform: `scale(${renderScale})` - }} > - <DocumentView key={d[Id]} + style={{ gridRowEnd: `span ${rowSpan}` }} > + <CollectionSchemaPreview Document={d} - DataDoc={d} + CollectionView={this.props.CollectionView} addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} removeDocument={this.props.removeDocument} - moveDocument={this.moveDocument} - ContainingCollectionView={this.props.CollectionView} - isTopMost={false} - ScreenToLocalTransform={dxf} - focus={childFocus} - ContentScaling={returnOne} - PanelWidth={width} - PanelHeight={height} - selectOnLoad={false} - parentActive={this.props.active} + getTransform={dxf} + width={width} + height={height} + active={this.props.active} addDocTab={this.props.addDocTab} - bringToFront={emptyFunction} whenActiveChanged={this.props.whenActiveChanged} - /> + setPreviewScript={emptyFunction} + previewScript={undefined}> + </CollectionSchemaPreview> </div>); }); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index e55cd9e37..699bddc7c 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -176,8 +176,11 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { return; } if (html && !html.startsWith("<a")) { - if (html.indexOf("<img") === 0) { - let split = html.split("\"")[1]; + let tags = html.split("<"); + if (tags[0] === "") tags.splice(0, 1); + let img = tags[0].startsWith("img") ? tags[0] : tags.length > 1 && tags[1].startsWith("img") ? tags[1] : ""; + if (img) { + let split = img.split("src=\"")[1].split("\"")[0]; let doc = Docs.ImageDocument(split, { ...options, width: 300 }); this.props.addDocument(doc, false); return; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 443c763bf..eaa3add40 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -70,9 +70,9 @@ class TreeView extends React.Component<TreeViewProps> { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight"); + @undoBatch openRight = async () => this.props.addDocTab(this.props.document, "onRight"); - onPointerDown = (e: React.PointerEvent) => e.stopPropagation() + onPointerDown = (e: React.PointerEvent) => e.stopPropagation(); onPointerEnter = (e: React.PointerEvent): void => { this.props.active() && (this.props.document.libraryBrush = true); if (e.buttons === 1 && SelectionManager.GetIsDragging()) { @@ -114,11 +114,11 @@ class TreeView extends React.Component<TreeViewProps> { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); } @action - indent = () => this.props.addDocument(this.props.document) && this.delete(); + indent = () => this.props.addDocument(this.props.document) && this.delete() renderBullet() { - let docList = Cast(this.props.document["data"], listSpec(Doc)); - let doc = Cast(this.props.document["data"], Doc); + let docList = Cast(this.props.document.data, listSpec(Doc)); + let doc = Cast(this.props.document.data, Doc); let isDoc = doc instanceof Doc || docList; return <div className="bullet" onClick={action(() => this._collapsed = !this._collapsed)}> {<FontAwesomeIcon icon={this._collapsed ? (isDoc ? "caret-square-right" : "caret-right") : (isDoc ? "caret-square-down" : "caret-down")} />} @@ -288,7 +288,7 @@ class TreeView extends React.Component<TreeViewProps> { addDocTab={this.props.addDocTab} setPreviewScript={emptyFunction}> </CollectionSchemaPreview> - </div> + </div>; } } return <div className="treeViewItem-container" ref={this.createTreeDropTarget} onContextMenu={this.onWorkspaceContextMenu}> @@ -327,14 +327,14 @@ class TreeView extends React.Component<TreeViewProps> { Doc.AddDocToList(docList[i - 1], fieldKey, child); remove(child); } - } + }; let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => { return add(doc, relativeTo ? relativeTo : docList[i], before !== undefined ? before : false); - } + }; let rowHeight = () => { let aspect = NumCast(child.nativeWidth, 0) / NumCast(child.nativeHeight, 0); return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym](); - } + }; return <TreeView document={child} treeViewId={treeViewId} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 013c11837..bf47195d9 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,6 @@ import { action, computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc, HeightSym, WidthSym } from "../../../../new_fields/Doc"; +import { Doc, HeightSym, WidthSym, DocListCastAsync } from "../../../../new_fields/Doc"; import { Id } from "../../../../new_fields/FieldSymbols"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { createSchema, makeInterface } from "../../../../new_fields/Schema"; @@ -26,6 +26,7 @@ import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); import PDFMenu from "../../pdf/PDFMenu"; +import { ContextMenu } from "../../ContextMenu"; export const panZoomSchema = createSchema({ panX: "number", @@ -340,6 +341,33 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY)); } + onContextMenu = () => { + ContextMenu.Instance.addItem({ + description: "Arrange contents in grid", + event: async () => { + const docs = await DocListCastAsync(this.Document[this.props.fieldKey]); + if (docs) { + let startX = this.Document.panX || 0; + let x = startX; + let y = this.Document.panY || 0; + let i = 0; + const width = Math.max(...docs.map(doc => NumCast(doc.width))); + const height = Math.max(...docs.map(doc => NumCast(doc.height))); + for (const doc of docs) { + doc.x = x; + doc.y = y; + x += width + 20; + if (++i === 6) { + i = 0; + x = startX; + y += height + 20; + } + } + } + } + }); + } + private childViews = () => [ <CollectionFreeFormBackgroundView key="backgroundView" {...this.props} {...this.getDocumentViewProps(this.props.Document)} />, ...this.views @@ -350,7 +378,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { return ( <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel} style={{ borderRadius: "inherit" }} - onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} > + onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onContextMenu={this.onContextMenu}> <MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} isSelected={this.props.isSelected} addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox} getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 93b883533..da50d0b53 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -238,7 +238,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu static _undoBatch?: UndoManager.Batch = undefined; @action - public collapseTargetsToPoint = async (scrpt: number[], expandedDocs: Doc[] | undefined): Promise<void> => { + public collapseTargetsToPoint = (scrpt: number[], expandedDocs: Doc[] | undefined): void => { SelectionManager.DeselectAll(); if (expandedDocs) { if (!DocumentView._undoBatch) { diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 7000352e7..6adead626 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -203,6 +203,7 @@ class Viewer extends React.Component<IViewerProps> { this._isPage[page] = "page"; this._visibleElements[page] = ( <Page + size={this._pageSizes[page]} pdf={this.props.pdf} page={page} numPages={this.props.pdf.numPages} diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 734dff7fc..b6f362702 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -19,6 +19,7 @@ import { UndoManager } from "../../util/UndoManager"; interface IPageProps { + size: { width: number, height: number }; pdf: Opt<Pdfjs.PDFDocumentProxy>; name: string; numPages: number; @@ -36,8 +37,8 @@ interface IPageProps { @observer export default class Page extends React.Component<IPageProps> { @observable private _state: string = "N/A"; - @observable private _width: number = 0; - @observable private _height: number = 0; + @observable private _width: number = this.props.size.width; + @observable private _height: number = this.props.size.height; @observable private _page: Opt<Pdfjs.PDFPageProxy>; @observable private _currPage: number = this.props.page + 1; @observable private _marqueeX: number = 0; diff --git a/src/server/index.ts b/src/server/index.ts index 2901f61ed..e645e29b4 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,3 +1,4 @@ +require('dotenv').config(); import * as bodyParser from 'body-parser'; import { exec } from 'child_process'; import * as cookieParser from 'cookie-parser'; @@ -45,6 +46,17 @@ const probe = require("probe-image-size"); const download = (url: string, dest: fs.PathLike) => request.get(url).pipe(fs.createWriteStream(dest)); +const release = process.env.RELEASE === "true"; +if (process.env.RELEASE === "true") { + console.log("Running server in release mode"); +} else { + console.log("Running server in debug mode"); +} +console.log(process.env.PWD); +let clientUtils = fs.readFileSync("./src/client/util/ClientUtils.ts.temp", "utf8"); +clientUtils = `//AUTO-GENERATED FILE: DO NOT EDIT\n${clientUtils.replace('"mode"', String(release))}`; +fs.writeFileSync("./src/client/util/ClientUtils.ts", clientUtils, "utf8"); + const mongoUrl = 'mongodb://localhost:27017/Dash'; mongoose.connect(mongoUrl); mongoose.connection.on('connected', () => console.log("connected")); @@ -406,11 +418,21 @@ app.post(RouteStore.reset, postReset); app.use(RouteStore.corsProxy, (req, res) => req.pipe(request(req.url.substring(1))).pipe(res)); -app.get(RouteStore.delete, (req, res) => - deleteFields().then(() => res.redirect(RouteStore.home))); +app.get(RouteStore.delete, (req, res) => { + if (release) { + res.send("no"); + return; + } + deleteFields().then(() => res.redirect(RouteStore.home)); +}); -app.get(RouteStore.deleteAll, (req, res) => - deleteAll().then(() => res.redirect(RouteStore.home))); +app.get(RouteStore.deleteAll, (req, res) => { + if (release) { + res.send("no"); + return; + } + deleteAll().then(() => res.redirect(RouteStore.home)); +}); app.use(wdm(compiler, { publicPath: config.output.publicPath })); @@ -435,7 +457,9 @@ server.on("connection", function (socket: Socket) { 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, deleteFields); + if (!release) { + Utils.AddServerHandler(socket, MessageStore.DeleteAll, deleteFields); + } Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField); Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff)); |