From c6a3faf616e68ede2d67580344e4337c3f0cfdc5 Mon Sep 17 00:00:00 2001 From: Jude Date: Sat, 9 Mar 2019 17:14:42 -0500 Subject: added some flair to freeform views --- src/client/views/InkingControl.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 929fb42a1..fc6a266e4 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -49,7 +49,7 @@ export class InkingControl extends React.Component { selected = (tool: InkTool) => { if (this._selectedTool === tool) { - return { backgroundColor: "black", color: "white" } + return { backgroundColor: "#61aaa3", color: "white" } } return {} } -- cgit v1.2.3-70-g09d2 From 06fb2bef46222c65d594b600bfeb72fb6a7f8212 Mon Sep 17 00:00:00 2001 From: Fawn Date: Sun, 10 Mar 2019 17:24:11 -0400 Subject: inking ui improvements --- src/client/views/InkingCanvas.scss | 121 +++++++++++++++++++++++++++++++++++-- src/client/views/InkingControl.tsx | 59 ++++++++++++------ src/client/views/Main.tsx | 5 +- 3 files changed, 158 insertions(+), 27 deletions(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index f654b194b..71c7e9ce0 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,3 +1,4 @@ +@import "global_variables"; .inking-canvas { position: fixed; top: -50000px; @@ -13,20 +14,128 @@ .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; + &:focus { + outline: none; + } + &::-webkit-slider-runnable-track { + width: 100%; + height: 3px; + border-radius: 1.5px; + cursor: pointer; + background: $light-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 3px; + } .ink-panel { - margin-top: 12px; + margin: 12px 18px 0 0; + height: 36px; + vertical-align: middle; + line-height: 36px; + padding: 0 10px; + background-color: $dark-color; + color: $light-color; + border-radius: 18px; &:first { margin-top: 0; } } + .ink-tools { + display: flex; + background-color: transparent; + border-radius: 0; + padding: 0; + button { + height: 36px; + border-radius: 18px; + margin-right: 6px; + padding: 0 16px; + font-size: 50%; + &:last-child { + margin-right: 0; + } + } + } .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; + .ink-color-display { + width: 60px; + height: 100%; + border-radius: 0 18px 18px 0; + margin-left: 6px; + cursor: pointer; + text-align: center; + span { + color: $light-color; + font-size: 8px; + user-select: none; + } + } + .ink-color-picker { + background-color: $dark-color; + border-radius: 5px; + padding: 6px; + position: absolute; + bottom: 42px; + left: 0; } } } \ No newline at end of file diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index fc6a266e4..695b761c9 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,16 +1,18 @@ import { observable, action, computed } from "mobx"; import { CirclePicker, ColorResult } from 'react-color' -import React = require("react"); -import "./InkingCanvas.scss" import { InkTool } from "../../fields/InkField"; import { observer } from "mobx-react"; +import React = require("react"); +import "./InkingCanvas.scss" @observer export class InkingControl extends React.Component { static Instance: InkingControl = new InkingControl({}); @observable private _selectedTool: InkTool = InkTool.None; - @observable private _selectedColor: string = "#f44336"; + @observable private _selectedColor: string = "rgb(244, 67, 54)"; @observable private _selectedWidth: string = "25"; + @observable private _open: boolean = false; + @observable private _colorPickerDisplay: boolean = false; constructor(props: Readonly<{}>) { super(props); @@ -54,24 +56,45 @@ export class InkingControl extends React.Component { return {} } + @action + toggleDisplay = () => { + this._open = !this._open; + } + + @action + toggleColorPicker = () => { + this._colorPickerDisplay = !this._colorPickerDisplay; + } + render() { return ( -
-
- - - - -
-
- - +
  • +
    + + + + +
    +
  • +
  • + + ) => this.switchWidth(e.target.value)} /> + ) => this.switchWidth(e.target.value)} /> -
  • -
    - -
    -
    + +
  • + +
    this.toggleColorPicker()}> + {this._colorPickerDisplay ? : } +
    +
    + +
    +
  • + ) } } \ No newline at end of file diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index e4ef90d97..d0bfa1f21 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -124,8 +124,7 @@ Documents.initProtos(mainDocId, (res?: Document) => { < div id="toolbar" > - {/* @TODO do the ink thing */} - < button className="toolbar-button round-button" title="Ink" > + {/* 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. */} @@ -164,7 +163,7 @@ Documents.initProtos(mainDocId, (res?: Document) => { - {/* */} + ), document.getElementById('root')); }) -- cgit v1.2.3-70-g09d2 From 99677c577a04aa289543ff5e97bd44e01b8fb4ab Mon Sep 17 00:00:00 2001 From: Jude Date: Mon, 11 Mar 2019 16:21:30 -0400 Subject: inking controls changes --- src/client/views/InkingCanvas.scss | 260 +++++++++++++++++++------------------ src/client/views/InkingControl.tsx | 33 +++-- 2 files changed, 152 insertions(+), 141 deletions(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index 71c7e9ce0..d132504fc 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,141 +1,147 @@ @import "global_variables"; .inking-canvas { - position: fixed; - top: -50000px; - left: -50000px; // z-index: 99; //overlays ink on top of everything - svg { - width: 100000px; - height: 100000px; - .highlight { - mix-blend-mode: multiply; - } + position: fixed; + top: -50000px; + left: -50000px; // z-index: 99; //overlays ink on top of everything + svg { + width: 100000px; + height: 100000px; + .highlight { + mix-blend-mode: multiply; } + } } .inking-control { - position: absolute; - left: 70px; - bottom: 70px; - margin: 0; - padding: 0; + position: absolute; + 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 3px; + background: transparent; + color: $light-color; + } + .ink-panel { + 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; - label, - input, - option { - font-size: 12px; + 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; } - input[type=range] { - -webkit-appearance: none; - background-color: transparent; - vertical-align: middle; - &:focus { - outline: none; - } - &::-webkit-slider-runnable-track { - width: 100%; - height: 3px; - border-radius: 1.5px; - cursor: pointer; - background: $light-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; - } + button:hover { + transform: scale(1.15); } - input[type=text] { - border: none; - padding: 0 3px; + } + .ink-size { + display: flex; + justify-content: space-between; + input[type="text"] { + width: 42px; } - .ink-panel { - margin: 12px 18px 0 0; - height: 36px; - vertical-align: middle; - line-height: 36px; - padding: 0 10px; - background-color: $dark-color; - color: $light-color; - border-radius: 18px; - &:first { - margin-top: 0; - } + > * { + margin-right: 6px; + &:last-child { + margin-right: 0; + } } - .ink-tools { - display: flex; - background-color: transparent; - border-radius: 0; - padding: 0; - button { - height: 36px; - border-radius: 18px; - margin-right: 6px; - padding: 0 16px; - font-size: 50%; - &:last-child { - margin-right: 0; - } - } + } + .ink-color { + display: flex; + position: relative; + padding-right: 0; + label { + margin-right: 6px; } - .ink-size { - display: flex; - justify-content: space-between; - input[type=text] { - width: 42px; - } - >* { - margin-right: 6px; - &:last-child { - margin-right: 0; - } - } + .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 { - display: flex; - position: relative; - padding-right: 0; - .ink-color-display { - width: 60px; - height: 100%; - border-radius: 0 18px 18px 0; - margin-left: 6px; - cursor: pointer; - text-align: center; - span { - color: $light-color; - font-size: 8px; - user-select: none; - } - } - .ink-color-picker { - background-color: $dark-color; - border-radius: 5px; - padding: 6px; - position: absolute; - bottom: 42px; - left: 0; - } + .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/InkingControl.tsx b/src/client/views/InkingControl.tsx index 695b761c9..523971af4 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -4,6 +4,11 @@ import { InkTool } from "../../fields/InkField"; import { observer } from "mobx-react"; import React = require("react"); import "./InkingCanvas.scss" +import { library } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons'; + +library.add(faPen, faHighlighter, faEraser, faBan); @observer export class InkingControl extends React.Component { @@ -51,7 +56,7 @@ export class InkingControl extends React.Component { selected = (tool: InkTool) => { if (this._selectedTool === tool) { - return { backgroundColor: "#61aaa3", color: "white" } + return { color: "#61aaa3" } } return {} } @@ -71,29 +76,29 @@ export class InkingControl extends React.Component {
    • - - - - + + + +
    • -
    • - - ) => this.switchWidth(e.target.value)} /> - ) => this.switchWidth(e.target.value)} /> -
    • this.toggleColorPicker()}> - {this._colorPickerDisplay ? : } + {/* {this._colorPickerDisplay ? : } */}
      - +
    • +
    • + + {/* ) => this.switchWidth(e.target.value)} /> */} + ) => this.switchWidth(e.target.value)} /> +
    ) } -- cgit v1.2.3-70-g09d2 From 736e0bdc6fb2b98592889bc7ba0991abd56bda29 Mon Sep 17 00:00:00 2001 From: Hannah Chow Date: Mon, 11 Mar 2019 17:35:54 -0400 Subject: linking kind of merged --- package-lock.json | 36 +++++++++++--- src/client/views/DocumentDecorations.scss | 82 ++++++++++++++++--------------- src/client/views/DocumentDecorations.tsx | 4 +- src/client/views/InkingControl.tsx | 6 +-- src/client/views/Main.tsx | 12 +---- src/client/views/nodes/DocumentView.tsx | 6 --- 6 files changed, 76 insertions(+), 70 deletions(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/package-lock.json b/package-lock.json index 75c02628e..4830b4ac1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3574,14 +3574,18 @@ }, "dependencies": { "readable-stream": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", - "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } } } @@ -11929,6 +11933,26 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "string_decoder": { diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index f39f31c3b..a29bf36fa 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,51 +1,18 @@ @import "global_variables"; #documentDecorations-container { -<<<<<<< HEAD - position: absolute; - display: grid; - z-index: 1000; - grid-template-rows: 8px 1fr 8px; - grid-template-columns: 8px 1fr 8px; - pointer-events: none; - #documentDecorations-centerCont { - background: none; - } - .documentDecorations-resizer { - pointer-events: auto; - background: $alt-accent; - opacity: 0.8; - } - #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; - } -} -======= 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 { @@ -63,8 +30,43 @@ #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 { height: 20px; width: 20px; @@ -74,6 +76,7 @@ pointer-events: auto; background-color: #2B6091; } + .linkButton-nonempty { height: 20px; width: 20px; @@ -82,5 +85,4 @@ opacity: 0.6; pointer-events: auto; background-color: rgb(35, 165, 42); -} ->>>>>>> 618e66a5a070f1aac9224bd3f44b76a5ac314bfa +} \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index a644e4dbe..b75644ecd 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -220,7 +220,7 @@ export class DocumentDecorations extends React.Component { return (
    @@ -234,7 +234,7 @@ export class DocumentDecorations extends React.Component {
    e.preventDefault()}>
    e.preventDefault()}>
    - {linkButton} +
    {linkButton}
    ) diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 96bf4d091..bf633b034 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,14 +1,10 @@ import { observable, action, computed } from "mobx"; -<<<<<<< HEAD + import { CirclePicker, ColorResult } from 'react-color' -======= -import { CirclePicker, ColorResult } from 'react-color'; import React = require("react"); import "./InkingCanvas.scss" ->>>>>>> 618e66a5a070f1aac9224bd3f44b76a5ac314bfa import { InkTool } from "../../fields/InkField"; import { observer } from "mobx-react"; -import React = require("react"); import "./InkingCanvas.scss" import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 1c0b9684e..687c765ec 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -82,7 +82,6 @@ Documents.initProtos(mainDocId, (res?: Document) => { let audiourl = "http://techslides.com/demos/samples/sample.mp3"; let videourl = "http://techslides.com/demos/sample-videos/small.mp4"; let clearDatabase = action(() => Utils.Emit(Server.Socket, MessageStore.DeleteAll, {})) -<<<<<<< HEAD let addTextNode = action(() => Documents.TextDocument({ width: 230, height: 130, title: "a text note" })) let addColNode = action(() => Documents.FreeformDocument([], { width: 300, height: 300, title: "a freeform collection" })); let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 450, height: 200, title: "a schema collection" })); @@ -91,16 +90,7 @@ Documents.initProtos(mainDocId, (res?: Document) => { let addWebNode = action(() => Documents.WebDocument(weburl, { width: 300, height: 400, title: "a sample web page" })); let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 300, height: 250, title: "video node" })); let addAudioNode = action(() => Documents.AudioDocument(audiourl, { width: 250, height: 100, title: "audio node" })); -======= - let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) - let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); - let addSchemaNode = action(() => Documents.SchemaDocument([Documents.TextDocument()], { width: 200, height: 200, title: "a schema collection" })); - let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" })); - let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" })); - let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); - let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" })); - let addAudioNode = action(() => Documents.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" })) ->>>>>>> 618e66a5a070f1aac9224bd3f44b76a5ac314bfa + let addClick = (creator: () => Document) => action(() => mainfreeform.GetList(KeyStore.Data, []).push(creator()) ); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 1db16aca6..dc793c16d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -100,17 +100,11 @@ export class DocumentView extends React.Component { onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; this._downY = e.clientY; -<<<<<<< HEAD - - if (e.shiftKey && e.buttons === 1) { - CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e); -======= if (e.shiftKey && e.buttons === 2) { if (this.props.isTopMost) { this.startDragging(e.pageX, e.pageY); } else CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e); ->>>>>>> 618e66a5a070f1aac9224bd3f44b76a5ac314bfa e.stopPropagation(); } else { if (this.active && !e.isDefaultPrevented()) { -- cgit v1.2.3-70-g09d2 From 3f7ff76768e0ff74e6a5d6e092f82e96661b3a2a Mon Sep 17 00:00:00 2001 From: Hannah Chow Date: Mon, 11 Mar 2019 20:16:18 -0400 Subject: pen tools styling and tooltips --- src/client/views/DocumentDecorations.scss | 1 - src/client/views/InkingCanvas.scss | 265 +++++++++++++++--------------- src/client/views/InkingControl.tsx | 16 +- 3 files changed, 141 insertions(+), 141 deletions(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index e77e22c5d..11595aa01 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -94,7 +94,6 @@ transition: transform 0.2s; text-align: center; display: flex; - vertical-align: middle; justify-content: center; align-items: center; } diff --git a/src/client/views/InkingCanvas.scss b/src/client/views/InkingCanvas.scss index d132504fc..d76861be1 100644 --- a/src/client/views/InkingCanvas.scss +++ b/src/client/views/InkingCanvas.scss @@ -1,147 +1,148 @@ @import "global_variables"; .inking-canvas { - position: fixed; - top: -50000px; - left: -50000px; // z-index: 99; //overlays ink on top of everything - svg { - width: 100000px; - height: 100000px; - .highlight { - mix-blend-mode: multiply; + position: fixed; + top: -50000px; + left: -50000px; // z-index: 99; //overlays ink on top of everything + svg { + width: 100000px; + height: 100000px; + .highlight { + mix-blend-mode: multiply; + } } - } } .inking-control { - position: absolute; - 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 3px; - background: transparent; - color: $light-color; - } - .ink-panel { - 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; + position: absolute; + left: 70px; + bottom: 70px; + margin: 0; padding: 0; - button { - height: 36px; - padding: 0px; - padding-bottom: 3px; - margin-left: 10px; - background-color: transparent; - color: $intermediate-color; + display: flex; + label, + input, + option { + font-size: 12px; } - button:hover { - transform: scale(1.15); + 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; + } } - } - .ink-size { - display: flex; - justify-content: space-between; input[type="text"] { - width: 42px; + border: none; + padding: 0 0px; + background: transparent; + color: $dark-color; + font-size: 12px; + margin-top: 4px; } - > * { - margin-right: 6px; - &:last-child { - margin-right: 0; - } + .ink-panel { + margin: 6px 12px 6px 0; + height: 30px; + vertical-align: middle; + line-height: 36px; + padding: 0 10px; + color: $intermediate-color; + &:first { + margin-top: 0; + } } - } - .ink-color { - display: flex; - position: relative; - padding-right: 0; - label { - margin-right: 6px; + .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-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-size { + display: flex; + justify-content: space-between; + input[type="text"] { + width: 42px; + } + >* { + margin-right: 6px; + &:last-child { + margin-right: 0; + } + } } - .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; + .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/InkingControl.tsx b/src/client/views/InkingControl.tsx index bf633b034..fb75ef2a5 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -78,14 +78,14 @@ export class InkingControl extends React.Component {
    • - - - - + + + +
    • - +
      this.toggleColorPicker()}> {/* {this._colorPickerDisplay ? : } */} @@ -95,9 +95,9 @@ export class InkingControl extends React.Component {
    • - - {/* ) => this.switchWidth(e.target.value)} /> */} + + ) => this.switchWidth(e.target.value)} /> ) => this.switchWidth(e.target.value)} />
    • -- cgit v1.2.3-70-g09d2 From 1bf3a5a0108704a0204cedcbad6e6d52d19cf982 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 17 Mar 2019 22:04:03 -0400 Subject: moved DocumentContents to DocumentContentsView --- src/client/views/InkingControl.tsx | 8 +++ .../views/collections/CollectionFreeFormView.tsx | 34 ++---------- src/client/views/collections/MarqueeView.tsx | 2 +- src/client/views/collections/PreviewCursor.tsx | 10 ++-- src/client/views/nodes/DocumentContentsView.tsx | 60 +++++++++++++++------- src/client/views/nodes/DocumentView.tsx | 55 ++------------------ 6 files changed, 62 insertions(+), 107 deletions(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index fb75ef2a5..6616f68d8 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -9,6 +9,8 @@ import "./InkingCanvas.scss" import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons'; +import { SelectionManager } from "../util/SelectionManager"; +import { KeyStore } from "../../fields/KeyStore"; library.add(faPen, faHighlighter, faEraser, faBan); @@ -34,6 +36,12 @@ export class InkingControl extends React.Component { @action switchColor = (color: ColorResult): void => { this._selectedColor = color.hex; + if (SelectionManager.SelectedDocuments().length == 1) { + var sdoc = SelectionManager.SelectedDocuments()[0]; + if (sdoc.props.ContainingCollectionView && sdoc.props.ContainingCollectionView) { + sdoc.props.Document.SetText(KeyStore.BackgroundColor, color.hex); + } + } } @action diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 988c9941f..cca57912c 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -8,28 +8,16 @@ import { TextField } from "../../../fields/TextField"; import { DragManager } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionPDFView } from "../collections/CollectionPDFView"; -import { CollectionSchemaView } from "../collections/CollectionSchemaView"; -import { CollectionVideoView } from "../collections/CollectionVideoView"; -import { CollectionView } from "../collections/CollectionView"; import { InkingCanvas } from "../InkingCanvas"; -import { AudioBox } from "../nodes/AudioBox"; import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; -import { DocumentView, DocumentViewProps, DocumentContents } from "../nodes/DocumentView"; -import { FormattedTextBox } from "../nodes/FormattedTextBox"; -import { ImageBox } from "../nodes/ImageBox"; -import { KeyValueBox } from "../nodes/KeyValueBox"; -import { PDFBox } from "../nodes/PDFBox"; -import { VideoBox } from "../nodes/VideoBox"; -import { WebBox } from "../nodes/WebBox"; +import { DocumentContentsView } from "../nodes/DocumentContentsView"; +import { DocumentView, DocumentViewProps } from "../nodes/DocumentView"; import "./CollectionFreeFormView.scss"; import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; import { MarqueeView } from "./MarqueeView"; import { PreviewCursor } from "./PreviewCursor"; import React = require("react"); -const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? @observer export class CollectionFreeFormView extends CollectionViewBase { @@ -283,28 +271,14 @@ export class CollectionFreeFormView extends CollectionViewBase { @computed get backgroundView() { return !this.backgroundLayout ? (null) : - ( false} select={() => { }} />); - // ( console.log(test)} - // />); } @computed get overlayView() { return !this.overlayLayout ? (null) : - ( false} select={() => { }} />); - // ( console.log(test)} - // />); } getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform()) diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx index 65aaa837f..f5c83a934 100644 --- a/src/client/views/collections/MarqueeView.tsx +++ b/src/client/views/collections/MarqueeView.tsx @@ -121,7 +121,7 @@ export class MarqueeView extends React.Component let centerShiftX = 0 - (selRect.left + selRect.width / 2); // moves each point by the offset that shifts the selection's center to the origin. let centerShiftY = 0 - (selRect.top + selRect.height / 2); let ink = this.props.container.props.Document.GetT(KeyStore.Ink, InkField); - if (ink && ink != FieldWaiting) { + if (ink && ink != FieldWaiting && ink.Data) { let idata = new Map(); ink.Data.forEach((value: StrokeData, key: string, map: any) => { let inside = InkingCanvas.IntersectStrokeRect(value, selRect); diff --git a/src/client/views/collections/PreviewCursor.tsx b/src/client/views/collections/PreviewCursor.tsx index a1411250a..cbcfa568d 100644 --- a/src/client/views/collections/PreviewCursor.tsx +++ b/src/client/views/collections/PreviewCursor.tsx @@ -1,16 +1,12 @@ -import { trace } from "mobx"; -import "./PreviewCursor.scss"; -import React = require("react"); import { action, IReactionDisposer, observable, reaction } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { FieldWaiting, Opt } from "../../../fields/Field"; -import { KeyStore } from "../../../fields/KeyStore"; -import { ListField } from "../../../fields/ListField"; +import { Opt } from "../../../fields/Field"; import { Documents } from "../../documents/Documents"; -import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { CollectionFreeFormView } from "./CollectionFreeFormView"; +import "./PreviewCursor.scss"; +import React = require("react"); export interface PreviewCursorProps { diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 55b4938a0..ce72ab64b 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -1,33 +1,55 @@ -import { Document } from "../../../fields/Document"; -import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; +import { computed } from "mobx"; +import { observer } from "mobx-react"; +import { FieldWaiting } from "../../../fields/Field"; +import { Key } from "../../../fields/Key"; +import { KeyStore } from "../../../fields/KeyStore"; +import { ListField } from "../../../fields/ListField"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { CollectionSchemaView } from "../collections/CollectionSchemaView"; -import { CollectionView, CollectionViewType } from "../collections/CollectionView"; +import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; import { CollectionPDFView } from "../collections/CollectionPDFView"; +import { CollectionSchemaView } from "../collections/CollectionSchemaView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; -import { FormattedTextBox } from "../nodes/FormattedTextBox"; -import { ImageBox } from "../nodes/ImageBox"; -import { VideoBox } from "../nodes/VideoBox"; -import { AudioBox } from "../nodes/AudioBox"; -import { KeyValueBox } from "./KeyValueBox" -import { WebBox } from "../nodes/WebBox"; -import { PDFBox } from "../nodes/PDFBox"; +import { CollectionView } from "../collections/CollectionView"; +import { AudioBox } from "./AudioBox"; +import { DocumentViewProps, JsxBindings } from "./DocumentView"; import "./DocumentView.scss"; +import { FormattedTextBox } from "./FormattedTextBox"; +import { ImageBox } from "./ImageBox"; +import { KeyValueBox } from "./KeyValueBox"; +import { PDFBox } from "./PDFBox"; +import { VideoBox } from "./VideoBox"; +import { WebBox } from "./WebBox"; import React = require("react"); const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? -interface JsxBindings { - Document: Document; - layout: string; - [prop: string]: any; -} -export class DocumentContentsView extends React.PureComponent { +@observer +export class DocumentContentsView extends React.Component boolean, + select: (ctrl: boolean) => void, + layoutKey: Key +}> { + @computed get layout(): string { return this.props.Document.GetText(this.props.layoutKey, "

      Error loading layout data

      "); } + @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array()); } + @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array()); } + + CreateBindings(): JsxBindings { + let bindings: JsxBindings = { ...this.props, }; + for (const key of this.layoutKeys) { + bindings[key.Name + "Key"] = key; // this maps string values of the form Key to an actual key Kestore.keyname e.g, "DataKey" => KeyStore.Data + } + for (const key of this.layoutFields) { + let field = this.props.Document.Get(key); + bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field; + } + return bindings; + } + render() { return { console.log(test) }} /> diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 3e691ee6d..b36d47b8b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,11 +1,12 @@ import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Document } from "../../../fields/Document"; -import { Field, FieldWaiting, Opt } from "../../../fields/Field"; +import { Field, Opt } from "../../../fields/Field"; import { Key } from "../../../fields/Key"; import { KeyStore } from "../../../fields/KeyStore"; import { ListField } from "../../../fields/ListField"; import { TextField } from "../../../fields/TextField"; +import { Utils } from "../../../Utils"; import { Documents } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager } from "../../util/DragManager"; @@ -14,22 +15,9 @@ import { Transform } from "../../util/Transform"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionView, CollectionViewType } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; +import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); -import { DocumentContentsView } from "./DocumentContentsView"; -import { Utils } from "../../../Utils"; -import { FormattedTextBox } from "./FormattedTextBox"; -import { ImageBox } from "./ImageBox"; -import { CollectionFreeFormView } from "../collections/CollectionFreeFormView"; -import { CollectionSchemaView } from "../collections/CollectionSchemaView"; -import { CollectionPDFView } from "../collections/CollectionPDFView"; -import { CollectionVideoView } from "../collections/CollectionVideoView"; -import { WebBox } from "./WebBox"; -import { KeyValueBox } from "./KeyValueBox"; -import { PDFBox } from "./PDFBox"; -import { VideoBox } from "./VideoBox"; -import { AudioBox } from "./AudioBox"; -const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? export interface DocumentViewProps { @@ -87,7 +75,7 @@ export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { return args; } -interface JsxBindings { +export interface JsxBindings { Document: Document; isSelected: () => boolean; select: (isCtrlPressed: boolean) => void; @@ -96,40 +84,7 @@ interface JsxBindings { [prop: string]: any; } -@observer -export class DocumentContents extends React.Component boolean, - select: (ctrl: boolean) => void, - layoutKey: Key -}> { - @computed get layout(): string { return this.props.Document.GetText(this.props.layoutKey, "

      Error loading layout data

      "); } - @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array()); } - @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array()); } - - CreateBindings(): JsxBindings { - let bindings: JsxBindings = { - ...this.props, - }; - for (const key of this.layoutKeys) { - bindings[key.Name + "Key"] = key; // this maps string values of the form Key to an actual key Kestore.keyname e.g, "DataKey" => KeyStore.Data - } - for (const key of this.layoutFields) { - let field = this.props.Document.Get(key); - bindings[key.Name] = field && field != FieldWaiting ? field.GetValue() : field; - } - return bindings; - } - render() { - return { console.log(test) }} - /> - } -} @observer export class DocumentView extends React.Component { @@ -377,7 +332,7 @@ export class DocumentView extends React.Component { onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} > - + ) } -- cgit v1.2.3-70-g09d2 From 8418b842b16da68150243e1750aa8b40eb8a8792 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 18 Mar 2019 11:48:24 -0400 Subject: fixed removing from schemas. fixed dragging link button to move quickly. cleaned up drag/drop code a little --- src/client/util/DragManager.ts | 12 +++----- src/client/views/DocumentDecorations.tsx | 14 ++++----- src/client/views/InkingControl.tsx | 3 +- .../views/collections/CollectionFreeFormView.tsx | 4 +-- src/client/views/collections/CollectionPDFView.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 4 +-- .../views/collections/CollectionVideoView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 7 +++-- .../views/collections/CollectionViewBase.tsx | 36 ++++++++-------------- src/client/views/collections/MarqueeView.tsx | 15 +++++++-- src/client/views/nodes/DocumentView.tsx | 16 +++++----- 11 files changed, 57 insertions(+), 58 deletions(-) (limited to 'src/client/views/InkingControl.tsx') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c0abec407..54784f2d2 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -2,18 +2,18 @@ import { DocumentDecorations } from "../views/DocumentDecorations"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import { Document } from "../../fields/Document" import { action } from "mobx"; -import { DocumentView } from "../views/nodes/DocumentView"; import { ImageField } from "../../fields/ImageField"; import { KeyStore } from "../../fields/KeyStore"; +import { CollectionView } from "../views/collections/CollectionView"; -export function setupDrag(_reference: React.RefObject, docFunc: () => Document) { +export function setupDrag(_reference: React.RefObject, docFunc: () => Document, removeFunc: (containingCollection: CollectionView) => void = () => { }) { let onRowMove = action((e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); - DragManager.StartDrag(_reference.current!, { document: docFunc() }); + DragManager.StartDrag(_reference.current!, { draggedDocument: docFunc(), removeDocument: removeFunc }); }); let onRowUp = action((e: PointerEvent): void => { document.removeEventListener("pointermove", onRowMove); @@ -122,9 +122,7 @@ export namespace DragManager { // bcz: PDFs don't show up if you clone them because they contain a canvas. // however, PDF's have a thumbnail field that contains an image of their canvas. // So we replace the pdf's canvas with the image thumbnail - const docView: DocumentView = dragData["documentView"]; - const doc: Document = dragData["document"]; - + const doc: Document = dragData["draggedDocument"]; if (doc) { var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement; let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField); @@ -138,7 +136,6 @@ export namespace DragManager { } } - dragDiv.appendChild(dragElement); let hideSource = false; @@ -191,6 +188,7 @@ export namespace DragManager { if (!target) { return; } + dragData["droppedDocument"] = dragData["aliasOnDrop"] ? (dragData["draggedDocument"] as Document).CreateAlias() : dragData["draggedDocument"]; target.dispatchEvent(new CustomEvent("dashOnDrop", { bubbles: true, detail: { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 3bdb7d5b3..1145fbe7f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -77,7 +77,6 @@ export class DocumentDecorations extends React.Component { } onLinkButtonUp = (e: PointerEvent): void => { - console.log("up"); document.removeEventListener("pointermove", this.onLinkButtonMoved) document.removeEventListener("pointerup", this.onLinkButtonUp) e.stopPropagation(); @@ -85,10 +84,11 @@ export class DocumentDecorations extends React.Component { onLinkButtonMoved = (e: PointerEvent): void => { - console.log("moved"); - let dragData: { [id: string]: any } = {}; - dragData["linkSourceDoc"] = SelectionManager.SelectedDocuments()[0]; if (this._linkButton.current != null) { + document.removeEventListener("pointermove", this.onLinkButtonMoved) + document.removeEventListener("pointerup", this.onLinkButtonUp) + let dragData: { [id: string]: any } = {}; + dragData["linkSourceDoc"] = SelectionManager.SelectedDocuments()[0]; DragManager.StartDrag(this._linkButton.current, dragData, { handlers: { dragComplete: action(() => { }), @@ -96,8 +96,6 @@ export class DocumentDecorations extends React.Component { hideSource: false }) } - document.removeEventListener("pointermove", this.onLinkButtonMoved) - document.removeEventListener("pointerup", this.onLinkButtonUp) e.stopPropagation(); } @@ -217,7 +215,7 @@ export class DocumentDecorations extends React.Component { }> -
      {linkCount}
      +
      {linkCount}
      ); } return ( @@ -237,7 +235,7 @@ export class DocumentDecorations extends React.Component {
      e.preventDefault()}>
      e.preventDefault()}>
      -
      {linkButton}
      +
      {linkButton}
      ) diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 6616f68d8..ad6bbd476 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -11,6 +11,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons'; import { SelectionManager } from "../util/SelectionManager"; import { KeyStore } from "../../fields/KeyStore"; +import { TextField } from "../../fields/TextField"; library.add(faPen, faHighlighter, faEraser, faBan); @@ -39,7 +40,7 @@ export class InkingControl extends React.Component { if (SelectionManager.SelectedDocuments().length == 1) { var sdoc = SelectionManager.SelectedDocuments()[0]; if (sdoc.props.ContainingCollectionView && sdoc.props.ContainingCollectionView) { - sdoc.props.Document.SetText(KeyStore.BackgroundColor, color.hex); + sdoc.props.Document.SetOnPrototype(KeyStore.BackgroundColor, new TextField(color.hex)); } } } diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx index 728076ef8..85ea2d121 100644 --- a/src/client/views/collections/CollectionFreeFormView.tsx +++ b/src/client/views/collections/CollectionFreeFormView.tsx @@ -28,7 +28,7 @@ export class CollectionFreeFormView extends CollectionViewBase { // mark this collection so that when the text box is created we can send it the SelectOnLoad prop to focus itself this._selectOnLoaded = newBox.Id; //set text to be the typed key and get focus on text box - this.props.addDocument(newBox); + this.props.addDocument(newBox, false); //remove cursor from screen this.PreviewCursorVisible = false; } @@ -79,7 +79,7 @@ export class CollectionFreeFormView extends CollectionViewBase { let screenX = de.x - (de.data["xOffset"] as number || 0); let screenY = de.y - (de.data["yOffset"] as number || 0); const [x, y] = this.getTransform().transformPoint(screenX, screenY); - let doc: Document = de.data["document"]; + let doc: Document = de.data["droppedDocument"]; if (doc) { doc.SetNumber(KeyStore.X, x); doc.SetNumber(KeyStore.Y, y); diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index 124d82c8b..e64b4c945 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -38,7 +38,7 @@ export class CollectionPDFView extends React.Component { public SelectedDocs: FieldId[] = [] public active: () => boolean = () => CollectionView.Active(this); - addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + addDocument = (doc: Document, allowDuplicates: boolean): void => { CollectionView.AddDocument(this.props, doc, allowDuplicates); } removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } specificContextMenu = (e: React.MouseEvent): void => { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index f88a62a0f..ced08a14e 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -14,7 +14,7 @@ import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; -import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; import { setupDrag } from "../../util/DragManager"; @@ -47,7 +47,7 @@ export class CollectionSchemaView extends CollectionViewBase { ) let reference = React.createRef(); - let onItemDown = setupDrag(reference, () => props.doc); + let onItemDown = setupDrag(reference, () => props.doc, (containingCollection: CollectionView) => this.props.removeDocument(props.doc)); return (
      { public SelectedDocs: FieldId[] = [] public active: () => boolean = () => CollectionView.Active(this); - addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + addDocument = (doc: Document, allowDuplicates: boolean): void => { CollectionView.AddDocument(this.props, doc, allowDuplicates); } removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } specificContextMenu = (e: React.MouseEvent): void => { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 40acf466e..303099c16 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -36,7 +36,7 @@ export class CollectionView extends React.Component { @observable public SelectedDocs: FieldId[] = []; public active: () => boolean = () => CollectionView.Active(this); - addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); } + addDocument = (doc: Document, allowDuplicates: boolean): void => { CollectionView.AddDocument(this.props, doc, allowDuplicates); } removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); } get subView() { return CollectionView.SubView(this); } @@ -48,12 +48,13 @@ export class CollectionView extends React.Component { } @action - public static AddDocument(props: CollectionViewProps, doc: Document) { + public static AddDocument(props: CollectionViewProps, doc: Document, allowDuplicates: boolean) { doc.SetNumber(KeyStore.Page, props.Document.GetNumber(KeyStore.CurPage, -1)); if (props.Document.Get(props.fieldKey) instanceof Field) { //TODO This won't create the field if it doesn't already exist const value = props.Document.GetData(props.fieldKey, ListField, new Array()) - value.push(doc); + if (!value.some(v => v.Id == doc.Id) || allowDuplicates) + value.push(doc); } else { props.Document.SetOnPrototype(props.fieldKey, new ListField([doc])); } diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx index 3d1a76a07..0358b5907 100644 --- a/src/client/views/collections/CollectionViewBase.tsx +++ b/src/client/views/collections/CollectionViewBase.tsx @@ -27,7 +27,7 @@ export interface CollectionViewProps { } export interface SubCollectionViewProps extends CollectionViewProps { active: () => boolean; - addDocument: (doc: Document) => void; + addDocument: (doc: Document, allowDuplicates: boolean) => void; removeDocument: (doc: Document) => boolean; CollectionView: CollectionView; } @@ -46,28 +46,16 @@ export class CollectionViewBase extends React.Component @undoBatch @action protected drop(e: Event, de: DragManager.DropEvent) { - let docToAlias = de.data["documentToAlias"]; - let docView = de.data["documentView"]; - let doc = docToAlias ? docToAlias.CreateAlias() : de.data["document"]; - if (docToAlias) { - [KeyStore.Width, KeyStore.Height].map(key => - docToAlias.GetTAsync(key, NumberField, (f: Opt) => { - if (f) { - doc.SetNumber(key, f.Data) - } - }) - ); - de.data["document"] = doc; - this.props.addDocument(doc); - } else if (docView) { - if (doc && docView.props.RemoveDocument && docView.props.ContainingCollectionView !== this.props.CollectionView) { - docView.props.RemoveDocument(doc); - this.props.removeDocument(doc); // bcz: not good -- want to check if it's there and then add if it isn't - this.props.addDocument(doc); + let dropped = de.data["droppedDocument"]; + if (dropped) { + if (de.data["aliasOnDrop"]) { + let dragged = de.data["draggedDocument"]; + [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => + dragged.GetTAsync(key, NumberField, (f: Opt) => f ? dropped.SetNumber(key, f.Data) : null)); + } else if (de.data["removeDocument"]) { + de.data["removeDocument"](this.props.CollectionView); } - } else if (doc) { - this.props.removeDocument(doc); // bcz: not good -- want to check if it's there and then add if it isn't - this.props.addDocument(doc); + this.props.addDocument(dropped, false); } e.stopPropagation(); } @@ -89,7 +77,7 @@ export class CollectionViewBase extends React.Component console.log("not good"); let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 }); htmlDoc.SetText(KeyStore.DocumentText, text); - this.props.addDocument(htmlDoc); + this.props.addDocument(htmlDoc, false); return; } @@ -99,7 +87,7 @@ export class CollectionViewBase extends React.Component const upload = window.location.origin + "/upload"; let item = e.dataTransfer.items[i]; if (item.kind === "string" && item.type.indexOf("uri") != -1) { - e.dataTransfer.items[i].getAsString(action((s: string) => this.props.addDocument(Documents.WebDocument(s, options)))) + e.dataTransfer.items[i].getAsString(action((s: string) => this.props.addDocument(Documents.WebDocument(s, options), false))) } let type = item.type console.log(type) diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx index f5c83a934..8c2f3443c 100644 --- a/src/client/views/collections/MarqueeView.tsx +++ b/src/client/views/collections/MarqueeView.tsx @@ -17,7 +17,7 @@ interface MarqueeViewProps { getMarqueeTransform: () => Transform; getTransform: () => Transform; container: CollectionFreeFormView; - addDocument: (doc: Document) => void; + addDocument: (doc: Document, allowDuplicates: false) => void; activeDocuments: () => Document[]; selectDocuments: (docs: Document[]) => void; removeDocument: (doc: Document) => boolean; @@ -111,7 +111,18 @@ export class MarqueeView extends React.Component let liftedInk = this.marqueeInkSelect(true); this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField); //setTimeout(() => { - this.props.addDocument(Documents.FreeformDocument(selected, { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, backgroundColor: "Transparent", height: bounds.height, ink: liftedInk, title: "a nested collection" })); + let newCollection = Documents.FreeformDocument(selected, { + x: bounds.left, + y: bounds.top, + panx: 0, + pany: 0, + width: bounds.width, + height: bounds.height, + backgroundColor: "Transparent", + ink: liftedInk, + title: "a nested collection" + }); + this.props.addDocument(newCollection, false); // }, 100); this.cleanupInteractions(); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index fbd58ef7e..e98815fa6 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -23,7 +23,7 @@ import React = require("react"); export interface DocumentViewProps { ContainingCollectionView: Opt; Document: Document; - AddDocument?: (doc: Document) => void; + AddDocument?: (doc: Document, allowDuplicates: boolean) => void; RemoveDocument?: (doc: Document) => boolean; ScreenToLocalTransform: () => Transform; isTopMost: boolean; @@ -164,12 +164,15 @@ export class DocumentView extends React.Component { if (this._mainCont.current) { const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0); let dragData: { [id: string]: any } = {}; - dragData["documentView"] = this; - if (dropAliasOfDraggedDoc) - dragData["documentToAlias"] = this.props.Document; - dragData["document"] = this.props.Document; + dragData["aliasOnDrop"] = dropAliasOfDraggedDoc; + dragData["draggedDocument"] = this.props.Document; dragData["xOffset"] = x - left; dragData["yOffset"] = y - top; + dragData["removeDocument"] = (dropCollectionView: CollectionView) => { + if (this.props.RemoveDocument && this.props.ContainingCollectionView !== dropCollectionView) { + this.props.RemoveDocument(this.props.Document); + } + } DragManager.StartDrag(this._mainCont.current, dragData, { handlers: { dragComplete: action(() => { }), @@ -213,7 +216,7 @@ export class DocumentView extends React.Component { fieldsClicked = (e: React.MouseEvent): void => { if (this.props.AddDocument) { - this.props.AddDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 })); + this.props.AddDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false); } } fullScreenClicked = (e: React.MouseEvent): void => { @@ -232,7 +235,6 @@ export class DocumentView extends React.Component { @action drop = (e: Event, de: DragManager.DropEvent) => { - console.log("drop"); const sourceDocView: DocumentView = de.data["linkSourceDoc"]; if (!sourceDocView) { return; -- cgit v1.2.3-70-g09d2