aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2020-08-19 19:36:26 -0400
committerbobzel <zzzman@gmail.com>2020-08-19 19:36:26 -0400
commit9ab88617231edf79b8f1a85e997d02a04ced85fd (patch)
tree9a4a7a683127135ed727656afd1f9aa6849fc65d
parentdee04716bb572bff63f205348e90d80d2e609532 (diff)
parentbc7de4993eef673c6ab637343e85ec325c65e3f9 (diff)
Merge branch 'menu_restructure'
-rw-r--r--src/client/util/SettingsManager.tsx2
-rw-r--r--src/client/views/collections/CollectionMenu.scss51
-rw-r--r--src/client/views/collections/CollectionMenu.tsx158
-rw-r--r--src/client/views/collections/CollectionSchemaMovableTableHOC.tsx26
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx6
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx23
-rw-r--r--src/client/views/nodes/DocumentView.tsx10
7 files changed, 256 insertions, 20 deletions
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index b4778d3eb..5642c5a42 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -32,7 +32,7 @@ export default class SettingsManager extends React.Component<{}> {
@observable private new_password = "";
@observable private new_confirm = "";
- @computed get backgroundColor() { return Doc.UserDoc().defaultColor; }
+ @computed get backgroundColor() { return Doc.UserDoc().activeCollectionBackground; }
constructor(props: {}) {
super(props);
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index 30d5103bf..d0bfd0a41 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -315,6 +315,57 @@
}
}
+.webBox-urlEditor {
+ position: relative;
+ opacity: 0.9;
+ z-index: 9001;
+ transition: top .5s;
+
+ .urlEditor {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ padding-bottom: 10px;
+ overflow: hidden;
+ margin-top: 5px;
+ height: 35px;
+
+ .editorBase {
+ display: flex;
+
+ .editor-collapse {
+ transition: all .5s, opacity 0.3s;
+ position: absolute;
+ width: 40px;
+ transform-origin: top left;
+ }
+
+ .switchToText {
+ color: $main-accent;
+ }
+
+ .switchToText:hover {
+ color: $dark-color;
+ }
+ }
+
+ button:hover {
+ transform: scale(1);
+ }
+ }
+}
+
+.webpage-urlInput {
+ padding: 12px 10px 11px 10px;
+ border: 0px;
+ color: grey;
+ letter-spacing: 2px;
+ outline-color: black;
+ background: rgb(238, 238, 238);
+ width: 100%;
+ margin-right: 10px;
+ height: 100%;
+}
+
.collectionFreeFormMenu-cont {
display: inline-flex;
position: relative;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 28ba6945a..cf053e1ca 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -14,10 +14,12 @@ import { ObjectField } from "../../../fields/ObjectField";
import { listSpec } from "../../../fields/Schema";
import { ScriptField } from "../../../fields/ScriptField";
import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
+import { WebField } from "../../../fields/URLField";
import { emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils";
import { DocumentType } from "../../documents/DocumentTypes";
import { CurrentUserUtils } from "../../util/CurrentUserUtils";
import { DragManager } from "../../util/DragManager";
+import { Scripting } from "../../util/Scripting";
import { SelectionManager } from "../../util/SelectionManager";
import { undoBatch } from "../../util/UndoManager";
import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu";
@@ -29,7 +31,6 @@ import { DocumentView } from "../nodes/DocumentView";
import RichTextMenu from "../nodes/formattedText/RichTextMenu";
import "./CollectionMenu.scss";
import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
-import { Scripting } from "../../util/Scripting";
@observer
export default class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -607,6 +608,158 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
</div>;
}
+ @action
+ onUrlDrop = (e: React.DragEvent) => {
+ const { dataTransfer } = e;
+ const html = dataTransfer.getData("text/html");
+ const uri = dataTransfer.getData("text/uri-list");
+ const url = uri || html || this._url;
+ this._url = url.startsWith(window.location.origin) ?
+ url.replace(window.location.origin, this._url.match(/http[s]?:\/\/[^\/]*/)?.[0] || "") : url;
+ this.submitURL();
+ e.stopPropagation();
+ }
+ onUrlDragover = (e: React.DragEvent) => {
+ e.preventDefault();
+ }
+
+ @computed get _url() {
+ return this.selectedDoc ? Cast(this.selectedDoc["data"], WebField, null)?.url.toString() : "hello";
+ }
+
+ set _url(value) { this.selectedDoc && (this.selectedDoc["data"] = value); }
+
+ @action
+ submitURL = () => {
+ if (!this._url.startsWith("http")) this._url = "http://" + this._url;
+ try {
+ const URLy = new URL(this._url);
+ const future = this.selectedDoc ? Cast(this.selectedDoc["data-future"], listSpec("string"), null) : null;
+ const history = this.selectedDoc ? Cast(this.selectedDoc["data-history"], listSpec("string"), null) : [];
+ const annos = this.selectedDoc ? DocListCast(this.selectedDoc["data-annotations"]) : undefined;
+ const url = this.selectedDoc ? Cast(this.selectedDoc["data"], WebField, null)?.url.toString() : null;
+ if (url) {
+ if (history === undefined) {
+ this.selectedDoc && (this.selectedDoc["data-history"] = new List<string>([url]));
+
+ } else {
+ history.push(url);
+ }
+ future && (future.length = 0);
+ this.selectedDoc && (this.selectedDoc["data-" + this.urlHash(url)] = new List<Doc>(annos));
+ }
+ this.selectedDoc && (this.selectedDoc["data"] = new WebField(URLy));
+ this.selectedDoc && (this.selectedDoc["data-annotations"] = new List<Doc>([]));
+ } catch (e) {
+ console.log("WebBox URL error:" + this._url);
+ }
+ }
+
+ urlHash(s: string) {
+ return s.split('').reduce((a: any, b: any) => { a = ((a << 5) - a) + b.charCodeAt(0); return a & a; }, 0);
+ }
+
+ toggleAnnotationMode = () => {
+ this.props.docView.layoutDoc.isAnnotating = !this.props.docView.layoutDoc.isAnnotating;
+ }
+
+ @action
+ onURLChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ this._url = e.target.value;
+ }
+
+ onValueKeyDown = async (e: React.KeyboardEvent) => {
+ if (e.key === "Enter") {
+ this.submitURL();
+ }
+ e.stopPropagation();
+ }
+
+ @action
+ forward = () => {
+ const future = this.selectedDoc && (Cast(this.selectedDoc["data-future"], listSpec("string"), null));
+ const history = this.selectedDoc && Cast(this.selectedDoc["data-history"], listSpec("string"), null);
+ if (future?.length) {
+ history?.push(this._url);
+ this.selectedDoc && (this.selectedDoc["data-annotations-" + this.urlHash(this._url)] = new List<Doc>(DocListCast(this.selectedDoc["data-annotations"])));
+ this.selectedDoc && (this.selectedDoc["data"] = new WebField(new URL(this._url = future.pop()!)));
+ this.selectedDoc && (this.selectedDoc["data-annotations"] = new List<Doc>(DocListCast(this.selectedDoc["data-annotations" + "-" + this.urlHash(this._url)])));
+ }
+ }
+
+ @action
+ back = () => {
+ const future = this.selectedDoc && (Cast(this.selectedDoc["data-future"], listSpec("string"), null));
+ const history = this.selectedDoc && Cast(this.selectedDoc["data-history"], listSpec("string"), null);
+ if (history?.length) {
+ if (future === undefined) this.selectedDoc && (this.selectedDoc["data-future"] = new List<string>([this._url]));
+ else future.push(this._url);
+ this.selectedDoc && (this.selectedDoc["data-annotations" + "-" + this.urlHash(this._url)] = new List<Doc>(DocListCast(this.selectedDoc["data-annotations"])));
+ this.selectedDoc && (this.selectedDoc["data"] = new WebField(new URL(this._url = history.pop()!)));
+ this.selectedDoc && (this.selectedDoc["data-annotations"] = new List<Doc>(DocListCast(this.selectedDoc["data-annotations" + "-" + this.urlHash(this._url)])));
+ }
+ }
+
+ private _keyInput = React.createRef<HTMLInputElement>();
+
+ @computed get urlEditor() {
+ return (
+ <div className="webBox-urlEditor"
+ onDrop={this.onUrlDrop}
+ onDragOver={this.onUrlDragover} style={{ top: 0 }}>
+ <div className="urlEditor">
+ <div className="editorBase">
+ <div className="webBox-buttons"
+ onDrop={this.onUrlDrop}
+ onDragOver={this.onUrlDragover} style={{ display: "flex" }}>
+ <div className="webBox-freeze" title={"Annotate"}
+ style={{ background: this.props.docView.layoutDoc.isAnnotating ? "lightBlue" : "gray" }}
+ onClick={this.toggleAnnotationMode} >
+ <FontAwesomeIcon icon="pen" size={"2x"} />
+ </div>
+ <div className="webBox-freeze" title={"Select"}
+ style={{ background: !this.props.docView.layoutDoc.isAnnotating ? "lightBlue" : "gray" }}
+ onClick={this.toggleAnnotationMode} >
+ <FontAwesomeIcon icon={"mouse-pointer"} size={"2x"} />
+ </div>
+ <input className="webpage-urlInput"
+ placeholder="ENTER URL"
+ value={this._url}
+ onDrop={this.onUrlDrop}
+ onDragOver={this.onUrlDragover}
+ onChange={this.onURLChange}
+ onKeyDown={this.onValueKeyDown}
+ onClick={(e) => {
+ this._keyInput.current!.select();
+ e.stopPropagation();
+ }}
+ ref={this._keyInput}
+ />
+ <div style={{
+ display: "flex",
+ flexDirection: "row",
+ justifyContent: "space-between",
+ maxWidth: "120px",
+ }}>
+ <button className="submitUrl" onClick={this.submitURL}
+ onDragOver={this.onUrlDragover} onDrop={this.onUrlDrop}>
+ GO
+ </button>
+ <button className="submitUrl" onClick={this.back}>
+ <FontAwesomeIcon icon="caret-left" size="lg"></FontAwesomeIcon>
+ </button>
+ <button className="submitUrl" onClick={this.forward}>
+ <FontAwesomeIcon icon="caret-right" size="lg"></FontAwesomeIcon>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+
+
@observable viewType = this.selectedDoc?._viewType;
render() {
@@ -648,6 +801,9 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
</button>
</Tooltip>
}
+ {/* {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText || this.props.isDoc ? (null) :
+ this.urlEditor
+ } */}
{!this.isText ?
<>
{this.drawButtons}
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 615f9bb77..4754adc90 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -1,19 +1,19 @@
import React = require("react");
-import { ReactTableDefaults, TableCellRenderer, RowInfo } from "react-table";
-import "./CollectionSchemaView.scss";
-import { Transform } from "../../util/Transform";
-import { Doc } from "../../../fields/Doc";
-import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager";
-import { Cast, FieldValue, StrCast } from "../../../fields/Types";
-import { ContextMenu } from "../ContextMenu";
-import { action } from "mobx";
import { library } from '@fortawesome/fontawesome-svg-core';
import { faGripVertical, faTrash } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { DocumentManager } from "../../util/DocumentManager";
+import { action } from "mobx";
+import { ReactTableDefaults, RowInfo, TableCellRenderer } from "react-table";
+import { Doc } from "../../../fields/Doc";
import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { undoBatch } from "../../util/UndoManager";
+import { Cast, FieldValue, StrCast } from "../../../fields/Types";
+import { DocumentManager } from "../../util/DocumentManager";
+import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
import { SnappingManager } from "../../util/SnappingManager";
+import { Transform } from "../../util/Transform";
+import { undoBatch } from "../../util/UndoManager";
+import { ContextMenu } from "../ContextMenu";
+import "./CollectionSchemaView.scss";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
library.add(faGripVertical, faTrash);
@@ -226,13 +226,15 @@ export class MovableRow extends React.Component<MovableRowProps> {
render() {
const { children = null, rowInfo } = this.props;
+
if (!rowInfo) {
return <ReactTableDefaults.TrComponent>{children}</ReactTableDefaults.TrComponent>;
}
const { original } = rowInfo;
const doc = FieldValue(Cast(original, Doc));
- if (!doc) return <></>;
+
+ if (!doc) return (null);
const reference = React.createRef<HTMLDivElement>();
const onItemDown = SetupDrag(reference, () => doc, this.move, StrCast(this.props.dropAction) as dropActionType);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b6a0504e2..e5af1b0cc 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -720,14 +720,14 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
</div>;
} else {
- //subtracted 250 for offset
+ //subtracted for offset
var str: string = "";
for (var i = 0; i < this._pointsX.length; i++) {
var x = 0;
- x = this._pointsX[i] - 250;
+ x = this._pointsX[i] - 64;
str += x.toString();
str += ",";
- str += this._pointsY[i].toString();
+ str += (this._pointsY[i] - 85).toString();
str += (" ");
}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index cf8645e4c..70e7d8311 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -129,9 +129,15 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
LinkDescriptionPopup.popupY = e.screenY - 100;
LinkDescriptionPopup.descriptionPopup = true;
- LinkDescriptionPopup.popupX = e.screenX;
- LinkDescriptionPopup.popupY = e.screenY - 100;
- LinkDescriptionPopup.descriptionPopup = true;
+ const rect = document.body.getBoundingClientRect();
+ if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+ LinkDescriptionPopup.popupX -= 190;
+ TaskCompletionBox.popupX -= 40;
+ }
+ if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+ LinkDescriptionPopup.popupY -= 40;
+ TaskCompletionBox.popupY -= 40;
+ }
setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
}
@@ -176,6 +182,17 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
LinkDescriptionPopup.popupY = screenY - 100;
LinkDescriptionPopup.descriptionPopup = true;
}
+
+ const rect = document.body.getBoundingClientRect();
+ if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+ LinkDescriptionPopup.popupX -= 190;
+ TaskCompletionBox.popupX -= 40;
+ }
+ if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+ LinkDescriptionPopup.popupY -= 40;
+ TaskCompletionBox.popupY -= 40;
+ }
+
setTimeout(action(() => { TaskCompletionBox.taskCompleted = false; }), 2500);
}
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9ae113150..7cf6b0f39 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -617,6 +617,16 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
LinkDescriptionPopup.popupY = de.y;
LinkDescriptionPopup.descriptionPopup = true;
+ const rect = document.body.getBoundingClientRect();
+ if (LinkDescriptionPopup.popupX + 200 > rect.width) {
+ LinkDescriptionPopup.popupX -= 190;
+ TaskCompletionBox.popupX -= 40;
+ }
+ if (LinkDescriptionPopup.popupY + 100 > rect.height) {
+ LinkDescriptionPopup.popupY -= 40;
+ TaskCompletionBox.popupY -= 40;
+ }
+
setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
});
if (de.complete.annoDragData) {