aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DocumentView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DocumentView.tsx')
-rw-r--r--src/client/views/nodes/DocumentView.tsx379
1 files changed, 270 insertions, 109 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index fec451b09..b9329f269 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,11 +1,13 @@
import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../fields/Document";
-import { Field, Opt, FieldWaiting } from "../../../fields/Field";
+import { Field, FieldWaiting, Opt } from "../../../fields/Field";
import { Key } from "../../../fields/Key";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
+import { BooleanField } from "../../../fields/BooleanField";
import { TextField } from "../../../fields/TextField";
+import { ServerUtils } from "../../../server/ServerUtil";
import { Utils } from "../../../Utils";
import { Documents } from "../../documents/Documents";
import { DocumentManager } from "../../util/DocumentManager";
@@ -19,11 +21,10 @@ import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
import React = require("react");
-
export interface DocumentViewProps {
ContainingCollectionView: Opt<CollectionView>;
Document: Document;
- AddDocument?: (doc: Document, allowDuplicates: boolean) => void;
+ AddDocument?: (doc: Document, allowDuplicates: boolean) => boolean;
RemoveDocument?: (doc: Document) => boolean;
ScreenToLocalTransform: () => Transform;
isTopMost: boolean;
@@ -34,8 +35,8 @@ export interface DocumentViewProps {
SelectOnLoad: boolean;
}
export interface JsxArgs extends DocumentViewProps {
- Keys: { [name: string]: Key }
- Fields: { [name: string]: Field }
+ Keys: { [name: string]: Key };
+ Fields: { [name: string]: Field };
}
/*
@@ -54,16 +55,16 @@ Example usage of this function:
}
*/
export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs {
- let Keys: { [name: string]: any } = {}
- let Fields: { [name: string]: any } = {}
+ let Keys: { [name: string]: any } = {};
+ let Fields: { [name: string]: any } = {};
for (const key of keys) {
- let fn = () => { }
- Object.defineProperty(fn, "name", { value: key + "Key" })
+ let fn = () => { };
+ Object.defineProperty(fn, "name", { value: key + "Key" });
Keys[key] = fn;
}
for (const field of fields) {
- let fn = () => { }
- Object.defineProperty(fn, "name", { value: field })
+ let fn = () => { };
+ Object.defineProperty(fn, "name", { value: field });
Fields[field] = fn;
}
let args: JsxArgs = {
@@ -84,58 +85,94 @@ export interface JsxBindings {
[prop: string]: any;
}
-
-
@observer
export class DocumentView extends React.Component<DocumentViewProps> {
private _mainCont = React.createRef<HTMLDivElement>();
private _downX: number = 0;
private _downY: number = 0;
+
private _reactionDisposer: Opt<IReactionDisposer>;
- @computed get active(): boolean { return SelectionManager.IsSelected(this) || !this.props.ContainingCollectionView || this.props.ContainingCollectionView.active(); }
- @computed get topMost(): boolean { return !this.props.ContainingCollectionView || this.props.ContainingCollectionView.collectionViewType == CollectionViewType.Docking; }
- @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); }
- @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>()); }
- @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>()); }
- screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect();
+ @computed get active(): boolean {
+ return (
+ SelectionManager.IsSelected(this) ||
+ !this.props.ContainingCollectionView ||
+ this.props.ContainingCollectionView.active()
+ );
+ }
+ @computed get topMost(): boolean {
+ return (
+ !this.props.ContainingCollectionView ||
+ this.props.ContainingCollectionView.collectionViewType ==
+ CollectionViewType.Docking
+ );
+ }
+ @computed get layout(): string {
+ return this.props.Document.GetText(
+ KeyStore.Layout,
+ "<p>Error loading layout data</p>"
+ );
+ }
+ @computed get layoutKeys(): Key[] {
+ return this.props.Document.GetData(
+ KeyStore.LayoutKeys,
+ ListField,
+ new Array<Key>()
+ );
+ }
+ @computed get layoutFields(): Key[] {
+ return this.props.Document.GetData(
+ KeyStore.LayoutFields,
+ ListField,
+ new Array<Key>()
+ );
+ }
+ screenRect = (): ClientRect | DOMRect =>
+ this._mainCont.current
+ ? this._mainCont.current.getBoundingClientRect()
+ : new DOMRect();
onPointerDown = (e: React.PointerEvent): void => {
this._downX = e.clientX;
this._downY = e.clientY;
if (e.shiftKey && e.buttons === 2) {
if (this.props.isTopMost) {
this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey);
- }
- else CollectionDockingView.Instance.StartOtherDrag(this.props.Document, e);
+ } else
+ CollectionDockingView.Instance.StartOtherDrag([this.props.Document], e);
e.stopPropagation();
} else {
if (this.active && !e.isDefaultPrevented()) {
e.stopPropagation();
- document.removeEventListener("pointermove", this.onPointerMove)
+ document.removeEventListener("pointermove", this.onPointerMove);
document.addEventListener("pointermove", this.onPointerMove);
- document.removeEventListener("pointerup", this.onPointerUp)
+ document.removeEventListener("pointerup", this.onPointerUp);
document.addEventListener("pointerup", this.onPointerUp);
}
}
- }
+ };
private dropDisposer?: DragManager.DragDropDisposer;
- protected createDropTarget = (ele: HTMLDivElement) => {
-
- }
componentDidMount() {
if (this._mainCont.current) {
- this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } });
+ this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, {
+ handlers: { drop: this.drop.bind(this) }
+ });
}
- runInAction(() => {
- DocumentManager.Instance.DocumentViews.push(this);
- })
+ runInAction(() => DocumentManager.Instance.DocumentViews.push(this));
this._reactionDisposer = reaction(
- () => this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.slice(),
+ () =>
+ this.props.ContainingCollectionView &&
+ this.props.ContainingCollectionView.SelectedDocs.slice(),
() => {
- if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.SelectedDocs.indexOf(this.props.Document.Id) != -1)
+ if (
+ this.props.ContainingCollectionView &&
+ this.props.ContainingCollectionView.SelectedDocs.indexOf(
+ this.props.Document.Id
+ ) != -1
+ )
SelectionManager.SelectDoc(this, true);
- });
+ }
+ );
}
componentDidUpdate() {
@@ -143,7 +180,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
this.dropDisposer();
}
if (this._mainCont.current) {
- this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } });
+ this.dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, {
+ handlers: { drop: this.drop.bind(this) }
+ });
}
}
@@ -151,10 +190,12 @@ export class DocumentView extends React.Component<DocumentViewProps> {
if (this.dropDisposer) {
this.dropDisposer();
}
- runInAction(() => {
- DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
-
- })
+ runInAction(() =>
+ DocumentManager.Instance.DocumentViews.splice(
+ DocumentManager.Instance.DocumentViews.indexOf(this),
+ 1
+ )
+ );
if (this._reactionDisposer) {
this._reactionDisposer();
}
@@ -162,22 +203,28 @@ export class DocumentView extends React.Component<DocumentViewProps> {
startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
if (this._mainCont.current) {
- const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
- let dragData = new DragManager.DocumentDragData(this.props.Document);
+ const [left, top] = this.props
+ .ScreenToLocalTransform()
+ .inverse()
+ .transformPoint(0, 0);
+ let dragData = new DragManager.DocumentDragData([this.props.Document]);
dragData.aliasOnDrop = dropAliasOfDraggedDoc;
dragData.xOffset = x - left;
dragData.yOffset = y - top;
dragData.removeDocument = (dropCollectionView: CollectionView) => {
- if (this.props.RemoveDocument && this.props.ContainingCollectionView !== dropCollectionView) {
+ if (
+ this.props.RemoveDocument &&
+ this.props.ContainingCollectionView !== dropCollectionView
+ ) {
this.props.RemoveDocument(this.props.Document);
}
- }
- DragManager.StartDocumentDrag(this._mainCont.current, dragData, {
+ };
+ DragManager.StartDocumentDrag([this._mainCont.current], dragData, {
handlers: {
- dragComplete: action(() => { }),
+ dragComplete: action(() => { })
},
hideSource: !dropAliasOfDraggedDoc
- })
+ });
}
}
@@ -185,8 +232,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
if (e.cancelBubble) {
return;
}
- if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
- document.removeEventListener("pointermove", this.onPointerMove)
+ if (
+ Math.abs(this._downX - e.clientX) > 3 ||
+ Math.abs(this._downY - e.clientY) > 3
+ ) {
+ document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
if (!this.topMost || e.buttons == 2 || e.altKey) {
this.startDragging(e.x, e.y, e.ctrlKey || e.altKey);
@@ -194,43 +244,65 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
e.stopPropagation();
e.preventDefault();
- }
+ };
onPointerUp = (e: PointerEvent): void => {
- document.removeEventListener("pointermove", this.onPointerMove)
- document.removeEventListener("pointerup", this.onPointerUp)
+ document.removeEventListener("pointermove", this.onPointerMove);
+ document.removeEventListener("pointerup", this.onPointerUp);
e.stopPropagation();
- if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientY - this._downY) < 4) {
+ if (!SelectionManager.IsSelected(this) &&
+ Math.abs(e.clientX - this._downX) < 4 &&
+ Math.abs(e.clientY - this._downY) < 4
+ ) {
SelectionManager.SelectDoc(this, e.ctrlKey);
}
- }
+ };
stopPropogation = (e: React.SyntheticEvent) => {
e.stopPropagation();
- }
+ };
deleteClicked = (): void => {
if (this.props.RemoveDocument) {
this.props.RemoveDocument(this.props.Document);
}
- }
+ };
fieldsClicked = (e: React.MouseEvent): void => {
if (this.props.AddDocument) {
- this.props.AddDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false);
+ this.props.AddDocument(
+ Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }),
+ false
+ );
}
- }
+ };
fullScreenClicked = (e: React.MouseEvent): void => {
CollectionDockingView.Instance.OpenFullScreen(this.props.Document);
ContextMenu.Instance.clearItems();
- ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked });
- ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
- }
+ ContextMenu.Instance.addItem({
+ description: "Close Full Screen",
+ event: this.closeFullScreenClicked
+ });
+ ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
+ };
closeFullScreenClicked = (e: React.MouseEvent): void => {
CollectionDockingView.Instance.CloseFullScreen();
ContextMenu.Instance.clearItems();
- ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
- ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
- }
+ ContextMenu.Instance.addItem({
+ description: "Full Screen",
+ event: this.fullScreenClicked
+ });
+ ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
+ };
+
+ @action
+ public minimize = (): void => {
+ this.props.Document.SetData(
+ KeyStore.Minimized,
+ true as boolean,
+ BooleanField
+ );
+ SelectionManager.DeselectAll();
+ };
@action
drop = (e: Event, de: DragManager.DropEvent) => {
@@ -242,18 +314,37 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
let linkDoc: Document = new Document();
- linkDoc.Set(KeyStore.Title, new TextField("New Link"));
- linkDoc.Set(KeyStore.LinkDescription, new TextField(""));
- linkDoc.Set(KeyStore.LinkTags, new TextField("Default"));
-
- sourceDoc.GetOrCreateAsync(KeyStore.LinkedToDocs, ListField, field => { (field as ListField<Document>).Data.push(linkDoc) });
- linkDoc.Set(KeyStore.LinkedToDocs, destDoc);
- destDoc.GetOrCreateAsync(KeyStore.LinkedFromDocs, ListField, field => { (field as ListField<Document>).Data.push(linkDoc) });
- linkDoc.Set(KeyStore.LinkedFromDocs, sourceDoc);
+ destDoc.GetTAsync(KeyStore.Prototype, Document).then(protoDest =>
+ sourceDoc.GetTAsync(KeyStore.Prototype, Document).then(protoSrc =>
+ runInAction(() => {
+ linkDoc.Set(KeyStore.Title, new TextField("New Link"));
+ linkDoc.Set(KeyStore.LinkDescription, new TextField(""));
+ linkDoc.Set(KeyStore.LinkTags, new TextField("Default"));
+ let dstTarg = protoDest ? protoDest : destDoc;
+ let srcTarg = protoSrc ? protoSrc : sourceDoc;
+ linkDoc.Set(KeyStore.LinkedToDocs, dstTarg);
+ linkDoc.Set(KeyStore.LinkedFromDocs, srcTarg);
+ dstTarg.GetOrCreateAsync(
+ KeyStore.LinkedFromDocs,
+ ListField,
+ field => {
+ (field as ListField<Document>).Data.push(linkDoc);
+ }
+ );
+ srcTarg.GetOrCreateAsync(
+ KeyStore.LinkedToDocs,
+ ListField,
+ field => {
+ (field as ListField<Document>).Data.push(linkDoc);
+ }
+ );
+ })
+ )
+ );
e.stopPropagation();
}
- }
+ };
onDrop = (e: React.DragEvent) => {
if (e.isDefaultPrevented()) {
@@ -267,22 +358,49 @@ export class DocumentView extends React.Component<DocumentViewProps> {
e.stopPropagation();
e.preventDefault();
}
- }
+ };
@action
onContextMenu = (e: React.MouseEvent): void => {
e.stopPropagation();
- let moved = Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3;
+ let moved =
+ Math.abs(this._downX - e.clientX) > 3 ||
+ Math.abs(this._downY - e.clientY) > 3;
if (moved || e.isDefaultPrevented()) {
- e.preventDefault()
+ e.preventDefault();
return;
}
- e.preventDefault()
+ e.preventDefault();
- ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
- ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked })
- ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) })
- ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) })
+ if (!this.isMinimized()) {
+ ContextMenu.Instance.addItem({
+ description: "Minimize",
+ event: this.minimize
+ });
+ }
+ ContextMenu.Instance.addItem({
+ description: "Full Screen",
+ event: this.fullScreenClicked
+ });
+ ContextMenu.Instance.addItem({
+ description: "Fields",
+ event: this.fieldsClicked
+ });
+ ContextMenu.Instance.addItem({
+ description: "Center",
+ event: () => this.props.focus(this.props.Document)
+ });
+ ContextMenu.Instance.addItem({
+ description: "Open Right",
+ event: () =>
+ CollectionDockingView.Instance.AddRightSplit(this.props.Document)
+ });
+ ContextMenu.Instance.addItem({
+ description: "Copy URL",
+ event: () => {
+ Utils.CopyText(ServerUtils.prepend("/doc/" + this.props.Document.Id));
+ }
+ });
ContextMenu.Instance.addItem({
description: "Copy ID",
event: () => {
@@ -290,52 +408,95 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
});
//ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) })
- ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
+ ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
if (!this.topMost) {
// DocumentViews should stop propagation of this event
e.stopPropagation();
}
- ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked })
- ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15)
+ ContextMenu.Instance.addItem({
+ description: "Delete",
+ event: this.deleteClicked
+ });
+ ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
SelectionManager.SelectDoc(this, e.ctrlKey);
- }
+ };
+ isMinimized = () => {
+ let field = this.props.Document.GetT(KeyStore.Minimized, BooleanField);
+ if (field && field !== FieldWaiting) {
+ return field.Data;
+ }
+ };
+
+ @action
+ expand = () => {
+ this.props.Document.SetData(
+ KeyStore.Minimized,
+ false as boolean,
+ BooleanField
+ );
+ };
isSelected = () => {
return SelectionManager.IsSelected(this);
- }
+ };
select = (ctrlPressed: boolean) => {
- SelectionManager.SelectDoc(this, ctrlPressed)
- }
+ SelectionManager.SelectDoc(this, ctrlPressed);
+ };
render() {
if (!this.props.Document) {
- return (null);
- }
- let lkeys = this.props.Document.GetT(KeyStore.LayoutKeys, ListField);
- if (!lkeys || lkeys === FieldWaiting) {
- return <p>Error loading layout keys</p>;
+ return null;
}
+
var scaling = this.props.ContentScaling();
var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0);
var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0);
- var backgroundcolor = this.props.Document.GetText(KeyStore.BackgroundColor, "");
- return (
- <div className="documentView-node" ref={this._mainCont}
- style={{
- background: backgroundcolor,
- width: nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%",
- height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%",
- transformOrigin: "left top",
- transform: `scale(${scaling} , ${scaling})`
- }}
- onDrop={this.onDrop}
- onContextMenu={this.onContextMenu}
- onPointerDown={this.onPointerDown} >
- <DocumentContentsView {...this.props} isSelected={this.isSelected} select={this.select} layoutKey={KeyStore.Layout} />
- </div >
- )
+
+ if (this.isMinimized()) {
+ return (
+ <div
+ className="minimized-box"
+ ref={this._mainCont}
+ style={{
+ transformOrigin: "left top",
+ transform: `scale(${scaling} , ${scaling})`
+ }}
+ onClick={this.expand}
+ onDrop={this.onDrop}
+ onPointerDown={this.onPointerDown}
+ />
+ );
+ } else {
+ var backgroundcolor = this.props.Document.GetText(
+ KeyStore.BackgroundColor,
+ ""
+ );
+ return (
+ <div
+ className="documentView-node"
+ ref={this._mainCont}
+ style={{
+ background: backgroundcolor,
+ width: nativeWidth > 0 ? nativeWidth.toString() + "px" : "100%",
+ height: nativeHeight > 0 ? nativeHeight.toString() + "px" : "100%",
+ transformOrigin: "left top",
+ transform: `scale(${scaling} , ${scaling})`
+ }}
+ onDrop={this.onDrop}
+ onContextMenu={this.onContextMenu}
+ onPointerDown={this.onPointerDown}
+ >
+ <DocumentContentsView
+ {...this.props}
+ isSelected={this.isSelected}
+ select={this.select}
+ layoutKey={KeyStore.Layout}
+ />
+ </div>
+ );
+ }
}
-} \ No newline at end of file
+}