aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2019-06-13 11:58:41 -0400
committerbob <bcz@cs.brown.edu>2019-06-13 11:58:41 -0400
commit5c8e4ee0c87b140f01f0d287af04fe205a80a584 (patch)
treedea35fe98ed404b762d8bbfcc7ba772225bda8f0 /src/client/views/nodes
parent95674ee7f68782d1ce85858120efea956825bcb9 (diff)
parente81e116b89fad0f3fcfb76039b0b802073307478 (diff)
Merge branch 'master' into rich_text_linking
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/DocumentView.tsx18
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx93
2 files changed, 44 insertions, 67 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 19f5c7d36..6fe01963a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -125,10 +125,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
constructor(props: DocumentViewProps) {
super(props);
- this.selectOnLoad = props.selectOnLoad;
}
-
_reactionDisposer?: IReactionDisposer;
@action
componentDidMount() {
@@ -271,7 +269,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (!linkedFwdDocs.some(l => l instanceof Promise)) {
let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 0].maximizeLocation, "inTab");
- DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0], linkedFwdContextDocs[altKey ? 1 : 0]);
+ let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
+ DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext);
}
}
}
@@ -317,13 +316,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
makeBtnClicked = (): void => {
let doc = Doc.GetProto(this.props.Document);
doc.isButton = !BoolCast(doc.isButton, false);
- if (StrCast(doc.layout).indexOf("Formatted") !== -1) { // only need to freeze the dimensions of text boxes since they don't have a native width and height naturally
- if (doc.isButton && !doc.nativeWidth) {
+ if (doc.isButton) {
+ if (!doc.nativeWidth) {
doc.nativeWidth = this.props.Document[WidthSym]();
doc.nativeHeight = this.props.Document[HeightSym]();
- } else {
- doc.nativeWidth = doc.nativeHeight = undefined;
}
+ } else {
+ doc.nativeWidth = doc.nativeHeight = undefined;
}
}
fullScreenClicked = (): void => {
@@ -442,14 +441,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; };
isSelected = () => SelectionManager.IsSelected(this);
- @action select = (ctrlPressed: boolean) => { this.selectOnLoad = false; SelectionManager.SelectDoc(this, ctrlPressed); }
+ @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }
- @observable selectOnLoad: boolean = false;
@computed get nativeWidth() { return this.Document.nativeWidth || 0; }
@computed get nativeHeight() { return this.Document.nativeHeight || 0; }
@computed get contents() {
return (
- <DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} selectOnLoad={this.selectOnLoad} layoutKey={"layout"} />);
+ <DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} selectOnLoad={this.props.selectOnLoad} layoutKey={"layout"} />);
}
render() {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 7dcacd19b..0a4a67211 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -5,51 +5,37 @@ import { observer } from "mobx-react";
import { baseKeymap } from "prosemirror-commands";
import { history } from "prosemirror-history";
import { keymap } from "prosemirror-keymap";
+import { NodeType } from 'prosemirror-model';
import { EditorState, Plugin, Transaction } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import { Doc, Opt } from "../../../new_fields/Doc";
+import { Id } from '../../../new_fields/FieldSymbols';
import { RichTextField } from "../../../new_fields/RichTextField";
import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
import { DocServer } from "../../DocServer";
-import { DocUtils, Docs } from '../../documents/Documents';
-import { DocumentManager } from "../../util/DocumentManager";
+import { Docs } from '../../documents/Documents';
import { DragManager } from "../../util/DragManager";
import buildKeymap from "../../util/ProsemirrorExampleTransfer";
import { inpRules } from "../../util/RichTextRules";
-import { ImageResizeView, schema } from "../../util/RichTextSchema";
+import { ImageResizeView, schema, SummarizedView } from "../../util/RichTextSchema";
import { SelectionManager } from "../../util/SelectionManager";
import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu";
import { TooltipTextMenu } from "../../util/TooltipTextMenu";
import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { ContextMenu } from "../../views/ContextMenu";
+import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from "../DocComponent";
import { InkingControl } from "../InkingControl";
import { FieldView, FieldViewProps } from "./FieldView";
import "./FormattedTextBox.scss";
import React = require("react");
-import { Id } from '../../../new_fields/FieldSymbols';
-import { MainOverlayTextBox } from '../MainOverlayTextBox';
-import { NodeType } from 'prosemirror-model';
library.add(faEdit);
library.add(faSmile);
// FormattedTextBox: Displays an editable plain text node that maps to a specified Key of a Document
//
-// HTML Markup: <FormattedTextBox Doc={Document's ID} FieldKey={Key's name}
-//
-// In Code, the node's HTML is specified in the document's parameterized structure as:
-// document.SetField(KeyStore.Layout, "<FormattedTextBox doc={doc} fieldKey={<KEYNAME>Key} />");
-// and the node's binding to the specified document KEYNAME as:
-// document.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.<KEYNAME>]));
-// The Jsx parser at run time will bind:
-// 'fieldKey' property to the Key stored in LayoutKeys
-// and 'doc' property to the document that is being rendered
-//
-// When rendered() by React, this extracts the TextController from the Document stored at the
-// specified Key and assigns it to an HTML input node. When changes are made to this node,
-// this will edit the document and assign the new value to that field.
-//]
export interface FormattedTextBoxProps {
isOverlay?: boolean;
@@ -74,11 +60,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
private _proseRef?: HTMLDivElement;
private _editorView: Opt<EditorView>;
private _toolTipTextMenu: TooltipTextMenu | undefined = undefined;
- private _lastState: any = undefined;
private _applyingChange: boolean = false;
private _linkClicked = "";
private _reactionDisposer: Opt<IReactionDisposer>;
- private _inputReactionDisposer: Opt<IReactionDisposer>;
private _proxyReactionDisposer: Opt<IReactionDisposer>;
private dropDisposer?: DragManager.DragDropDisposer;
public get CurrentDiv(): HTMLDivElement { return this._ref.current!; }
@@ -117,10 +101,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
}
-
dispatchTransaction = (tx: Transaction) => {
if (this._editorView) {
- const state = this._lastState = this._editorView.state.apply(tx);
+ const state = this._editorView.state.apply(tx);
this._editorView.updateState(state);
this._applyingChange = true;
Doc.SetOnPrototype(this.props.Document, this.props.fieldKey, new RichTextField(JSON.stringify(state.toJSON())));
@@ -181,18 +164,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
]
};
- if (this.props.isOverlay) {
- this._inputReactionDisposer = reaction(() => FormattedTextBox.InputBoxOverlay,
- () => {
- if (this._editorView) {
- this._editorView.destroy();
- }
- this.setupEditor(config, // bcz: not sure why, but the order of events is such that this.props.Document hasn't updated yet, so without forcing the editor to the MainOverlayTextBox, it will display the previously focused textbox
- MainOverlayTextBox.Instance.TextDoc ? MainOverlayTextBox.Instance.TextDoc : this.props.Document,
- MainOverlayTextBox.Instance.TextFieldKey ? MainOverlayTextBox.Instance.TextFieldKey : this.props.fieldKey);
- }
- );
- } else {
+ if (!this.props.isOverlay) {
this._proxyReactionDisposer = reaction(() => this.props.isSelected(),
() => {
if (this.props.isSelected()) {
@@ -202,13 +174,12 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
});
}
-
this._reactionDisposer = reaction(
() => {
const field = this.props.Document ? Cast(this.props.Document[this.props.fieldKey], RichTextField) : undefined;
- return field ? field.Data : undefined;
+ return field ? field.Data : `{"doc":{"type":"doc","content":[]},"selection":{"type":"text","anchor":0,"head":0}}`;
},
- field => field && this._editorView && !this._applyingChange &&
+ field => this._editorView && !this._applyingChange &&
this._editorView.updateState(EditorState.fromJSON(config, JSON.parse(field)))
);
this.setupEditor(config, this.props.Document, this.props.fieldKey);
@@ -226,7 +197,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
dispatchTransaction: this.dispatchTransaction,
nodeViews: {
- image(node, view, getPos) { return new ImageResizeView(node, view, getPos); }
+ image(node, view, getPos) { return new ImageResizeView(node, view, getPos); },
+ star(node, view, getPos) { return new SummarizedView(node, view, getPos); }
}
});
if (startup) {
@@ -236,9 +208,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
}
if (this.props.selectOnLoad) {
- console.log("Sel on load " + this.props.Document.title + " " + doc!.title);
- this.props.select(false);
- this._editorView!.focus();
+ if (!this.props.isOverlay) this.props.select(false);
+ else this._editorView!.focus();
}
}
@@ -249,9 +220,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
if (this._reactionDisposer) {
this._reactionDisposer();
}
- if (this._inputReactionDisposer) {
- this._inputReactionDisposer();
- }
if (this._proxyReactionDisposer) {
this._proxyReactionDisposer();
}
@@ -264,7 +232,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this._toolTipTextMenu.tooltip.style.opacity = "0";
}
}
- this._linkClicked = "";
+ let ctrlKey = e.ctrlKey;
if (e.button === 0 && ((!this.props.isSelected() && !e.ctrlKey) || (this.props.isSelected() && e.ctrlKey)) && !e.metaKey && e.target) {
let href = (e.target as any).href;
for (let parent = (e.target as any).parentNode; !href && parent; parent = parent.parentNode) {
@@ -281,6 +249,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
e.stopPropagation();
e.preventDefault();
}
+
}
if (e.button === 2 || (e.button === 0 && e.ctrlKey)) {
e.preventDefault();
@@ -290,14 +259,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
if (this._toolTipTextMenu && this._toolTipTextMenu.tooltip) {
this._toolTipTextMenu.tooltip.style.opacity = "1";
}
- let ctrlKey = e.ctrlKey;
- if (this._linkClicked) {
- DocServer.GetRefField(this._linkClicked).then(f => {
- (f instanceof Doc) && DocumentManager.Instance.jumpToDocument(f, ctrlKey, document => this.props.addDocTab(document, "inTab"));
- });
- e.stopPropagation();
- e.preventDefault();
- }
if (e.buttons === 1 && this.props.isSelected() && !e.altKey) {
e.stopPropagation();
}
@@ -375,6 +336,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
if (!this._undoTyping) {
this._undoTyping = UndoManager.StartBatch("undoTyping");
}
+ if (this.props.isOverlay && this.props.Document.autoHeight) {
+ let xf = this._ref.current!.getBoundingClientRect();
+ let scrBounds = this.props.ScreenToLocalTransform().transformBounds(0, 0, xf.width, xf.height);
+ let nh = NumCast(this.props.Document.nativeHeight, 0);
+ let dh = NumCast(this.props.Document.height, 0);
+ let sh = scrBounds.height;
+ this.props.Document.height = nh ? dh / nh * sh : sh;
+ this.props.Document.proto!.nativeHeight = nh ? sh : undefined;
+ }
}
@action
@@ -385,6 +355,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
onPointerLeave = (e: React.PointerEvent) => {
this._entered = false;
}
+
+ specificContextMenu = (e: React.MouseEvent): void => {
+ let subitems: ContextMenuProps[] = [];
+ subitems.push({
+ description: BoolCast(this.props.Document.autoHeight, false) ? "Manual Height" : "Auto Height",
+ event: action(() => this.props.Document.autoHeight = !BoolCast(this.props.Document.autoHeight, false)), icon: "expand-arrows-alt"
+ });
+ ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems });
+ }
render() {
let style = this.props.isOverlay ? "scroll" : "hidden";
let rounded = NumCast(this.props.Document.borderRounding) < 0 ? "-rounded" : "";
@@ -398,10 +377,10 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
color: this.props.color ? this.props.color : this.props.hideOnLeave ? "white" : "initial",
pointerEvents: interactive ? "all" : "none",
}}
- // onKeyDown={this.onKeyPress}
onKeyPress={this.onKeyPress}
onFocus={this.onFocused}
onClick={this.onClick}
+ onContextMenu={this.specificContextMenu}
onBlur={this.onBlur}
onPointerUp={this.onPointerUp}
onPointerDown={this.onPointerDown}