From a4fa90e0d376a993392c0eff143a5c387e387980 Mon Sep 17 00:00:00 2001 From: Andrew Kim Date: Sun, 17 Mar 2019 00:15:40 -0400 Subject: testing mobile image --- src/.DS_Store | Bin 6148 -> 6148 bytes src/client/documents/Documents.ts | 12 +- src/client/util/TooltipTextMenu.scss | 7 +- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/views/.DS_Store | Bin 6148 -> 8196 bytes src/client/views/ContextMenu.scss | 77 +++-- src/client/views/ContextMenu.tsx | 16 +- src/client/views/DocumentDecorations.scss | 85 ++++- src/client/views/DocumentDecorations.tsx | 17 +- src/client/views/EditableView.scss | 6 + src/client/views/EditableView.tsx | 3 +- src/client/views/InkingCanvas.scss | 131 ++++++- src/client/views/InkingCanvas.tsx | 28 +- src/client/views/InkingControl.tsx | 66 +++- src/client/views/InkingStroke.tsx | 2 - src/client/views/Main.scss | 139 +++++++- src/client/views/Main.tsx | 96 ++++-- src/client/views/_global_variables.scss | 17 + src/client/views/_nodeModuleOverrides.scss | 23 ++ .../views/collections/CollectionFreeFormView.scss | 104 ++++-- .../views/collections/CollectionFreeFormView.tsx | 20 +- .../views/collections/CollectionPDFView.scss | 27 ++ src/client/views/collections/CollectionPDFView.tsx | 26 +- .../views/collections/CollectionSchemaView.scss | 383 +++++++++++---------- .../views/collections/CollectionSchemaView.tsx | 32 +- .../views/collections/CollectionTreeView.scss | 32 +- .../views/collections/CollectionTreeView.tsx | 25 +- .../views/collections/CollectionVideoView.scss | 40 +++ .../views/collections/CollectionVideoView.tsx | 86 ++++- src/client/views/collections/CollectionView.tsx | 9 +- src/client/views/collections/MarqueeView.tsx | 49 ++- src/client/views/collections/PreviewCursor.tsx | 8 +- src/client/views/nodes/AudioBox.tsx | 12 +- src/client/views/nodes/DocumentContentsView.tsx | 35 ++ src/client/views/nodes/DocumentView.scss | 44 +-- src/client/views/nodes/DocumentView.tsx | 22 +- src/client/views/nodes/FieldTextBox.scss | 14 +- src/client/views/nodes/FormattedTextBox.scss | 64 ++-- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/ImageBox.scss | 25 +- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.scss | 42 +-- src/client/views/nodes/LinkBox.scss | 42 ++- src/client/views/nodes/LinkBox.tsx | 19 +- src/client/views/nodes/LinkEditor.scss | 22 +- src/client/views/nodes/LinkMenu.scss | 1 + src/client/views/nodes/LinkMenu.tsx | 4 +- src/client/views/nodes/PDFBox.scss | 2 +- src/client/views/nodes/PDFBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 18 +- src/fields/KeyStore.ts | 3 +- 51 files changed, 1386 insertions(+), 557 deletions(-) create mode 100644 src/client/views/EditableView.scss create mode 100644 src/client/views/_global_variables.scss create mode 100644 src/client/views/_nodeModuleOverrides.scss create mode 100644 src/client/views/collections/CollectionPDFView.scss create mode 100644 src/client/views/collections/CollectionVideoView.scss create mode 100644 src/client/views/nodes/DocumentContentsView.tsx (limited to 'src') diff --git a/src/.DS_Store b/src/.DS_Store index f20f36d63..90213270f 100644 Binary files a/src/.DS_Store and b/src/.DS_Store differ diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f35d553b1..05bc743be 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -23,10 +23,13 @@ import { PDFField } from "../../fields/PDFField"; import { PDFBox } from "../views/nodes/PDFBox"; import { CollectionPDFView } from "../views/collections/CollectionPDFView"; import { RichTextField } from "../../fields/RichTextField"; +import { CollectionVideoView } from "../views/collections/CollectionVideoView"; +import { StrokeData, InkField } from "../../fields/InkField"; export interface DocumentOptions { x?: number; y?: number; + ink?: Map; width?: number; height?: number; nativeWidth?: number; @@ -39,6 +42,7 @@ export interface DocumentOptions { layout?: string; layoutKeys?: Key[]; viewType?: number; + backgroundColor?: string; } export namespace Documents { @@ -82,8 +86,10 @@ export namespace Documents { if (options.page !== undefined) { doc.SetNumber(KeyStore.Page, options.page); } if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); } if (options.viewType !== undefined) { doc.SetNumber(KeyStore.ViewType, options.viewType); } + if (options.backgroundColor !== undefined) { doc.SetText(KeyStore.BackgroundColor, options.backgroundColor); } if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); } if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } + if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); } return doc; } function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document { @@ -128,7 +134,7 @@ export namespace Documents { function GetCollectionPrototype(): Document { return collProto ? collProto : collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"), - { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] }); + { panx: 0, pany: 0, scale: 1, width: 500, height: 500, layoutKeys: [KeyStore.Data] }); } function GetKVPPrototype(): Document { @@ -138,9 +144,9 @@ export namespace Documents { } function GetVideoPrototype(): Document { if (!videoProto) { - videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionView.LayoutString("AnnotationsKey"), + videoProto = setupPrototypeOptions(videoProtoId, "VIDEO_PROTO", CollectionVideoView.LayoutString("AnnotationsKey"), { x: 0, y: 0, nativeWidth: 600, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] }); - videoProto.SetNumber(KeyStore.CurFrame, 1); + videoProto.SetNumber(KeyStore.CurPage, 0); videoProto.SetText(KeyStore.BackgroundLayout, VideoBox.LayoutString()); } return videoProto; diff --git a/src/client/util/TooltipTextMenu.scss b/src/client/util/TooltipTextMenu.scss index fa43f5326..ea580d104 100644 --- a/src/client/util/TooltipTextMenu.scss +++ b/src/client/util/TooltipTextMenu.scss @@ -1,8 +1,9 @@ +@import "../views/global_variables"; .tooltipMenu { position: absolute; z-index: 20; - background: rgb(19, 18, 18); + background: $dark-color; border: 1px solid silver; border-radius: 4px; padding: 2px 10px; @@ -31,14 +32,14 @@ bottom: -4.5px; border: 5px solid transparent; border-bottom-width: 0; - border-top-color: black; + border-top-color: $dark-color; } .menuicon { display: inline-block; border-right: 1px solid rgba(0, 0, 0, 0.2); //color: rgb(19, 18, 18); - color: white; + color: $light-color; line-height: 1; padding: 0px 2px; margin: 1px; diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 3b87fe9de..8cc653bf2 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -117,7 +117,7 @@ export class TooltipTextMenu { let width = Math.abs(start.left - end.left) / 2; let mid = Math.min(start.left, end.left) + width; //THIS WIDTH IS 15 * NUMBER OF ICONS + 15 - this.tooltip.style.width = 120 + "px"; + this.tooltip.style.width = 122 + "px"; this.tooltip.style.bottom = (box.bottom - start.top) + "px"; } diff --git a/src/client/views/.DS_Store b/src/client/views/.DS_Store index 6bd614c8b..0964d5ff3 100644 Binary files a/src/client/views/.DS_Store and b/src/client/views/.DS_Store differ diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index 41994ef79..f6830d9cd 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -1,42 +1,55 @@ +@import "global_variables"; .contextMenu-cont { - position: absolute; - display: flex; - z-index: 1000; - box-shadow: #AAAAAA .2vw .2vw .4vw; - flex-direction: column; + position: absolute; + display: flex; + z-index: 1000; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; + flex-direction: column; +} + +.contextMenu-item:first-child { + background: $intermediate-color; + color: $light-color; +} + +.contextMenu-item:first-child::placeholder { + color: $light-color; +} + +.contextMenu-item:first-child:hover { + background: $intermediate-color; + color: $light-color; } .contextMenu-item { - width: auto; - height: auto; - background: #F0F8FF; - display: flex; - justify-content: left; - align-items: center; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all .1s; - border-width: .11px; - border-style: none; - border-color: rgb(187, 186, 186); - border-bottom-style: solid; - padding: 10px; - white-space: nowrap; - // font-size: 1.5vw; - font-size: 12px; + width: auto; + height: auto; + background: $light-color-secondary; + display: flex; + justify-content: left; + align-items: center; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all 0.1s; + border-width: 0.11px; + border-style: none; + border-color: $intermediate-color; + border-bottom-style: solid; + padding: 10px; + white-space: nowrap; + font-size: 13px; } .contextMenu-item:hover { - transition: all .1s; - background: #B0E0E6; + transition: all 0.1s; + background: $lighter-alt-accent; } .contextMenu-description { - // font-size: 1.5vw; - text-align: left; - // width: 8vw; -} \ No newline at end of file + text-align: left; + width: 8vw; +} diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 12352c667..9109b56bb 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -13,6 +13,8 @@ export class ContextMenu extends React.Component { @observable private _pageY: number = 0; @observable private _display: string = "none"; @observable private _searchString: string = ""; + // afaik displaymenu can be called before all the items are added to the menu, so can't determine in displayMenu what the height of the menu will be + @observable private _yRelativeToTop: boolean = true; private ref: React.RefObject; @@ -59,8 +61,13 @@ export class ContextMenu extends React.Component { intersects = (x: number, y: number): boolean => { if (this.ref.current && this._display !== "none") { - if (x >= this._pageX && x <= this._pageX + this.ref.current.getBoundingClientRect().width) { - if (y >= this._pageY && y <= this._pageY + this.ref.current.getBoundingClientRect().height) { + let menuSize = { width: this.ref.current.getBoundingClientRect().width, height: this.ref.current.getBoundingClientRect().height }; + + let upperLeft = { x: this._pageX, y: this._yRelativeToTop ? this._pageY : window.innerHeight - (this._pageY + menuSize.height) }; + let bottomRight = { x: this._pageX + menuSize.width, y: this._yRelativeToTop ? this._pageY + menuSize.height : window.innerHeight - this._pageY }; + + if (x >= upperLeft.x && x <= bottomRight.x) { + if (y >= upperLeft.y && y <= bottomRight.y) { return true; } } @@ -69,9 +76,12 @@ export class ContextMenu extends React.Component { } render() { + let style = this._yRelativeToTop ? { left: this._pageX, top: this._pageY, display: this._display } : + { left: this._pageX, bottom: this._pageY, display: this._display }; + return ( -
+
{this._items.filter(prop => { return prop.description.toLowerCase().indexOf(this._searchString.toLowerCase()) !== -1; diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index fb9091dfc..11595aa01 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,17 +1,18 @@ +@import "global_variables"; #documentDecorations-container { position: absolute; display: grid; z-index: 1000; - grid-template-rows: 20px 1fr 20px 0px; - grid-template-columns: 20px 1fr 20px; + grid-template-rows: 8px 1fr 8px 30px; + grid-template-columns: 8px 1fr 8px; pointer-events: none; #documentDecorations-centerCont { background: none; } .documentDecorations-resizer { pointer-events: auto; - background: lightblue; - opacity: 0.4; + background: $alt-accent; + opacity: 0.8; } #documentDecorations-topLeftResizer, #documentDecorations-bottomRightResizer { @@ -29,23 +30,89 @@ #documentDecorations-rightResizer { cursor: ew-resize; } - } + +// position: absolute; +// display: grid; +// z-index: 1000; +// grid-template-rows: 20px 1fr 20px 0px; +// grid-template-columns: 20px 1fr 20px; +// pointer-events: none; +// #documentDecorations-centerCont { +// background: none; +// } +// .documentDecorations-resizer { +// pointer-events: auto; +// background: lightblue; +// opacity: 0.4; +// } +// #documentDecorations-topLeftResizer, +// #documentDecorations-bottomRightResizer { +// cursor: nwse-resize; +// } +// #documentDecorations-topRightResizer, +// #documentDecorations-bottomLeftResizer { +// cursor: nesw-resize; +// } +// #documentDecorations-topResizer, +// #documentDecorations-bottomResizer { +// cursor: ns-resize; +// } +// #documentDecorations-leftResizer, +// #documentDecorations-rightResizer { +// cursor: ew-resize; +// } +// } +.linkFlyout { + grid-column: 1/4 +} + +.linkButton-empty:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; +} + +.linkButton-nonempty:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; +} + .linkButton-empty { height: 20px; width: 20px; margin-top: 10px; border-radius: 50%; - opacity: 0.6; + opacity: 0.9; pointer-events: auto; - background-color: #2B6091; + background-color: $dark-color; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + transition: transform 0.2s; + text-align: center; + display: flex; + justify-content: center; + align-items: center; } + .linkButton-nonempty { height: 20px; width: 20px; margin-top: 10px; border-radius: 50%; - opacity: 0.6; + opacity: 0.9; pointer-events: auto; - background-color: rgb(35, 165, 42); + background-color: $dark-color; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + transition: transform 0.2s; + text-align: center; + display: flex; + justify-content: center; + align-items: center; } \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index dc62f97cf..3bdb7d5b3 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -18,6 +18,8 @@ export class DocumentDecorations extends React.Component { static Instance: DocumentDecorations private _resizer = "" private _isPointerDown = false; + + private _resizeBorderWidth = 16; private _linkButton = React.createRef(); @observable private _hidden = false; @@ -206,21 +208,24 @@ export class DocumentDecorations extends React.Component { let linkButton = null; if (SelectionManager.SelectedDocuments().length > 0) { let selFirst = SelectionManager.SelectedDocuments()[0]; + let linkToSize = selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length; + let linkFromSize = selFirst.props.Document.GetData(KeyStore.LinkedFromDocs, ListField, []).length; + let linkCount = linkToSize + linkFromSize; linkButton = ( }> -
+
{linkCount}
); } return (
e.preventDefault()}>
e.preventDefault()}>
@@ -232,7 +237,7 @@ export class DocumentDecorations extends React.Component {
e.preventDefault()}>
e.preventDefault()}>
- {linkButton} +
{linkButton}
) diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss new file mode 100644 index 000000000..be3c5069a --- /dev/null +++ b/src/client/views/EditableView.scss @@ -0,0 +1,6 @@ +.editableView-container-editing { + overflow-wrap: break-word; + word-wrap: break-word; + hyphens: auto; + max-width: 300px; +} \ No newline at end of file diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 84b1b91c3..3b54c0dbb 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -1,6 +1,7 @@ import React = require('react') import { observer } from 'mobx-react'; import { observable, action } from 'mobx'; +import "./EditableView.scss" export interface EditableProps { /** @@ -49,7 +50,7 @@ export class EditableView extends React.Component { style={{ display: "inline" }}> } else { return ( -
this.editing = true)}> {this.props.contents}
diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index f654b194b..e79b146b9 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,8 +1,10 @@ +@import "global_variables"; .inking-canvas { - position: fixed; + position: absolute; top: -50000px; left: -50000px; // z-index: 99; //overlays ink on top of everything svg { + position:absolute; width: 100000px; height: 100000px; .highlight { @@ -13,20 +15,135 @@ .inking-control { position: absolute; - right: 0; - bottom: 75px; - text-align: right; + left: 70px; + bottom: 70px; + margin: 0; + padding: 0; + display: flex; + label, + input, + option { + font-size: 12px; + } + input[type="range"] { + -webkit-appearance: none; + background-color: transparent; + vertical-align: middle; + margin-top: 8px; + &:focus { + outline: none; + } + &::-webkit-slider-runnable-track { + width: 100%; + height: 3px; + border-radius: 1.5px; + cursor: pointer; + background: $intermediate-color; + } + &::-webkit-slider-thumb { + height: 12px; + width: 12px; + border: 1px solid $intermediate-color; + border-radius: 6px; + background: $light-color; + cursor: pointer; + -webkit-appearance: none; + margin-top: -4px; + } + &::-moz-range-track { + width: 100%; + height: 3px; + border-radius: 1.5px; + cursor: pointer; + background: $light-color; + } + &::-moz-range-thumb { + height: 12px; + width: 12px; + border: 1px solid $intermediate-color; + border-radius: 6px; + background: $light-color; + cursor: pointer; + -webkit-appearance: none; + margin-top: -4px; + } + } + input[type="text"] { + border: none; + padding: 0 0px; + background: transparent; + color: $dark-color; + font-size: 12px; + margin-top: 4px; + } .ink-panel { - margin-top: 12px; + margin: 6px 12px 6px 0; + height: 30px; + vertical-align: middle; + line-height: 36px; + padding: 0 10px; + color: $intermediate-color; &:first { margin-top: 0; } } + .ink-tools { + display: flex; + background-color: transparent; + border-radius: 0; + padding: 0; + button { + height: 36px; + padding: 0px; + padding-bottom: 3px; + margin-left: 10px; + background-color: transparent; + color: $intermediate-color; + } + button:hover { + transform: scale(1.15); + } + } .ink-size { display: flex; justify-content: space-between; - input { - width: 85%; + input[type="text"] { + width: 42px; + } + >* { + margin-right: 6px; + &:last-child { + margin-right: 0; + } + } + } + .ink-color { + display: flex; + position: relative; + padding-right: 0; + label { + margin-right: 6px; + } + .ink-color-display { + border-radius: 11px; + width: 22px; + height: 22px; + margin-top: 6px; + cursor: pointer; + text-align: center; // span { + // color: $light-color; + // font-size: 8px; + // user-select: none; + // } + } + .ink-color-picker { + background-color: $light-color; + border-radius: 5px; + padding: 12px; + position: absolute; + bottom: 36px; + left: -3px; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; } } } \ No newline at end of file diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 0d87c1239..84c47f616 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -1,4 +1,5 @@ import { observer } from "mobx-react"; +import { observable } from "mobx"; import { action, computed } from "mobx"; import { InkingControl } from "./InkingControl"; import React = require("react"); @@ -6,14 +7,10 @@ import { Transform } from "../util/Transform"; import { Document } from "../../fields/Document"; import { KeyStore } from "../../fields/KeyStore"; import { InkField, InkTool, StrokeData, StrokeMap } from "../../fields/InkField"; -import { JsxArgs } from "./nodes/DocumentView"; import { InkingStroke } from "./InkingStroke"; import "./InkingCanvas.scss" -import { CollectionDockingView } from "./collections/CollectionDockingView"; import { Utils } from "../../Utils"; import { FieldWaiting } from "../../fields/Field"; -import { getMapLikeKeys } from "mobx/lib/internal"; - interface InkCanvasProps { getScreenTransform: () => Transform; @@ -22,7 +19,16 @@ interface InkCanvasProps { @observer export class InkingCanvas extends React.Component { - + static InkOffset: number = 50000; + public static IntersectStrokeRect(stroke: StrokeData, selRect: { left: number, top: number, width: number, height: number }): boolean { + let inside = false; + stroke.pathData.map(val => { + if (selRect.left < val.x - InkingCanvas.InkOffset && selRect.left + selRect.width > val.x - InkingCanvas.InkOffset && + selRect.top < val.y - InkingCanvas.InkOffset && selRect.top + selRect.height > val.y - InkingCanvas.InkOffset) + inside = true; + }); + return inside + } private _isDrawing: boolean = false; private _idGenerator: string = ""; @@ -51,7 +57,6 @@ export class InkingCanvas extends React.Component { document.removeEventListener("mouseup", this.handleMouseUp); } - @action handleMouseDown = (e: React.PointerEvent): void => { if (e.button != 0 || @@ -62,7 +67,6 @@ export class InkingCanvas extends React.Component { if (InkingControl.Instance.selectedTool === InkTool.Eraser) { return } - e.stopPropagation() const point = this.relativeCoordinatesForEvent(e); // start the new line, saves a uuid to represent the field of the stroke @@ -74,7 +78,7 @@ export class InkingCanvas extends React.Component { color: InkingControl.Instance.selectedColor, width: InkingControl.Instance.selectedWidth, tool: InkingControl.Instance.selectedTool, - page: this.props.Document.GetNumber(KeyStore.CurPage, 0) + page: this.props.Document.GetNumber(KeyStore.CurPage, -1) }); this.inkData = data; this._isDrawing = true; @@ -110,8 +114,8 @@ export class InkingCanvas extends React.Component { relativeCoordinatesForEvent = (e: React.MouseEvent): { x: number, y: number } => { let [x, y] = this.props.getScreenTransform().transformPoint(e.clientX, e.clientY); - x += 50000 - y += 50000 + x += InkingCanvas.InkOffset; + y += InkingCanvas.InkOffset; return { x, y }; } @@ -145,11 +149,11 @@ export class InkingCanvas extends React.Component { // parse data from server let paths: Array = [] - let curPage = this.props.Document.GetNumber(KeyStore.CurPage, 0) + let curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1) Array.from(lines).map(item => { let id = item[0]; let strokeData = item[1]; - if (strokeData.page == 0 || strokeData.page == curPage) + if (strokeData.page == -1 || strokeData.page == curPage) paths.push() { super(props); @@ -49,29 +58,50 @@ export class InkingControl extends React.Component { selected = (tool: InkTool) => { if (this._selectedTool === tool) { - return { backgroundColor: "black", color: "white" } + return { color: "#61aaa3" } } return {} } + @action + toggleDisplay = () => { + this._open = !this._open; + } + + @action + toggleColorPicker = () => { + this._colorPickerDisplay = !this._colorPickerDisplay; + } + render() { return ( -
-
- - - - -
-
- - +
  • +
    + + + + +
    +
  • +
  • + +
    this.toggleColorPicker()}> + {/* {this._colorPickerDisplay ? : } */} +
    +
    + +
    +
  • +
  • + + ) => this.switchWidth(e.target.value)} /> + ) => this.switchWidth(e.target.value)} /> -
  • -
    - -
    -
    + + ) } } \ No newline at end of file diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index d724421d3..87b5c43d8 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -21,8 +21,6 @@ export class InkingStroke extends React.Component { @observable private _strokeColor: string = this.props.color; @observable private _strokeWidth: string = this.props.width; - private _canvasColor: string = "#cdcdcd"; - deleteStroke = (e: React.MouseEvent): void => { if (InkingControl.Instance.selectedTool === InkTool.Eraser && e.buttons === 1) { this.props.deleteCallback(this.props.id); diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 2b1c77b74..bb42db202 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -1,22 +1,35 @@ +@import "global_variables"; +@import "nodeModuleOverrides"; html, body { width: 100%; height: 100%; overflow: hidden; - font-family: 'Hind Siliguri', sans-serif; + font-family: $sans-serif; margin: 0; } +#dash-title { + position: absolute; + right: 46.5%; + letter-spacing: 3px; + top: 9px; + font-size: 12px; + color: $alt-accent; + z-index: 9999; +} + h1 { font-size: 50px; position: fixed; top: 30px; left: 50%; transform: translateX(-50%); - color: black; + color: $dark-color; text-shadow: -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff; z-index: 9999; - font-family: 'Fjalla One', sans-serif; + font-family: $sans-serif; + font-weight: 700; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; @@ -33,23 +46,131 @@ p { margin: 0px; padding: 0px; } + ::-webkit-scrollbar { -webkit-appearance: none; - height:5px; - width:5px; + height: 5px; + width: 5px; } + ::-webkit-scrollbar-thumb { border-radius: 2px; - background-color: rgba(0,0,0,.5); + background-color: rgba(0, 0, 0, 0.5); +} + +// button stuff +button { + background: $dark-color; + outline: none; + border: 0px; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + padding: 10px; + transition: transform 0.2s; +} + +button:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; } -.main-buttonDiv { +.clear-db-button { position: absolute; - width: 150px; - left: 0px; + right: 45%; + bottom: 3%; + font-size: 50%; +} + +.round-button { + width: 36px; + height: 36px; + border-radius: 18px; + font-size: 15px; +} + +.round-button:hover { + transform: scale(1.15); +} + +.add-button { + position: relative; + margin-right: 10px; } + .main-undoButtons { position: absolute; width: 150px; right: 0px; } + +//toolbar stuff +#toolbar { + position: absolute; + bottom: 62px; + left: 24px; + .toolbar-button { + display: block; + margin-bottom: 10px; + } +} + +// add nodes menu. Note that the + button is actually an input label, not an actual button. +#add-nodes-menu { + position: absolute; + bottom: 24px; + left: 24px; + label { + background: $dark-color; + color: $light-color; + display: inline-block; + border-radius: 18px; + font-size: 25px; + width: 36px; + height: 36px; + margin-right: 10px; + cursor: pointer; + transition: transform 0.2s; + } + label p { + padding-left: 10.5px; + padding-top: 3px; + } + label:hover { + background: $main-accent; + transform: scale(1.15); + } + input { + display: none; + } + input:not(:checked)~#add-options-content { + display: none; + } + input:checked~label { + transform: rotate(45deg); + transition: transform 0.5s; + cursor: pointer; + } +} + +#add-options-content { + display: table; + opacity: 1; + margin: 0; + padding: 0; + position: relative; + float: right; + bottom: 0.3em; + margin-bottom: -1.68em; +} + +ul#add-options-list { + list-style: none; + padding: 0; + li { + display: inline-block; + padding: 0; + } +} \ No newline at end of file diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 95bf9cad0..3a68b98ce 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -18,6 +18,19 @@ import { DocumentDecorations } from './DocumentDecorations'; import { DocumentView } from './nodes/DocumentView'; import "./Main.scss"; import { InkingControl } from './InkingControl'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faFont } from '@fortawesome/free-solid-svg-icons'; +import { faImage } from '@fortawesome/free-solid-svg-icons'; +import { faFilePdf } from '@fortawesome/free-solid-svg-icons'; +import { faObjectGroup } from '@fortawesome/free-solid-svg-icons'; +import { faTable } from '@fortawesome/free-solid-svg-icons'; +import { faGlobeAsia } from '@fortawesome/free-solid-svg-icons'; +import { faUndoAlt } from '@fortawesome/free-solid-svg-icons'; +import { faRedoAlt } from '@fortawesome/free-solid-svg-icons'; +import { faPenNib } from '@fortawesome/free-solid-svg-icons'; +import { faFilm } from '@fortawesome/free-solid-svg-icons'; +import { faMusic } from '@fortawesome/free-solid-svg-icons'; configure({ enforceActions: "observed" }); // causes errors to be generated when modifying an observable outside of an action @@ -29,10 +42,22 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { } }), true) - const mainDocId = "mainDoc"; let mainContainer: Document; let mainfreeform: Document; + +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); + Documents.initProtos(mainDocId, (res?: Document) => { if (res instanceof Document) { mainContainer = res; @@ -80,6 +105,8 @@ Documents.initProtos(mainDocId, (res?: Document) => { ReactDOM.render((
    + {/*
    — DASH —
    */} + Transform.Identity} ContentScaling={() => 1} @@ -91,27 +118,52 @@ Documents.initProtos(mainDocId, (res?: Document) => { ContainingCollectionView={undefined} /> -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - + + + {/* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */} + < div id="toolbar" > + + + +
    + + {/* for the expandable add nodes menu. Not included with the above because once it expands it expands the whole div with it, making canvas interactions limited. */} + < div id="add-nodes-menu" > + + + +
    +
      +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    +
    + +
    + -
    ), +
    ), document.getElementById('root')); }) diff --git a/src/client/views/_global_variables.scss b/src/client/views/_global_variables.scss new file mode 100644 index 000000000..44a819b79 --- /dev/null +++ b/src/client/views/_global_variables.scss @@ -0,0 +1,17 @@ +@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700"); +// colors +$light-color: #fcfbf7; +$light-color-secondary: rgb(241, 239, 235); +$main-accent: #61aaa3; +// $alt-accent: #cdd5ec; +// $alt-accent: #cdeceb; +$alt-accent: #59dff7; +$lighter-alt-accent: rgb(207, 220, 240); +$intermediate-color: #9c9396; +$dark-color: #121721; +// fonts +$sans-serif: "Noto Sans", sans-serif; +// $sans-serif: "Roboto Slab", sans-serif; +$serif: "Crimson Text", serif; +// misc values +$border-radius: 0.3em; diff --git a/src/client/views/_nodeModuleOverrides.scss b/src/client/views/_nodeModuleOverrides.scss new file mode 100644 index 000000000..6f97e60f8 --- /dev/null +++ b/src/client/views/_nodeModuleOverrides.scss @@ -0,0 +1,23 @@ +// this file is for overriding all the css from installed node modules + +// goldenlayout stuff +div .lm_header { + background: $dark-color; + min-height: 2em; +} + +.lm_tab { + margin-top: 0.6em !important; + padding-top: 0.5em !important; + min-height: 1.35em; + padding-bottom: 0px; + border-radius: 5px; + font-family: $sans-serif !important; +} + +.lm_header .lm_controls { + right: 1em !important; +} + +// @TODO the ril__navgiation buttons in the img gallery are a lil messed up but I can't figure out +// why. Low priority for now but it's bugging me. --Julie diff --git a/src/client/views/collections/CollectionFreeFormView.scss b/src/client/views/collections/CollectionFreeFormView.scss index d472cc5c4..9c7a03b52 100644 --- a/src/client/views/collections/CollectionFreeFormView.scss +++ b/src/client/views/collections/CollectionFreeFormView.scss @@ -1,29 +1,56 @@ +@import "../global_variables"; + .collectionfreeformview-container { + .collectionfreeformview > .jsx-parser { + position: absolute; + height: 100%; + width: 100%; + } - .collectionfreeformview > .jsx-parser{ - position:absolute; - height: 100%; - width: 100%; - } - - border-style: solid; - box-sizing: border-box; - position: relative; + //nested freeform views + .collectionfreeformview-container { + // background-image: linear-gradient(to right, $light-color-secondary 1px, transparent 1px), + // linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px); + // background-size: 30px 30px; + } + + border: 0px solid $light-color-secondary; + border-radius: $border-radius; + box-sizing: border-box; + position: relative; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw; + .collectionfreeformview { + position: absolute; top: 0; left: 0; width: 100%; height: 100%; - overflow: hidden; - .collectionfreeformview { - position: absolute; - top: 0; - left: 0; - width:100%; - height: 100%; - } + } } .collectionfreeformview-overlay { + .collectionfreeformview > .jsx-parser { + position: absolute; + height: 100%; + } + .formattedTextBox-cont { + background: $light-color-secondary; + } + position:absolute; + border: 0px solid transparent; + border-radius: $border-radius; + overflow: hidden; + box-sizing: border-box; + top: 0; + left: 0; + width: 100%; + height: 100%; + .collectionfreeformview { .collectionfreeformview > .jsx-parser{ position:absolute; height: 100%; @@ -32,26 +59,39 @@ background:yellow; } - border-style: solid; - box-sizing: border-box; + // overflow: hidden; + // border-style: solid; + // box-sizing: border-box; position: absolute; top: 0; left: 0; width: 100%; height: 100%; - overflow: hidden; - .collectionfreeformview { - position: absolute; - top: 0; - left: 0; - width:100%; - height: 100%; - } + } } +// selection border...? .border { - border-style: solid; - box-sizing: border-box; - width: 100%; - height: 100%; -} \ No newline at end of file + border-style: solid; + box-sizing: border-box; + width: 98%; + height: 98%; + border-radius: $border-radius; +} + +//this is an animation for the blinking cursor! +@keyframes blink { + 0% { + opacity: 0; + } + 49% { + opacity: 0; + } + 50% { + opacity: 1; + } +} + +#prevCursor { + animation: blink 1s infinite; +} diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 3d5326552..5c0eab392 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -52,13 +52,13 @@ export class CollectionFreeFormView extends CollectionViewBase { } public getActiveDocuments = () => { - var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1); + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); const lvalue = this.props.Document.GetT>(this.props.fieldKey, ListField); let active: Document[] = []; if (lvalue && lvalue != FieldWaiting) { lvalue.Data.map(doc => { - var page = doc.GetNumber(KeyStore.Page, 0); - if (page == curPage || page == 0) { + var page = doc.GetNumber(KeyStore.Page, -1); + if (page == curPage || page == -1) { active.push(doc); } }) @@ -126,7 +126,7 @@ export class CollectionFreeFormView extends CollectionViewBase { onPointerUp = (e: PointerEvent): void => { e.stopPropagation(); - if (!this.MarqueeVisible && Math.abs(this.DownX - e.clientX) < 3 && Math.abs(this.DownY - e.clientY) < 3) { + if (Math.abs(this.DownX - e.clientX) < 4 && Math.abs(this.DownY - e.clientY) < 4) { //show preview text cursor on tap this.PreviewCursorVisible = true; //select is not already selected @@ -140,9 +140,8 @@ export class CollectionFreeFormView extends CollectionViewBase { @action onPointerMove = (e: PointerEvent): void => { if (!e.cancelBubble && this.props.active()) { - if (e.buttons != 2 && !e.altKey && !e.metaKey && !this.MarqueeVisible) { + if (e.buttons == 1 && !e.altKey && !e.metaKey) { this.MarqueeVisible = true; - this.PreviewCursorVisible = false; } if (this.MarqueeVisible) { e.stopPropagation(); @@ -152,7 +151,6 @@ export class CollectionFreeFormView extends CollectionViewBase { let x = this.props.Document.GetNumber(KeyStore.PanX, 0); let y = this.props.Document.GetNumber(KeyStore.PanY, 0); let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY); - this.PreviewCursorVisible = false; this.SetPan(x - dx, y - dy); this._lastX = e.pageX; this._lastY = e.pageY; @@ -272,7 +270,7 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get views() { - var curPage = this.props.Document.GetNumber(KeyStore.CurPage, 1); + var curPage = this.props.Document.GetNumber(KeyStore.CurPage, -1); const lvalue = this.props.Document.GetT>(this.props.fieldKey, ListField); if (lvalue && lvalue != FieldWaiting) { return lvalue.Data.map(doc => { @@ -343,10 +341,12 @@ export class CollectionFreeFormView extends CollectionViewBase { ref={this._canvasRef}> {this.backgroundView} - + {this.views} - + {this.overlayView} ); diff --git a/src/client/views/collections/CollectionPDFView.scss b/src/client/views/collections/CollectionPDFView.scss new file mode 100644 index 000000000..0144625c1 --- /dev/null +++ b/src/client/views/collections/CollectionPDFView.scss @@ -0,0 +1,27 @@ +.collectionPdfView-buttonTray { + top : 25px; + left : 20px; + position: relative; + transform-origin: left top; + position: absolute; +} +.collectionPdfView-cont{ + width: 100%; + height: 100%; + position: absolute; + +} +.collectionPdfView-backward { + color : white; + top :0px; + left : 0px; + position: absolute; + background-color: rgba(50, 50, 50, 0.2); +} +.collectionPdfView-forward { + color : white; + top :0px; + left : 35px; + position: absolute; + background-color: rgba(50, 50, 50, 0.2); +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index f22c07060..124d82c8b 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -1,10 +1,11 @@ -import { action, computed } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { KeyStore } from "../../../fields/KeyStore"; import { ContextMenu } from "../ContextMenu"; import { CollectionView, CollectionViewType } from "./CollectionView"; import { CollectionViewProps } from "./CollectionViewBase"; +import "./CollectionPDFView.scss" import React = require("react"); import { FieldId } from "../../../fields/Field"; @@ -18,22 +19,23 @@ export class CollectionPDFView extends React.Component { isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`; } - public SelectedDocs: FieldId[] = [] - @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0; - @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0; + private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); } + private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); } + @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : -1; + @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : -1; - @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 0); } - @computed private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); } - @computed private get uIButtons() { + private get uIButtons() { + let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]); return ( -
    - - +
    + +
    ); } // "inherited" CollectionView API starts here... - + @observable + public SelectedDocs: FieldId[] = [] public active: () => boolean = () => CollectionView.Active(this); addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } @@ -49,7 +51,7 @@ export class CollectionPDFView extends React.Component { get subView(): any { return CollectionView.SubView(this); } render() { - return (
    + return (
    {this.subView} {this.props.isSelected() ? this.uIButtons : (null)}
    ) diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss index d40e6d314..0d615dc01 100644 --- a/src/client/views/collections/CollectionSchemaView.scss +++ b/src/client/views/collections/CollectionSchemaView.scss @@ -1,185 +1,162 @@ - +@import "../global_variables"; .collectionSchemaView-container { - border-style: solid; + border: 1px solid $intermediate-color; + border-radius: $border-radius; + box-sizing: border-box; + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + +.collectionSchemaView-content { + position: absolute; + height:100%; + width:100%; + overflow:auto; +} + .collectionSchemaView-previewRegion { + position: relative; + background: $light-color; + float: left; + height: 100%; + } + .collectionSchemaView-previewHandle { + position: absolute; + height: 37px; + width: 20px; + z-index: 20; + right: 0; + top: 0; + background: $main-accent; + } + .collectionSchemaView-dividerDragger { + position: relative; box-sizing: border-box; + border-left: 1px solid $intermediate-color; + border-right: 1px solid $intermediate-color; + float: left; + height: 100%; + } + .collectionSchemaView-tableContainer { + position: relative; + float: left; + height: 100%; + } + + .ReactTable { position: absolute; + // display: inline-block; + // overflow: auto; width: 100%; height: 100%; - .collectionSchemaView-previewRegion { - position: relative; - background: black; - float: left; - height: 100%; - } - .collectionSchemaView-previewHandle { - position: absolute; - height: 37px; - width: 20px; - z-index: 20; - right: 0; - top: 0; - background: Black ; - } - .collectionSchemaView-dividerDragger{ - position: relative; - background: black; - float: left; - height: 100%; - } - .collectionSchemaView-tableContainer { + background: $light-color; + box-sizing: border-box; + border: none !important; + .rt-table { + overflow-y: auto; + overflow-x: auto; + height: 100%; + display: -webkit-inline-box; + direction: ltr; + // direction:rtl; + // display:block; + } + .rt-tbody { + //direction: ltr; + direction: rtl; + } + .rt-tr-group { + direction: ltr; + max-height: 44px; + } + .rt-td { + border-width: 1px; + border-right-color: $intermediate-color; + .imageBox-cont { position: relative; - float: left; - height: 100%; - } - - .ReactTable { - position: absolute; - // display: inline-block; - // overflow: auto; - width: 100%; + max-height: 100%; + } + .imageBox-cont img { + object-fit: contain; + max-width: 100%; height: 100%; - background: white; - box-sizing: border-box; - .rt-table { - overflow-y: auto; - overflow-x: auto; - height: 100%; - - display: -webkit-inline-box; - direction: ltr; - // direction:rtl; - // display:block; - } - .rt-tbody { - //direction: ltr; - direction: rtl; - } - .rt-tr-group { - direction: ltr; - max-height: 44px; - } - .rt-td { - border-width: 1; - border-right-color: #aaa; - .imageBox-cont { - position:relative; - max-height:100%; - } - .imageBox-cont img { - object-fit: contain; - max-width: 100%; - height: 100% - } - } - .rt-tr-group { - border-width: 1; - border-bottom-color: #aaa - } - } - .ReactTable .rt-thead.-header { - background:grey; - } - .ReactTable .rt-th, .ReactTable .rt-td { - max-height: 44; - padding: 3px 7px; - } - .ReactTable .rt-tbody .rt-tr-group:last-child { - border-bottom: grey; - border-bottom-style: solid; - border-bottom-width: 1; - } - .documentView-node:first-child { - background: grey; - .imageBox-cont img { - object-fit: contain; - } - } + } + .videobox-cont { + object-fit: contain; + width:auto; + height: 100%; + } + } + } + .ReactTable .rt-thead.-header { + background: $intermediate-color; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 12px; + height: 30px; + padding-top: 4px; + } + .ReactTable .rt-th, + .ReactTable .rt-td { + max-height: 44; + padding: 3px 7px; + 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:first-child { + background: $light-color; + .imageBox-cont img { + object-fit: contain; + } + } } .Resizer { - box-sizing: border-box; - background: #000; - opacity: 0.5; - z-index: 1; - background-clip: padding-box; - &.horizontal { - height: 11px; - margin: -5px 0; - border-top: 5px solid rgba(255, 255, 255, 0); - 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); - } - } + box-sizing: border-box; + background: #000; + opacity: 0.5; + z-index: 1; + background-clip: padding-box; + &.horizontal { + height: 11px; + margin: -5px 0; + border-top: 5px solid rgba(255, 255, 255, 0); + border-bottom: 5px solid rgba(255, 255, 255, 0); + cursor: row-resize; + width: 100%; &:hover { - -webkit-transition: all 2s ease; - transition: all 2s ease; - } + 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; + } } .vertical { - section { - width: 100vh; - height: 100vh; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - } - header { - padding: 1rem; - background: #eee; - } - footer { - padding: 1rem; - background: #eee; - } -} - -.horizontal { - section { - width: 100vh; - height: 100vh; - display: flex; - flex-direction: column; - } - header { - padding: 1rem; - background: #eee; - } - footer { - padding: 1rem; - background: #eee; - } -} - -.parent { - width: 100%; - height: 100%; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; + section { + width: 100vh; + height: 100vh; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -189,19 +166,71 @@ -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; + } + header { + padding: 1rem; + background: #eee; + } + footer { + padding: 1rem; + background: #eee; + } +} + +.horizontal { + section { + width: 100vh; + height: 100vh; + display: flex; + flex-direction: column; + } + header { + padding: 1rem; + background: #eee; + } + footer { + padding: 1rem; + background: #eee; + } +} + +.parent { + width: 100%; + height: 100%; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; } .header { - background: #aaa; - height: 3rem; - line-height: 3rem; + background: #aaa; + height: 3rem; + line-height: 3rem; } .wrapper { - background: #ffa; - margin: 5rem; - -webkit-box-flex: 1; - -webkit-flex: 1; - -ms-flex: 1; - flex: 1; -} \ No newline at end of file + background: #ffa; + margin: 5rem; + -webkit-box-flex: 1; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.-even { + background: $light-color !important; +} + +.-odd { + background: $light-color-secondary !important; +} diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 04f017378..8c1aeef2c 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -1,5 +1,5 @@ import React = require("react") -import { action, observable } from "mobx"; +import { action, observable, computed } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; @@ -24,14 +24,14 @@ import { setupDrag } from "../../util/DragManager"; @observer export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef(); - private DIVIDER_WIDTH = 5; + private DIVIDER_WIDTH = 4; @observable _contentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ContentScaling prop of the DocumentView @observable _dividerX = 0; @observable _panelWidth = 0; @observable _panelHeight = 0; @observable _selectedIndex = 0; - @observable _splitPercentage: number = 50; + @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); } renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { @@ -49,7 +49,7 @@ export class CollectionSchemaView extends CollectionViewBase { let reference = React.createRef(); let onItemDown = setupDrag(reference, () => props.doc); return ( -
    +
    { let field = props.doc.Get(props.fieldKey); @@ -89,7 +89,8 @@ export class CollectionSchemaView extends CollectionViewBase { return { onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that._selectedIndex = rowInfo.index; - this._splitPercentage += 0.05; // bcz - ugh - needed to force Measure to do its thing and call onResize + // bcz - ugh - needed to force Measure to do its thing and call onResize + this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage - 0.05) if (handleOriginal) { handleOriginal() @@ -106,18 +107,18 @@ export class CollectionSchemaView extends CollectionViewBase { @action onDividerMove = (e: PointerEvent): void => { let nativeWidth = this._mainCont.current!.getBoundingClientRect(); - this._splitPercentage = Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100); + this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)); } @action onDividerUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onDividerMove); document.removeEventListener('pointerup', this.onDividerUp); - if (this._startSplitPercent == this._splitPercentage) { - this._splitPercentage = this._splitPercentage == 1 ? 66 : 100; + if (this._startSplitPercent == this.splitPercentage) { + this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0); } } onDividerDown = (e: React.PointerEvent) => { - this._startSplitPercent = this._splitPercentage; + this._startSplitPercent = this.splitPercentage; e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onDividerMove); @@ -134,12 +135,12 @@ export class CollectionSchemaView extends CollectionViewBase { e.preventDefault(); document.removeEventListener("pointermove", this.onExpanderMove); document.removeEventListener('pointerup', this.onExpanderUp); - if (this._startSplitPercent == this._splitPercentage) { - this._splitPercentage = this._splitPercentage == 100 ? 66 : 100; + if (this._startSplitPercent == this.splitPercentage) { + this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0); } } onExpanderDown = (e: React.PointerEvent) => { - this._startSplitPercent = this._splitPercentage; + this._startSplitPercent = this.splitPercentage; e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onExpanderMove); @@ -203,7 +204,7 @@ export class CollectionSchemaView extends CollectionViewBase { ) let previewHandle = !this.props.active() ? (null) : (
    ); - let dividerDragger = this._splitPercentage == 100 ? (null) : + let dividerDragger = this.splitPercentage == 0 ? (null) :
    return (
    @@ -213,7 +214,8 @@ export class CollectionSchemaView extends CollectionViewBase { this._panelHeight = r.entry.height; })}> {({ measureRef }) => -
    +
    {dividerDragger} -
    +
    {content}
    {previewHandle} diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index f8d580a7b..fa0f1c761 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -1,16 +1,25 @@ +@import "../global_variables"; #body { padding: 20px; - background: #bbbbbb; + background: $light-color-secondary; + font-size: 13px; + overflow: scroll; } ul { list-style: none; + padding-left: 20px; } li { margin: 5px 0; } +.collection-child { + margin-top: 10px; + margin-bottom: 10px; +} + .no-indent { padding-left: 0; } @@ -18,10 +27,17 @@ li { .bullet { width: 1.5em; display: inline-block; + color: $intermediate-color; +} + +.coll-title { + font-size: 24px; + margin-bottom: 20px; } .collectionTreeView-dropTarget { - border-style: solid; + border: 0px solid transparent; + border-radius: $border-radius; box-sizing: border-box; height: 100%; } @@ -30,8 +46,16 @@ li { display: inline-table; } +.docContainer:hover { + .delete-button { + display: inline; + } +} + .delete-button { - color: #999999; + color: $intermediate-color; float: right; - margin-left: 1em; + margin-left: 15px; + margin-top: 3px; + display: none; } \ No newline at end of file diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 8b06d9ac4..80fc89712 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -12,6 +12,10 @@ import { setupDrag } from "../../util/DragManager"; import { FieldWaiting } from "../../../fields/Field"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTrashAlt, faCaretRight, faCaretDown } from '@fortawesome/free-solid-svg-icons'; + export interface TreeViewProps { document: Document; deleteDoc: (doc: Document) => void; @@ -23,6 +27,10 @@ export enum BulletType { List } +library.add(faTrashAlt); +library.add(faCaretDown); +library.add(faCaretRight); + @observer /** * Component that takes in a document prop and a boolean whether it's collapsed or not. @@ -50,11 +58,11 @@ class TreeView extends React.Component { switch (type) { case BulletType.Collapsed: - return
    + return
    case BulletType.Collapsible: - return
    + return
    case BulletType.List: - return
    + return
    } } @@ -79,7 +87,7 @@ class TreeView extends React.Component { this.props.document.SetData(KeyStore.Title, value, TextField); return true; }} /> -
    x
    +
    } @@ -101,7 +109,7 @@ class TreeView extends React.Component { ) ) subView = -
  • +
  • {this.renderBullet(BulletType.Collapsible)} {titleElement}
      @@ -109,7 +117,7 @@ class TreeView extends React.Component {
  • } else { - subView =
  • + subView =
  • {this.renderBullet(BulletType.Collapsed)} {titleElement}
  • @@ -157,7 +165,7 @@ export class CollectionTreeView extends CollectionViewBase { return (
    this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}> -

    +
    { return this.props.Document.Title; @@ -165,7 +173,8 @@ export class CollectionTreeView extends CollectionViewBase { this.props.Document.SetData(KeyStore.Title, value, TextField); return true; }} /> -

    +
    +
      {childrenElement}
    diff --git a/src/client/views/collections/CollectionVideoView.scss b/src/client/views/collections/CollectionVideoView.scss new file mode 100644 index 000000000..cbb981b13 --- /dev/null +++ b/src/client/views/collections/CollectionVideoView.scss @@ -0,0 +1,40 @@ + +.collectionVideoView-cont{ + width: 100%; + height: 100%; + position: absolute; + +} +.collectionVideoView-time{ + color : white; + top :25px; + left : 25px; + position: absolute; + background-color: rgba(50, 50, 50, 0.2); + transform-origin: left top; +} +.collectionVideoView-play { + width: 25px; + height: 20px; + bottom: 25px; + left : 25px; + position: absolute; + color : white; + background-color: rgba(50, 50, 50, 0.2); + border-radius: 4px; + text-align: center; + transform-origin: left bottom; +} +.collectionVideoView-full { + width: 25px; + height: 20px; + bottom: 25px; + right : 25px; + position: absolute; + color : white; + background-color: rgba(50, 50, 50, 0.2); + border-radius: 4px; + text-align: center; + transform-origin: right bottom; + +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index a6471f53c..b64ef3c07 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -1,4 +1,4 @@ -import { action, computed } from "mobx"; +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; import { KeyStore } from "../../../fields/KeyStore"; @@ -7,6 +7,7 @@ import { CollectionView, CollectionViewType } from "./CollectionView"; import { CollectionViewProps } from "./CollectionViewBase"; import React = require("react"); import { FieldId } from "../../../fields/Field"; +import "./CollectionVideoView.scss" @observer @@ -18,14 +19,29 @@ export class CollectionVideoView extends React.Component { isTopMost={isTopMost} SelectOnLoad={selectOnLoad} BackgroundView={BackgroundView} focus={focus}/>`; } - public SelectedDocs: FieldId[] = [] - @action onPageBack = () => this.curPage > 1 ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage - 1) : 0; - @action onPageForward = () => this.curPage < this.numPages ? this.props.Document.SetNumber(KeyStore.CurPage, this.curPage + 1) : 0; + private _mainCont = React.createRef(); + + private get uIButtons() { + let scaling = Math.min(1.8, this.props.ScreenToLocalTransform().transformDirection(1, 1)[0]); + return ([ +
    + {"" + Math.round(this.ctime)} + {" " + Math.round((this.ctime - Math.trunc(this.ctime)) * 100)} +
    , +
    + {this.playing ? "\"" : ">"} +
    , +
    + F +
    + ]); + } + - @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 0); } - @computed private get numPages() { return this.props.Document.GetNumber(KeyStore.NumPages, 0); } // "inherited" CollectionView API starts here... + @observable + public SelectedDocs: FieldId[] = [] public active: () => boolean = () => CollectionView.Active(this); addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } @@ -40,11 +56,63 @@ export class CollectionVideoView extends React.Component { get collectionViewType(): CollectionViewType { return CollectionViewType.Freeform; } get subView(): any { return CollectionView.SubView(this); } + componentDidMount() { + this.updateTimecode(); + } + + get player(): HTMLVideoElement | undefined { + return this._mainCont.current ? this._mainCont.current.getElementsByTagName("video")[0] : undefined; + } + + @action + updateTimecode = () => { + if (this.player) { + this.ctime = this.player.currentTime; + this.props.Document.SetNumber(KeyStore.CurPage, Math.round(this.ctime)); + } + setTimeout(() => this.updateTimecode(), 100) + } + + + @observable + ctime: number = 0 + @observable + playing: boolean = false; + + @action + onPlayDown = () => { + if (this.player) { + if (this.player.paused) { + this.player.play(); + this.playing = true; + } else { + this.player.pause(); + this.playing = false; + } + } + } + @action + onFullDown = (e: React.PointerEvent) => { + if (this.player) { + this.player.requestFullscreen(); + e.stopPropagation(); + e.preventDefault(); + } + } + + @action + onResetDown = () => { + if (this.player) { + this.player.pause(); + this.player.currentTime = 0; + } + + } + render() { - return (
    - {/*
    ) diff --git a/src/client/views/nodes/LinkEditor.scss b/src/client/views/nodes/LinkEditor.scss index cb191dc8c..fb0c69cff 100644 --- a/src/client/views/nodes/LinkEditor.scss +++ b/src/client/views/nodes/LinkEditor.scss @@ -1,3 +1,4 @@ +@import "../global_variables"; .edit-container { width: 100%; height: auto; @@ -9,21 +10,34 @@ margin-bottom: 10px; padding: 5px; font-size: 12px; + border: 1px solid #bababa; } .description-input { - font-size: 12px; + font-size: 11px; padding: 5px; margin-bottom: 10px; + border: 1px solid #bababa; } .save-button { width: 50px; height: 20px; - background-color: #2B6091; + pointer-events: auto; + background-color: $dark-color; + color: $light-color; + text-transform: uppercase; + letter-spacing: 2px; + padding: 2px; + font-size: 10px; margin: 0 auto; - color: white; + transition: transform 0.2s; text-align: center; line-height: 20px; - font-size: 12px; +} + +.save-button:hover { + background: $main-accent; + transform: scale(1.05); + cursor: pointer; } \ No newline at end of file diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss index a120ab2a7..dedcce6ef 100644 --- a/src/client/views/nodes/LinkMenu.scss +++ b/src/client/views/nodes/LinkMenu.scss @@ -10,6 +10,7 @@ padding: 5px; margin-bottom: 10px; font-size: 12px; + border: 1px solid #bababa; } #linkMenu-list { diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 5c6b06d00..5eeb40772 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -39,8 +39,8 @@ export class LinkMenu extends React.Component {
    - {this.renderLinkItems(linkTo, KeyStore.LinkedToDocs, "Source: ")} - {this.renderLinkItems(linkFrom, KeyStore.LinkedFromDocs, "Destination: ")} + {this.renderLinkItems(linkTo, KeyStore.LinkedToDocs, "Destination: ")} + {this.renderLinkItems(linkFrom, KeyStore.LinkedFromDocs, "Source: ")}
    ) diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 9f92410d4..ad947afd5 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -11,5 +11,5 @@ } .pdfBox-contentContainer { position: absolute; - transform-origin: "left top"; + transform-origin: left top; } \ No newline at end of file diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 544af41a2..b0b5a63a4 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -86,7 +86,7 @@ export class PDFBox extends React.Component { @observable private _interactive: boolean = false; @observable private _loaded: boolean = false; - @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, 0); } + @computed private get curPage() { return this.props.doc.GetNumber(KeyStore.CurPage, -1); } componentDidMount() { this._reactionDisposer = reaction( diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 9c60d4348..8c1ee669f 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -30,7 +30,7 @@ export class VideoBox extends React.Component { var nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 0); var nativeHeight = this.props.doc.GetNumber(KeyStore.NativeHeight, 0); var newNativeHeight = nativeWidth * r.entry.height / r.entry.width; - if (newNativeHeight != nativeHeight && !isNaN(newNativeHeight)) { + if (!nativeHeight && newNativeHeight != nativeHeight && !isNaN(newNativeHeight)) { this.props.doc.SetNumber(KeyStore.Height, newNativeHeight / nativeWidth * this.props.doc.GetNumber(KeyStore.Width, 0)); this.props.doc.SetNumber(KeyStore.NativeHeight, newNativeHeight); } @@ -48,16 +48,14 @@ export class VideoBox extends React.Component { //setTimeout(action(() => this._loaded = true), 500); return ( -
    - - {({ measureRef }) => -
    + } + ) } } \ No newline at end of file diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 6481e14fe..06cdc8fc8 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -19,11 +19,13 @@ export namespace KeyStore { export const Annotations = new Key("Annotations"); export const ViewType = new Key("ViewType"); export const Layout = new Key("Layout"); + export const BackgroundColor = new Key("BackgroundColor"); export const BackgroundLayout = new Key("BackgroundLayout"); export const OverlayLayout = new Key("OverlayLayout"); export const LayoutKeys = new Key("LayoutKeys"); export const LayoutFields = new Key("LayoutFields"); export const ColumnsKey = new Key("SchemaColumns"); + export const SchemaSplitPercentage = new Key("SchemaSplitPercentage"); export const Caption = new Key("Caption"); export const ActiveFrame = new Key("ActiveFrame"); export const DocumentText = new Key("DocumentText"); @@ -33,7 +35,6 @@ export namespace KeyStore { export const LinkTags = new Key("LinkTag"); export const Thumbnail = new Key("Thumbnail"); export const CurPage = new Key("CurPage"); - export const CurFrame = new Key("CurFrame"); export const NumPages = new Key("NumPages"); export const Ink = new Key("Ink"); } -- cgit v1.2.3-70-g09d2