aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx1
-rw-r--r--src/client/views/nodes/DocumentView.tsx73
-rw-r--r--src/client/views/nodes/FormattedTextBox.scss2
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx100
-rw-r--r--src/client/views/nodes/ImageBox.tsx14
-rw-r--r--src/client/views/nodes/LinkEditor.tsx2
-rw-r--r--src/client/views/nodes/LinkMenuGroup.tsx2
-rw-r--r--src/client/views/nodes/VideoBox.tsx10
8 files changed, 149 insertions, 55 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7ffd760e0..3b6c443c2 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -77,6 +77,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
transformOrigin: "left top",
position: "absolute",
backgroundColor: "transparent",
+ boxShadow: this.props.Document.z ? `#9c9396 ${StrCast(this.props.Document.boxShadow, "10px 10px 0.9vw")}` : undefined,
borderRadius: this.borderRounding(),
transform: this.transform,
transition: hasPosition ? "transform 1s" : StrCast(this.props.Document.transition),
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 2dc2c18a3..c5cf2e23a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,19 +1,24 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import * as fa from '@fortawesome/free-solid-svg-icons';
-import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc";
+import * as rp from "request-promise";
+import { Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
+import { Copy, Id } from '../../../new_fields/FieldSymbols';
import { List } from "../../../new_fields/List";
import { ObjectField } from "../../../new_fields/ObjectField";
-import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
-import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types";
+import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema";
+import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
-import { emptyFunction, Utils, returnFalse, returnTrue } from "../../../Utils";
+import { RouteStore } from '../../../server/RouteStore';
+import { emptyFunction, returnTrue, Utils } from "../../../Utils";
import { DocServer } from "../../DocServer";
-import { Docs, DocUtils, DocumentType } from "../../documents/Documents";
+import { Docs, DocUtils } from "../../documents/Documents";
+import { ClientUtils } from '../../util/ClientUtils';
+import DictationManager from '../../util/DictationManager';
import { DocumentManager } from "../../util/DocumentManager";
import { DragManager, dropActionType } from "../../util/DragManager";
-import { SearchUtil } from "../../util/SearchUtil";
+import { LinkManager } from '../../util/LinkManager';
import { SelectionManager } from "../../util/SelectionManager";
import { Transform } from "../../util/Transform";
import { undoBatch, UndoManager } from "../../util/UndoManager";
@@ -22,29 +27,22 @@ import { CollectionPDFView } from "../collections/CollectionPDFView";
import { CollectionVideoView } from "../collections/CollectionVideoView";
import { CollectionView } from "../collections/CollectionView";
import { ContextMenu } from "../ContextMenu";
+import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from "../DocComponent";
+import { EditableView } from '../EditableView';
+import { OverlayView } from '../OverlayView';
import { PresentationView } from "../presentationview/PresentationView";
-import { Template, Templates } from "./../Templates";
+import { ScriptingRepl } from '../ScriptingRepl';
+import { Template } from "./../Templates";
import { DocumentContentsView } from "./DocumentContentsView";
-import * as rp from "request-promise";
import "./DocumentView.scss";
-import React = require("react");
-import { Id, Copy } from '../../../new_fields/FieldSymbols';
-import { ContextMenuProps } from '../ContextMenuItem';
-import { list, object, createSimpleSchema } from 'serializr';
-import { LinkManager } from '../../util/LinkManager';
-import { RouteStore } from '../../../server/RouteStore';
import { FormattedTextBox } from './FormattedTextBox';
-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';
+import React = require("react");
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
library.add(fa.faTrash);
library.add(fa.faShare);
+library.add(fa.faDownload);
library.add(fa.faExpandArrowsAlt);
library.add(fa.faCompressArrowsAlt);
library.add(fa.faLayerGroup);
@@ -62,7 +60,7 @@ library.add(fa.faCrosshairs);
library.add(fa.faDesktop);
library.add(fa.faUnlock);
library.add(fa.faLock);
-library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCompass, fa.faSnowflake);
+library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone);
// const linkSchema = createSchema({
// title: "string",
@@ -93,7 +91,7 @@ export interface DocumentViewProps {
selectOnLoad: boolean;
parentActive: () => boolean;
whenActiveChanged: (isActive: boolean) => void;
- bringToFront: (doc: Doc) => void;
+ bringToFront: (doc: Doc, sendToBack?: boolean) => void;
addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void;
zoomToScale: (scale: number) => void;
@@ -118,6 +116,7 @@ export const positionSchema = createSchema({
height: "number",
x: "number",
y: "number",
+ z: "number",
});
export type PositionDocument = makeInterface<[typeof positionSchema]>;
@@ -526,7 +525,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
@action
makeBackground = (): void => {
- this.props.Document.isBackground = true;
+ this.props.Document.isBackground = !this.props.Document.isBackground;
+ this.props.Document.isBackground && this.props.bringToFront(this.props.Document, true);
}
@undoBatch
@@ -535,6 +535,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this.props.Document.lockedPosition = BoolCast(this.props.Document.lockedPosition) ? undefined : true;
}
+ listen = async () => {
+ let transcript = await DictationManager.Instance.listen();
+ transcript && (Doc.GetProto(this.props.Document).transcript = transcript);
+ }
+
@action
onContextMenu = async (e: React.MouseEvent): Promise<void> => {
e.persist();
@@ -558,8 +563,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
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" });
+ cm.addItem({ description: "Transcribe Speech", event: this.listen, icon: "microphone" });
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.isBackground ? "Remove Background" : "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: () => {
@@ -576,12 +582,6 @@ 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);
- // this.props.addDocTab && this.props.addDocTab(Docs.Create.SchemaDocument(["title"], aliases, {}), undefined, "onRight"); // bcz: dataDoc?
- // }, icon: "search"
- // });
if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) {
cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" });
}
@@ -597,6 +597,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
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: "Download document", icon: "download", event: () => {
+ const a = document.createElement("a");
+ const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
+ a.href = url;
+ a.download = `DocExport-${this.props.Document[Id]}.zip`;
+ a.click();
+ }
+ });
cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
type User = { email: string, userDocumentId: string };
let usersMenu: ContextMenuProps[] = [];
@@ -690,7 +699,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
<div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
ref={this._mainCont}
style={{
- pointerEvents: this.layoutDoc.isBackground ? "none" : "all",
+ pointerEvents: this.layoutDoc.isBackground && !this.isSelected() ? "none" : "all",
color: foregroundColor,
outlineColor: "maroon",
outlineStyle: "dashed",
diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss
index a24abb32e..247f7d1ea 100644
--- a/src/client/views/nodes/FormattedTextBox.scss
+++ b/src/client/views/nodes/FormattedTextBox.scss
@@ -43,7 +43,7 @@
.formattedTextBox-inner-rounded div,
.formattedTextBox-inner div {
- padding: 10px;
+ padding: 10px 10px;
}
.menuicon {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index fc0cc98aa..e076efe18 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1,10 +1,11 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import { faEdit, faSmile, faTextHeight } from '@fortawesome/free-solid-svg-icons';
-import { action, IReactionDisposer, observable, reaction, runInAction, computed, trace } from "mobx";
+import { action, IReactionDisposer, observable, reaction, runInAction, computed, Lambda, trace } from "mobx";
import { observer } from "mobx-react";
import { baseKeymap } from "prosemirror-commands";
import { history } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
+import { Node as ProsNode } from "prosemirror-model";
import { EditorState, Plugin, Transaction, Selection } from "prosemirror-state";
import { NodeType, Slice, Node, Fragment } from 'prosemirror-model';
import { EditorView } from "prosemirror-view";
@@ -33,6 +34,7 @@ import { Templates } from '../Templates';
import { FieldView, FieldViewProps } from "./FieldView";
import "./FormattedTextBox.scss";
import React = require("react");
+import { For } from 'babel-types';
import { DateField } from '../../../new_fields/DateField';
import { Utils } from '../../../Utils';
import { MainOverlayTextBox } from '../MainOverlayTextBox';
@@ -49,6 +51,7 @@ export interface FormattedTextBoxProps {
height?: string;
color?: string;
outer_div?: (domminus: HTMLElement) => void;
+ firstinstance?: boolean;
}
const richTextSchema = createSchema({
@@ -63,14 +66,16 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
public static LayoutString(fieldStr: string = "data") {
return FieldView.LayoutString(FormattedTextBox, fieldStr);
}
+ public static Instance: FormattedTextBox;
private _ref: React.RefObject<HTMLDivElement>;
private _outerdiv?: (dominus: HTMLElement) => void;
private _proseRef?: HTMLDivElement;
private _editorView: Opt<EditorView>;
- private _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
+ private static _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
private _applyingChange: boolean = false;
private _linkClicked = "";
private _reactionDisposer: Opt<IReactionDisposer>;
+ private _searchReactionDisposer?: Lambda;
private _textReactionDisposer: Opt<IReactionDisposer>;
private _proxyReactionDisposer: Opt<IReactionDisposer>;
private dropDisposer?: DragManager.DragDropDisposer;
@@ -100,6 +105,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
return "";
}
+ public static getToolTip() {
+ return this._toolTipTextMenu;
+ }
+
@undoBatch
public setFontColor(color: string) {
let self = this;
@@ -115,6 +124,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
constructor(props: FieldViewProps) {
super(props);
+ //if (this.props.firstinstance) {
+ FormattedTextBox.Instance = this;
+ //}
if (this.props.outer_div) {
this._outerdiv = this.props.outer_div;
}
@@ -129,7 +141,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
@computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "dummy"); }
- @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
+ @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
+
paste = (e: ClipboardEvent) => {
if (e.clipboardData && this._editorView) {
@@ -145,7 +158,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
// tx.setSelection(new Selection(tx.))
const state = this._editorView!.state;
this._editorView!.dispatch(tx);
- if (this._toolTipTextMenu) {
+ if (FormattedTextBox._toolTipTextMenu) {
// this._toolTipTextMenu.makeLinkWithState(state)
}
e.stopPropagation();
@@ -161,7 +174,20 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
if (this._editorView) {
const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
+ if (state.selection.empty && FormattedTextBox._toolTipTextMenu) {
+ const marks = tx.storedMarks;
+ if (marks) { FormattedTextBox._toolTipTextMenu.mark_key_pressed(marks); }
+ }
this._applyingChange = true;
+ const fieldkey = "preview";
+ if (Object.keys(this.dataDoc).indexOf(fieldkey) !== -1) {
+ this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()));
+ this.dataDoc[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n");
+ }
+ else {
+ Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()));
+ Doc.GetProto(this.dataDoc)[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n");
+ }
if (this.extensionDoc) this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n");
if (this.extensionDoc) this.extensionDoc.lastModified = new DateField(new Date(Date.now()));
this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()));
@@ -175,6 +201,50 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
+ public highlightSearchTerms = (terms: String[]) => {
+ if (this._editorView && (this._editorView as any).docView) {
+ const fieldkey = "preview";
+ const doc = this._editorView.state.doc;
+ const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight);
+ doc.nodesBetween(0, doc.content.size, (node: ProsNode, pos: number, parent: ProsNode, index: number) => {
+ if (node.isLeaf && node.isText && node.text) {
+ let nodeText: String = node.text;
+ let tokens = nodeText.split(" ");
+ let start = pos;
+ tokens.forEach((word) => {
+ if (terms.includes(word) && this._editorView) {
+ this._editorView.dispatch(this._editorView.state.tr.addMark(start, start + word.length, mark).removeStoredMark(mark));
+ // else {
+ // this._editorView.state.tr.addMark(start, start + word.length, mark).removeStoredMark(mark);
+ // }
+ }
+ start += word.length + 1;
+ });
+ }
+ });
+ }
+ }
+
+ public unhighlightSearchTerms = () => {
+ if (this._editorView && (this._editorView as any).docView) {
+ const doc = this._editorView.state.doc;
+ const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight);
+ doc.nodesBetween(0, doc.content.size, (node: ProsNode, pos: number, parent: ProsNode, index: number) => {
+ if (node.isLeaf && node.isText && node.text) {
+ if (node.marks.includes(mark) && this._editorView) {
+ this._editorView.dispatch(this._editorView.state.tr.removeMark(pos, pos + node.nodeSize, mark));
+ }
+ }
+ });
+ // const fieldkey = 'search_string';
+ // if (Object.keys(this.props.Document).indexOf(fieldkey) !== -1) {
+ // this.props.Document[fieldkey] = undefined;
+ // }
+ // else this.props.Document.proto![fieldkey] = undefined;
+ // }
+ }
+ }
+
protected createDropTarget = (ele: HTMLDivElement) => {
this._proseRef = ele;
if (this.dropDisposer) {
@@ -277,6 +347,22 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}, { fireImmediately: true });
this.setupEditor(config, this.dataDoc, this.props.fieldKey);
+
+ this._searchReactionDisposer = reaction(() => {
+ return StrCast(this.props.Document.search_string);
+ }, searchString => {
+ const fieldkey = 'preview';
+ let preview = false;
+ // if (!this._editorView && Object.keys(this.props.Document).indexOf(fieldkey) !== -1) {
+ // preview = true;
+ // }
+ if (searchString) {
+ this.highlightSearchTerms([searchString]);
+ }
+ else {
+ this.unhighlightSearchTerms();
+ }
+ }, { fireImmediately: true });
}
clipboardTextSerializer = (slice: Slice): string => {
@@ -411,7 +497,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 0 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
e.stopPropagation();
- if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) {
+ if (FormattedTextBox._toolTipTextMenu && FormattedTextBox._toolTipTextMenu.tooltip) {
//this._toolTipTextMenu.tooltip.style.opacity = "0";
}
}
@@ -467,7 +553,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
onPointerUp = (e: React.PointerEvent): void => {
- if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) {
+ if (FormattedTextBox._toolTipTextMenu && FormattedTextBox._toolTipTextMenu.tooltip) {
//this._toolTipTextMenu.tooltip.style.opacity = "1";
}
if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
@@ -508,7 +594,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
tooltipTextMenuPlugin() {
let myprops = this.props;
- let self = this;
+ let self = FormattedTextBox;
return new Plugin({
view(_editorView) {
return self._toolTipTextMenu = new TooltipTextMenu(_editorView, myprops);
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index dbe545048..9a0615d68 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -68,7 +68,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
private dropDisposer?: DragManager.DragDropDisposer;
- @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; }
+ @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : this.props.Document; }
protected createDropTarget = (ele: HTMLDivElement) => {
@@ -93,17 +93,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
if (de.data instanceof DragManager.DocumentDragData) {
de.data.droppedDocuments.forEach(action((drop: Doc) => {
if (de.mods === "CtrlKey") {
- let temp = Doc.MakeDelegate(drop);
- this.props.Document.nativeWidth = Doc.GetProto(this.props.Document).nativeWidth = undefined;
- this.props.Document.nativeHeight = Doc.GetProto(this.props.Document).nativeHeight = undefined;
- this.props.Document.width = drop.width;
- this.props.Document.height = drop.height;
- Doc.GetProto(this.props.Document).type = DocumentType.TEMPLATE;
- if (this.props.DataDoc && this.props.DataDoc.layout === this.props.Document) {
- this.props.DataDoc.layout = temp;
- } else {
- this.props.Document.layout = temp;
- }
+ Doc.ApplyTemplateTo(drop, this.props.Document, this.props.DataDoc);
e.stopPropagation();
} else if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) {
Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url);
diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
index 0ea948c81..ecb3e9db4 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -290,7 +290,7 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
let index = keys.indexOf("");
if (index > -1) keys.splice(index, 1);
- let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c));
+ let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
let ref = React.createRef<HTMLDivElement>();
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx
index 0cb216aa6..e04044266 100644
--- a/src/client/views/nodes/LinkMenuGroup.tsx
+++ b/src/client/views/nodes/LinkMenuGroup.tsx
@@ -72,7 +72,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
let index = keys.indexOf("");
if (index > -1) keys.splice(index, 1);
- let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c));
+ let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
let createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { width: 500, height: 300, title: groupType + " table" }));
let ref = React.createRef<HTMLDivElement>();
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 1f8636826..704030d85 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -23,6 +23,7 @@ import { faVideo } from "@fortawesome/free-solid-svg-icons";
import { CompileScript } from "../../util/Scripting";
import { Doc } from "../../../new_fields/Doc";
import { ScriptField } from "../../../new_fields/ScriptField";
+var path = require('path');
type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
const VideoDocument = makeInterface(positionSchema, pageSchema);
@@ -89,6 +90,13 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
this._youtubePlayer && this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab");
}
+ choosePath(url: string) {
+ if (url.indexOf(window.location.origin) === -1) {
+ return Utils.CorsProxy(url);
+ }
+ return url;
+ }
+
@action public Snapshot() {
let width = NumCast(this.props.Document.width);
let height = NumCast(this.props.Document.height);
@@ -127,7 +135,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
let filename = encodeURIComponent("snapshot" + this.props.Document.title + "_" + this.props.Document.curPage).replace(/\./g, "");
VideoBox.convertDataUri(dataUrl, filename).then(returnedFilename => {
if (returnedFilename) {
- let url = Utils.prepend(returnedFilename);
+ let url = this.choosePath(Utils.prepend(returnedFilename));
let imageSummary = Docs.Create.ImageDocument(url, {
x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"