aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/cognitive_services/CognitiveServices.ts5
-rw-r--r--src/client/util/DragManager.ts2
-rw-r--r--src/client/views/ContextMenu.scss57
-rw-r--r--src/client/views/ContextMenu.tsx8
-rw-r--r--src/client/views/ContextMenuItem.tsx6
-rw-r--r--src/client/views/DocumentDecorations.tsx10
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx6
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx8
-rw-r--r--src/client/views/collections/CollectionView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx13
-rw-r--r--src/client/views/nodes/DocumentView.tsx34
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx6
-rw-r--r--src/client/views/nodes/IconBox.tsx10
-rw-r--r--src/client/views/nodes/ImageBox.tsx29
-rw-r--r--src/client/views/nodes/VideoBox.tsx6
-rw-r--r--src/client/views/search/SearchItem.tsx7
17 files changed, 144 insertions, 70 deletions
diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index d69378d0e..bbc438a9b 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -9,6 +9,7 @@ import { Utils } from "../../Utils";
import { CompileScript } from "../util/Scripting";
import { ComputedField } from "../../new_fields/ScriptField";
import { InkData } from "../../new_fields/InkField";
+import { undoBatch, UndoManager } from "../util/UndoManager";
type APIManager<D> = { converter: BodyConverter<D>, requester: RequestExecutor, analyzer: AnalysisApplier };
type RequestExecutor = (apiKey: string, body: string, service: Service) => Promise<string>;
@@ -103,6 +104,7 @@ export namespace CognitiveServices {
},
analyzer: async (target: Doc, keys: string[], service: Service, converter: Converter) => {
+ let batch = UndoManager.StartBatch("Image Analysis");
let imageData = Cast(target.data, ImageField);
let storageKey = keys[0];
if (!imageData || await Cast(target[storageKey], Doc)) {
@@ -120,6 +122,7 @@ export namespace CognitiveServices {
}
}
target[storageKey] = toStore;
+ batch.end();
}
};
@@ -205,6 +208,7 @@ export namespace CognitiveServices {
},
analyzer: async (target: Doc, keys: string[], inkData: InkData) => {
+ let batch = UndoManager.StartBatch("Ink Analysis");
let results = await executeQuery<InkData, any>(Service.Handwriting, Manager, inkData);
if (results) {
results.recognitionUnits && (results = results.recognitionUnits);
@@ -213,6 +217,7 @@ export namespace CognitiveServices {
let individualWords = recognizedText.filter((text: string) => text && text.split(" ").length === 1);
target[keys[1]] = individualWords.join(" ");
}
+ batch.end();
}
};
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 5271f2f5d..95416cd53 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -8,6 +8,7 @@ import * as globalCssVariables from "../views/globalCssVariables.scss";
import { DocumentManager } from "./DocumentManager";
import { LinkManager } from "./LinkManager";
import { SelectionManager } from "./SelectionManager";
+import { DocumentDecorations } from "../views/DocumentDecorations";
export type dropActionType = "alias" | "copy" | undefined;
export function SetupDrag(
@@ -421,6 +422,7 @@ export namespace DragManager {
if (options) {
options.handlers.dragComplete({});
}
+ DocumentDecorations.Instance.endLinkDragBatch();
};
AbortDrag = () => {
diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 254163b53..e2c0de8af 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -6,6 +6,10 @@
z-index: $contextMenu-zindex;
box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
flex-direction: column;
+ background: whitesmoke;
+ padding-bottom: 10px;
+ border-radius: 15px;
+ border: solid #BBBBBBBB 1px;
}
// .contextMenu-item:first-child {
@@ -28,12 +32,17 @@
z-index: 1000;
box-shadow: #AAAAAA .2vw .2vw .4vw;
flex-direction: column;
+ border: 1px solid #BBBBBBBB;
+ border-radius: 15px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ background: whitesmoke;
}
.contextMenu-item {
// width: 11vw; //10vw
height: 30px; //2vh
- background: #DDDDDD;
+ background: whitesmoke;
display: flex; //comment out to allow search icon to be inline with search text
justify-content: left;
align-items: center;
@@ -44,23 +53,33 @@
-ms-user-select: none;
user-select: none;
transition: all .1s;
+ border-style: none;
+ // padding: 10px 0px 10px 0px;
+ white-space: nowrap;
+ font-size: 13px;
+ color: grey;
+ letter-spacing: 2px;
+ text-transform: uppercase;
+ padding-right: 30px;
+}
+
+.contextMenu-item:hover {
border-width: .11px;
border-style: none;
border-color: $intermediate-color; // rgb(187, 186, 186);
border-bottom-style: solid;
- // padding: 10px 0px 10px 0px;
- white-space: nowrap;
- font-size: 20px;
+ border-top-style: solid;
}
.contextMenu-itemSelected {
- background: rgb(136, 136, 136)
+ background: lightgoldenrodyellow;
+ border-style: none;
}
.contextMenu-group {
// width: 11vw; //10vw
height: 30px; //2vh
- background: rgb(200, 200, 200);
+ background: lightgray;
display: flex; //comment out to allow search icon to be inline with search text
justify-content: left;
align-items: center;
@@ -74,27 +93,41 @@
border-width: .11px;
border-style: none;
border-color: $intermediate-color; // rgb(187, 186, 186);
- border-bottom-style: solid;
// padding: 10px 0px 10px 0px;
white-space: nowrap;
- font-size: 20px;
+ font-size: 13px;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ padding-left: 5px;
}
.contextMenu-item:hover {
- transition: all 0.1s;
+ transition: all 0.1s ease;
background: $lighter-alt-accent;
}
.contextMenu-description {
- font-size: 20px;
+ margin-left: 5px;
text-align: left;
display: inline; //need this?
}
+.search-icon {
+ margin: 10px;
+}
+
+.search {
+ margin-left: 10px;
+ padding-left: 10px;
+ border: solid black 1px;
+ border-radius: 5px;
+}
+
.icon-background {
pointer-events: none;
- background-color: #DDDDDD;
+ background-color: transparent;
width: 35px;
text-align: center;
- font-size: 22px;
+ font-size: 20px;
+ margin-left: 5px;
} \ No newline at end of file
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index c163c56a0..a608e448a 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -38,6 +38,10 @@ export class ContextMenu extends React.Component {
this._items = [];
}
+ findByDescription = (target: string) => {
+ return this._items.find(menuItem => menuItem.description === target);
+ }
+
@action
addItem(item: ContextMenuProps) {
if (this._items.indexOf(item) === -1) {
@@ -165,11 +169,11 @@ export class ContextMenu extends React.Component {
const contents = (
<>
- <span>
+ <span className={"search-icon"}>
<span className="icon-background">
<FontAwesomeIcon icon="search" size="lg" />
</span>
- <input className="contextMenu-item contextMenu-description" type="text" placeholder="Search . . ." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
+ <input className="contextMenu-item contextMenu-description search" type="text" placeholder="Search . . ." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
</span>
{this.menuItems}
</>
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 9bbb97d7e..badb9cf19 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -10,14 +10,14 @@ library.add(faAngleRight);
export interface OriginalMenuProps {
description: string;
event: () => void;
- icon?: IconProp; //maybe should be optional (icon?)
+ icon: IconProp; //maybe should be optional (icon?)
closeMenu?: () => void;
}
export interface SubmenuProps {
description: string;
subitems: ContextMenuProps[];
- icon?: IconProp; //maybe should be optional (icon?)
+ icon: IconProp; //maybe should be optional (icon?)
closeMenu?: () => void;
}
@@ -94,7 +94,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
) : null}
<div className="contextMenu-description">
{this.props.description}
- <FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "5px" }} />
+ <FontAwesomeIcon icon={faAngleRight} size="lg" style={{ position: "absolute", right: "10px"}} />
</div>
{submenu}
</div>
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c08a84742..751b64c35 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -54,6 +54,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
private _downY = 0;
private _iconDoc?: Doc = undefined;
private _resizeUndo?: UndoManager.Batch;
+ private _linkDrag?: UndoManager.Batch;
@observable private _minimizedX = 0;
@observable private _minimizedY = 0;
@observable private _title: string = "";
@@ -376,7 +377,16 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
}
}
+ endLinkDragBatch = () => {
+ if (!this._linkDrag) {
+ return;
+ }
+ this._linkDrag.end();
+ this._linkDrag = undefined;
+ }
+
onLinkerButtonDown = (e: React.PointerEvent): void => {
+ this._linkDrag = UndoManager.StartBatch("Drag Link");
e.stopPropagation();
document.removeEventListener("pointermove", this.onLinkerButtonMoved);
document.addEventListener("pointermove", this.onLinkerButtonMoved);
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8b7eb8856..52292abbb 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -389,7 +389,7 @@ export class MainView extends React.Component {
];
if (!ClientUtils.RELEASE) btns.unshift([React.createRef<HTMLDivElement>(), "cat", "Add Cat Image", addImageNode]);
- return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 5 }} >
+ return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} >
<input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
<label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Add Node"><p>+</p></label>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0f67c47aa..a57d3c81a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1,6 +1,6 @@
import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
+import { faCog, faPlus, faTable } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, trace, untracked } from "mobx";
import { observer } from "mobx-react";
@@ -34,7 +34,7 @@ import { ComputedField } from "../../../new_fields/ScriptField";
library.add(faCog);
-library.add(faPlus);
+library.add(faPlus, faTable);
// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -321,7 +321,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
onContextMenu = (e: React.MouseEvent): void => {
if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
- ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB });
+ ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB, icon: "table" });
}
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index a1697f9b4..1c7fe4bee 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,5 +1,5 @@
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
+import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faArrowsAltH, faCaretSquareDown, faCaretSquareRight, faTrashAlt, faPlus, faMinus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, trace, untracked } from "mobx";
import { observer } from "mobx-react";
@@ -61,7 +61,7 @@ library.add(faCaretRight);
library.add(faCaretSquareDown);
library.add(faCaretSquareRight);
library.add(faArrowsAltH);
-
+library.add(faPlus, faMinus);
@observer
/**
* Component that takes in a document prop and a boolean whether it's collapsed or not.
@@ -520,8 +520,8 @@ export class CollectionTreeView extends CollectionSubView(Document) {
onContextMenu = (e: React.MouseEvent): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
if (!e.isPropagationStopped() && this.props.Document.workspaceLibrary) { // excludeFromLibrary means this is the user document
- ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()) });
- ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)) });
+ ContextMenu.Instance.addItem({ description: "Create Workspace", event: undoBatch(() => MainView.Instance.createNewWorkspace()), icon: "plus" });
+ ContextMenu.Instance.addItem({ description: "Delete Workspace", event: undoBatch(() => this.remove(this.props.Document)), icon: "minus" });
e.stopPropagation();
e.preventDefault();
ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index cd137cd60..b4f29755c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -15,6 +15,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
import { CollectionSchemaView } from "./CollectionSchemaView";
import { CollectionStackingView } from './CollectionStackingView';
import { CollectionTreeView } from "./CollectionTreeView";
+import { faEye } from '@fortawesome/free-regular-svg-icons';
export const COLLECTION_BORDER_WIDTH = 2;
library.add(faTh);
@@ -26,7 +27,7 @@ library.add(faThList);
library.add(faFingerprint);
library.add(faColumns);
library.add(faEllipsisV);
-library.add(faImage);
+library.add(faImage, faEye);
@observer
export class CollectionView extends React.Component<FieldViewProps> {
@@ -66,7 +67,7 @@ export class CollectionView extends React.Component<FieldViewProps> {
break;
}
}
- ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems });
+ ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" });
ContextMenu.Instance.addItem({ description: "Apply Template", event: undoBatch(() => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight")), icon: "project-diagram" });
}
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index c5ed64314..d07fc7f80 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -13,7 +13,7 @@ import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
import { undoBatch, UndoManager } from "../../../util/UndoManager";
import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
-import { ContextMenu } from "../../ContextMenu";
+import { SubmenuProps, ContextMenuProps } from "../../ContextMenuItem";
import { InkingCanvas } from "../../InkingCanvas";
import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentContentsView } from "../../nodes/DocumentContentsView";
@@ -34,11 +34,12 @@ import { CompileScript } from "../../../util/Scripting";
import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
import { library } from "@fortawesome/fontawesome-svg-core";
import { faEye } from "@fortawesome/free-regular-svg-icons";
-import { faTable, faPaintBrush, faAsterisk, faExpandArrowsAlt, faCompressArrowsAlt } from "@fortawesome/free-solid-svg-icons";
+import { faTable, faPaintBrush, faAsterisk, faExpandArrowsAlt, faCompressArrowsAlt, faCompass } from "@fortawesome/free-solid-svg-icons";
import { undo } from "prosemirror-history";
import { number } from "prop-types";
+import { ContextMenu } from "../../ContextMenu";
-library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt);
+library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass);
export const panZoomSchema = createSchema({
panX: "number",
@@ -492,12 +493,13 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
onContextMenu = () => {
- ContextMenu.Instance.addItem({
+ let layoutItems: ContextMenuProps[] = [];
+ layoutItems.push({
description: `${this.fitToBox ? "Unset" : "Set"} Fit To Container`,
event: undoBatch(async () => this.props.Document.fitToBox = !this.fitToBox),
icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt"
});
- ContextMenu.Instance.addItem({
+ layoutItems.push({
description: "Arrange contents in grid",
icon: "table",
event: async () => {
@@ -524,6 +526,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}, "arrange contents");
}
});
+ ContextMenu.Instance.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
ContextMenu.Instance.addItem({
description: "Analyze Strokes", event: async () => {
let data = Cast(this.fieldExtensionDoc[this.inkKey], InkField);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8177916c5..ddb3ad44e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -39,6 +39,8 @@ import { OverlayView } from '../OverlayView';
import { ScriptingRepl } from '../ScriptingRepl';
import { ClientUtils } from '../../util/ClientUtils';
import { EditableView } from '../EditableView';
+import { faHandPointer, faHandPointRight } from '@fortawesome/free-regular-svg-icons';
+import { DocumentDecorations } from '../DocumentDecorations';
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
library.add(fa.faTrash);
@@ -60,8 +62,7 @@ library.add(fa.faCrosshairs);
library.add(fa.faDesktop);
library.add(fa.faUnlock);
library.add(fa.faLock);
-library.add(fa.faLaptopCode);
-
+library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCompass, fa.faSnowflake);
// const linkSchema = createSchema({
// title: "string",
@@ -551,12 +552,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" });
subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" });
cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" });
- cm.addItem({ description: !BoolCast(this.props.Document.ignoreAspect) && this.props.Document.nativeWidth && this.props.Document.nativeHeight ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" });
- cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
- cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Pos" : "Lock Pos", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
- cm.addItem({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
- cm.addItem({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" });
- cm.addItem({
+ cm.addItem({ description: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" });
+ cm.addItem({ description: "Pin to Presentation", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" });
+ cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
+ let makes: ContextMenuProps[] = [];
+ makes.push({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" });
+ makes.push({ description: this.props.Document.isButton ? "Remove Button" : "Make Button", event: this.makeBtnClicked, icon: "concierge-bell" });
+ makes.push({
description: "Make Portal", event: () => {
let portal = Docs.Create.FreeformDocument([], { width: this.props.Document[WidthSym]() + 10, height: this.props.Document[HeightSym](), title: this.props.Document.title + ".portal" });
//Doc.GetProto(this.props.Document).subBulletDocs = new List<Doc>([portal]);
@@ -570,6 +572,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}, icon: "window-restore"
});
+ cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" });
// cm.addItem({
// description: "Find aliases", event: async () => {
// const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
@@ -580,11 +583,16 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" });
}
cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) });
- cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
- cm.addItem({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" });
+ let existing = ContextMenu.Instance.findByDescription("Layout...");
+ let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
+ layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
+ layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" });
+ !existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
if (!ClientUtils.RELEASE) {
- cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
- cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
+ let copies: ContextMenuProps[] = [];
+ copies.push({ description: "Copy URL", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
+ copies.push({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
+ cm.addItem({ description: "Copy...", subitems: copies, icon: "copy" });
}
cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
type User = { email: string, userDocumentId: string };
@@ -608,7 +616,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
notifDoc.data = new List([sharedDoc]);
}
}
- }
+ }, icon: "male"
}));
} catch {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index bd0fd8301..c3d1c0e90 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,5 +1,5 @@
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faEdit, faSmile } from '@fortawesome/free-solid-svg-icons';
+import { faEdit, faSmile, faTextHeight } from '@fortawesome/free-solid-svg-icons';
import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace } from "mobx";
import { observer } from "mobx-react";
import { baseKeymap } from "prosemirror-commands";
@@ -38,7 +38,7 @@ import { thisExpression } from 'babel-types';
import { Utils } from '../../../Utils';
library.add(faEdit);
-library.add(faSmile);
+library.add(faSmile, faTextHeight);
// FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
//
@@ -462,7 +462,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
description: BoolCast(this.props.Document.autoHeight) ? "Manual Height" : "Auto Height",
event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight)), icon: "expand-arrows-alt"
});
- ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems });
+ ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems, icon: "text-height" });
}
render() {
let self = this;
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index 6f50033a4..7e78ec684 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -1,6 +1,6 @@
import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTag, faTextHeight } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
@@ -18,7 +18,7 @@ library.add(faCaretUp);
library.add(faObjectGroup);
library.add(faStickyNote);
library.add(faFilePdf);
-library.add(faFilm);
+library.add(faFilm, faTag, faTextHeight);
@observer
export class IconBox extends React.Component<FieldViewProps> {
@@ -47,13 +47,15 @@ export class IconBox extends React.Component<FieldViewProps> {
specificContextMenu = (): void => {
ContextMenu.Instance.addItem({
description: BoolCast(this.props.Document.hideLabel) ? "Show label with icon" : "Remove label from icon",
- event: this.setLabelField
+ event: this.setLabelField,
+ icon: "tag"
});
let maxDocs = DocListCast(this.props.Document.maximizedDocs);
if (maxDocs.length === 1 && !BoolCast(this.props.Document.hideLabel)) {
ContextMenu.Instance.addItem({
description: BoolCast(this.props.Document.useOwnTitle) ? "Use target title for label" : "Use own title label",
- event: this.setUseOwnTitleField
+ event: this.setUseOwnTitleField,
+ icon: "text-height"
});
}
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 2115024a1..29a76b0c8 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -202,6 +202,20 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
});
}
+ @undoBatch
+ rotate = action(() => {
+ let proto = Doc.GetProto(this.props.Document);
+ let nw = this.props.Document.nativeWidth;
+ let nh = this.props.Document.nativeHeight;
+ let w = this.props.Document.width;
+ let h = this.props.Document.height;
+ proto.rotation = (NumCast(this.props.Document.rotation) + 90) % 360;
+ proto.nativeWidth = nh;
+ proto.nativeHeight = nw;
+ this.props.Document.width = h;
+ this.props.Document.height = w;
+ });
+
specificContextMenu = (e: React.MouseEvent): void => {
let field = Cast(this.Document[this.props.fieldKey], ImageField);
if (field) {
@@ -209,20 +223,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
let funcs: ContextMenuProps[] = [];
funcs.push({ description: "Copy path", event: () => Utils.CopyText(url), icon: "expand-arrows-alt" });
funcs.push({ description: "Record 1sec audio", event: this.recordAudioAnnotation, icon: "expand-arrows-alt" });
- funcs.push({
- description: "Rotate", event: action(() => {
- let proto = Doc.GetProto(this.props.Document);
- let nw = this.props.Document.nativeWidth;
- let nh = this.props.Document.nativeHeight;
- let w = this.props.Document.width;
- let h = this.props.Document.height;
- proto.rotation = (NumCast(this.props.Document.rotation) + 90) % 360;
- proto.nativeWidth = nh;
- proto.nativeHeight = nw;
- this.props.Document.width = h;
- this.props.Document.height = w;
- }), icon: "expand-arrows-alt"
- });
+ funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" });
let modes: ContextMenuProps[] = [];
let dataDoc = Doc.GetProto(this.props.Document);
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 30ad75000..34cb47b20 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -19,10 +19,14 @@ import { positionSchema } from "./DocumentView";
import { FieldView, FieldViewProps } from './FieldView';
import { pageSchema } from "./ImageBox";
import "./VideoBox.scss";
+import { library } from "@fortawesome/fontawesome-svg-core";
+import { faVideo } from "@fortawesome/free-solid-svg-icons";
type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
const VideoDocument = makeInterface(positionSchema, pageSchema);
+library.add(faVideo);
+
@observer
export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoDocument) {
private _reactionDisposer?: IReactionDisposer;
@@ -179,7 +183,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
},
icon: "expand-arrows-alt"
});
- ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems });
+ ContextMenu.Instance.addItem({ description: "Video Funcs...", subitems: subitems, icon: "video" });
}
}
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 5c2ced2eb..562594210 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -1,6 +1,6 @@
import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote, faFingerprint } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
@@ -38,7 +38,7 @@ library.add(faFilm);
library.add(faMusic);
library.add(faLink);
library.add(faChartBar);
-library.add(faGlobeAsia);
+library.add(faGlobeAsia, faFingerprint);
@observer
export class SelectorContextMenu extends React.Component<SearchItemProps> {
@@ -223,7 +223,8 @@ export class SearchItem extends React.Component<SearchItemProps> {
ContextMenu.Instance.addItem({
description: "Copy ID", event: () => {
Utils.CopyText(this.props.doc[Id]);
- }
+ },
+ icon: "fingerprint"
});
ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
}