aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-07-07 16:20:33 -0400
committerbobzel <zzzman@gmail.com>2022-07-07 16:20:33 -0400
commitb7e66da6b23cdb41c127000dfe13843d35f7d0cc (patch)
tree97f74e2c5dde93d470cb928a0577435927fc2e80 /src/client/views/collections
parent897544f4bbe003778bcc48a11fd30b57f9e1ea50 (diff)
fixed more errors.
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionDockingView.scss29
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx337
-rw-r--r--src/client/views/collections/TabDocView.tsx609
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss27
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx610
5 files changed, 894 insertions, 718 deletions
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 21045a20e..6d5a39bc2 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,5 +1,6 @@
-@import "../global/globalCssVariables.scss";
-
+@import '../global/globalCssVariables.scss';
+@import '../../../../node_modules/golden-layout/src/css/goldenlayout-base.css';
+@import '../../../../node_modules/golden-layout/src/css/goldenlayout-dark-theme.css';
.lm_title {
-webkit-appearance: none;
@@ -153,7 +154,7 @@
background: $white;
}
- .lm_controls>li {
+ .lm_controls > li {
opacity: 1;
transform: scale(1);
}
@@ -196,7 +197,7 @@
position: absolute;
cursor: move;
border: 2px solid #cfe8ff;
- box-shadow: inset 0 0 60px rgba(0, 0, 0, .2);
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.2);
border-radius: 5px;
z-index: 1000;
box-sizing: border-box;
@@ -205,7 +206,7 @@
.flexlayout__outline_rect_edge {
cursor: move;
border: 2px solid #b7d1b5;
- box-shadow: inset 0 0 60px rgba(0, 0, 0, .2);
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.2);
border-radius: 5px;
z-index: 1000;
box-sizing: border-box;
@@ -214,7 +215,7 @@
.flexlayout__edge_rect {
position: absolute;
z-index: 1000;
- box-shadow: inset 0 0 5px rgba(0, 0, 0, .2);
+ box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background-color: lightgray;
}
@@ -222,7 +223,7 @@
position: absolute;
cursor: move;
border: 2px solid #aaaaaa;
- box-shadow: inset 0 0 60px rgba(0, 0, 0, .3);
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.3);
border-radius: 5px;
z-index: 1000;
box-sizing: border-box;
@@ -301,7 +302,7 @@
.flexlayout__tab_button:hover .flexlayout__tab_button_trailing,
.flexlayout__tab_button--selected .flexlayout__tab_button_trailing {
- background: transparent url("../../../../node_modules/flexlayout-react/images/close_white.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/close_white.png') no-repeat center;
}
.flexlayout__tab_button_overflow {
@@ -314,7 +315,7 @@
font-size: 10px;
color: lightgray;
font-family: Arial, sans-serif;
- background: transparent url("../../../../node_modules/flexlayout-react/images/more.png") no-repeat left;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/more.png') no-repeat left;
}
.flexlayout__tabset_header {
@@ -369,7 +370,7 @@
height: 20px;
border: none;
outline-width: 0;
- background: transparent url("../../../../node_modules/flexlayout-react/images/maximize.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/maximize.png') no-repeat center;
}
.flexlayout__tab_toolbar_button-max {
@@ -377,7 +378,7 @@
height: 20px;
border: none;
outline-width: 0;
- background: transparent url("../../../../node_modules/flexlayout-react/images/restore.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/restore.png') no-repeat center;
}
.flexlayout__popup_menu_item {
@@ -390,7 +391,7 @@
}
.flexlayout__popup_menu_container {
- box-shadow: inset 0 0 5px rgba(0, 0, 0, .15);
+ box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.15);
border: 1px solid #555;
background: #222;
border-radius: 3px;
@@ -497,7 +498,7 @@
.flexlayout__border_button:hover .flexlayout__border_button_trailing,
.flexlayout__border_button--selected .flexlayout__border_button_trailing {
- background: transparent url("../../../../node_modules/flexlayout-react/images/close_white.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/close_white.png') no-repeat center;
}
.flexlayout__border_toolbar_left {
@@ -539,4 +540,4 @@
bottom: 0;
right: 0;
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 0830b6fdf..27478e59b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,34 +1,32 @@
-import 'golden-layout/src/css/goldenlayout-base.css';
-import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx";
-import { observer } from "mobx-react";
+import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
import * as ReactDOM from 'react-dom';
-import * as GoldenLayout from "../../../client/goldenLayout";
-import { Doc, DocListCast, Opt } from "../../../fields/Doc";
+import * as GoldenLayout from '../../../client/goldenLayout';
+import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { inheritParentAcls } from '../../../fields/util';
import { emptyFunction, incrementTitleCopy } from '../../../Utils';
-import { DocServer } from "../../DocServer";
+import { DocServer } from '../../DocServer';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
-import { DragManager } from "../../util/DragManager";
+import { DragManager } from '../../util/DragManager';
import { InteractionUtils } from '../../util/InteractionUtils';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
-import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from '../../util/UndoManager';
import { LightboxView } from '../LightboxView';
-import "./CollectionDockingView.scss";
+import './CollectionDockingView.scss';
import { CollectionFreeFormView } from './collectionFreeForm';
-import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import { CollectionViewType } from './CollectionView';
import { TabDocView } from './TabDocView';
-import React = require("react");
-const _global = (window /* browser */ || global /* node */) as any;
+import React = require('react');
+const _global = (window /* browser */ || global) /* node */ as any;
@observer
export class CollectionDockingView extends CollectionSubView() {
@@ -41,8 +39,8 @@ export class CollectionDockingView extends CollectionSubView() {
width: width,
props: {
documentId: document[Id],
- panelName // name of tab that can be used to close or replace its contents
- }
+ panelName, // name of tab that can be used to close or replace its contents
+ },
};
}
@@ -50,14 +48,16 @@ export class CollectionDockingView extends CollectionSubView() {
private _lightboxReactionDisposer?: IReactionDisposer;
private _containerRef = React.createRef<HTMLDivElement>();
public _flush: UndoManager.Batch | undefined;
- private _ignoreStateChange = "";
+ private _ignoreStateChange = '';
public tabMap: Set<any> = new Set();
- public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; }
+ public get HasFullScreen() {
+ return this._goldenLayout._maximisedItem !== null;
+ }
private _goldenLayout: any = null;
constructor(props: SubCollectionViewProps) {
super(props);
- runInAction(() => CollectionDockingView.Instance = this);
+ runInAction(() => (CollectionDockingView.Instance = this));
//Why is this here?
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
@@ -66,19 +66,18 @@ export class CollectionDockingView extends CollectionSubView() {
/**
* Switches from dragging a document around a freeform canvas to dragging it as a tab to be docked.
- *
+ *
* @param e fake mouse down event position data containing pageX and pageY coordinates
* @param dragDocs the documents to be dragged
* @param batch optionally an undo batch that has been started to use instead of starting a new batch
- */
- public StartOtherDrag = (e: { pageX: number, pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => {
- this._flush = this._flush ?? UndoManager.StartBatch("golden layout drag");
- const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) :
- { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) };
- const dragSource = this._goldenLayout.createDragSource(document.createElement("div"), config);
+ */
+ public StartOtherDrag = (e: { pageX: number; pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => {
+ this._flush = this._flush ?? UndoManager.StartBatch('golden layout drag');
+ const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) : { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) };
+ const dragSource = this._goldenLayout.createDragSource(document.createElement('div'), config);
this.tabDragStart(dragSource, finishDrag);
dragSource._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 });
- }
+ };
tabItemDropped = () => DragManager.CompleteWindowDrag?.(false);
tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => {
@@ -88,7 +87,7 @@ export class CollectionDockingView extends CollectionSubView() {
if (aborted) {
proxy._dragListener.AbortDrag();
if (this._flush) {
- this._flush.cancel(); // cancel the undo change being logged
+ this._flush.cancel(); // cancel the undo change being logged
this._flush = undefined;
this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout)
}
@@ -96,16 +95,16 @@ export class CollectionDockingView extends CollectionSubView() {
}
finishDrag?.(aborted);
};
- }
+ };
@undoBatch
public CloseFullScreen = () => {
this._goldenLayout._maximisedItem?.toggleMaximise();
this.stateChanged();
- }
+ };
@undoBatch
public static CloseSplit(document: Opt<Doc>, panelName?: string): boolean {
- const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document);
+ const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find(tab => (panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document));
if (tab) {
const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
if (j !== -1) {
@@ -121,12 +120,12 @@ export class CollectionDockingView extends CollectionSubView() {
public static OpenFullScreen(doc: Doc) {
SelectionManager.DeselectAll();
const instance = CollectionDockingView.Instance;
- if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") {
+ if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === 'layout') {
return CurrentUserUtils.openDashboard(doc);
}
const newItemStackConfig = {
type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))]
+ content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))],
};
const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
instance._goldenLayout.root.contentItems[0].addChild(docconfig);
@@ -150,7 +149,7 @@ export class CollectionDockingView extends CollectionSubView() {
stack.contentItems[activeContentItemIndex].remove();
return CollectionDockingView.Instance.layoutChanged();
}
- const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => tab.contentItem.config.props.panelName === panelName);
+ const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find(tab => tab.contentItem.config.props.panelName === panelName);
if (tab) {
tab.header.parent.addChild(newConfig, undefined);
const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
@@ -160,11 +159,9 @@ export class CollectionDockingView extends CollectionSubView() {
return CollectionDockingView.AddSplit(document, panelName, stack, panelName);
}
-
@undoBatch
public static ToggleSplit(doc: Doc, location: string, stack?: any, panelName?: string) {
- return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === doc) !== -1 ?
- CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName);
+ return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex(tab => tab.DashDoc === doc) !== -1 ? CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName);
}
//
@@ -193,35 +190,37 @@ export class CollectionDockingView extends CollectionSubView() {
const newItem = glayRoot.layoutManager.createContentItem({ type: 'stack', content: [docContentConfig] }, instance._goldenLayout);
newItem.callDownwards('_$init');
return newItem;
- }
- if (glayRoot.contentItems.length === 0) { // if no rows / columns
+ };
+ if (glayRoot.contentItems.length === 0) {
+ // if no rows / columns
glayRoot.addChild(newContentItem());
} else if (glayRoot.contentItems[0].isStack) {
glayRoot.contentItems[0].addChild(docContentConfig);
- } else if (
- glayRoot.contentItems.length === 1 &&
- glayRoot.contentItems[0].contentItems.length === 1 &&
- glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) {
+ } else if (glayRoot.contentItems.length === 1 && glayRoot.contentItems[0].contentItems.length === 1 && glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) {
glayRoot.contentItems[0].contentItems[0].addChild(docContentConfig);
- }
- else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
+ } else if (instance._goldenLayout.root.contentItems[0].isRow) {
+ // if row
switch (pullSide) {
default:
- case "right": glayRoot.contentItems[0].addChild(newContentItem()); break;
- case "left": glayRoot.contentItems[0].addChild(newContentItem(), 0); break;
- case "top":
- case "bottom":
+ case 'right':
+ glayRoot.contentItems[0].addChild(newContentItem());
+ break;
+ case 'left':
+ glayRoot.contentItems[0].addChild(newContentItem(), 0);
+ break;
+ case 'top':
+ case 'bottom':
// if not going in a row layout, must add already existing content into column
const rowlayout = glayRoot.contentItems[0];
- const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
+ const newColumn = rowlayout.layoutManager.createContentItem({ type: 'column' }, instance._goldenLayout);
const newItem = newContentItem();
instance._goldenLayout.saveScrollTops(rowlayout.element);
rowlayout.parent.replaceChild(rowlayout, newColumn);
- if (pullSide === "top") {
+ if (pullSide === 'top') {
newColumn.addChild(rowlayout, undefined, true);
newColumn.addChild(newItem, 0, true);
- } else if (pullSide === "bottom") {
+ } else if (pullSide === 'bottom') {
newColumn.addChild(newItem, undefined, true);
newColumn.addChild(rowlayout, 0, true);
}
@@ -230,21 +229,26 @@ export class CollectionDockingView extends CollectionSubView() {
rowlayout.config.height = 50;
newItem.config.height = 50;
}
- } else {// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
+ } else {
+ // if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
switch (pullSide) {
- case "top": glayRoot.contentItems[0].addChild(newContentItem(), 0); break;
- case "bottom": glayRoot.contentItems[0].addChild(newContentItem()); break;
- case "left":
- case "right":
+ case 'top':
+ glayRoot.contentItems[0].addChild(newContentItem(), 0);
+ break;
+ case 'bottom':
+ glayRoot.contentItems[0].addChild(newContentItem());
+ break;
+ case 'left':
+ case 'right':
default:
// if not going in a row layout, must add already existing content into column
const collayout = glayRoot.contentItems[0];
- const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
+ const newRow = collayout.layoutManager.createContentItem({ type: 'row' }, instance._goldenLayout);
const newItem = newContentItem();
instance._goldenLayout.saveScrollTops(collayout.element);
collayout.parent.replaceChild(collayout, newRow);
- if (pullSide === "left") {
+ if (pullSide === 'left') {
newRow.addChild(collayout, undefined, true);
newRow.addChild(newItem, 0, true);
} else {
@@ -276,7 +280,7 @@ export class CollectionDockingView extends CollectionSubView() {
const config = StrCast(this.props.Document.dockingConfig);
if (config) {
const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) ?? [];
+ const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')) ?? [];
await Promise.all(docids.map(id => DocServer.GetRefField(id)));
if (this._goldenLayout) {
@@ -287,12 +291,12 @@ export class CollectionDockingView extends CollectionSubView() {
this._goldenLayout.unbind('tabCreated', this.tabCreated);
this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
this._goldenLayout.unbind('stackCreated', this.stackCreated);
- } catch (e) { }
+ } catch (e) {}
}
this.tabMap.clear();
this._goldenLayout.destroy();
}
- const glay = this._goldenLayout = new GoldenLayout(JSON.parse(config));
+ const glay = (this._goldenLayout = new GoldenLayout(JSON.parse(config)));
glay.on('tabCreated', this.tabCreated);
glay.on('tabDestroyed', this.tabDestroyed);
glay.on('stackCreated', this.stackCreated);
@@ -303,46 +307,52 @@ export class CollectionDockingView extends CollectionSubView() {
glay.root.layoutManager.on('dragStart', this.tabDragStart);
glay.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
}
- }
+ };
componentDidMount: () => void = () => {
if (this._containerRef.current) {
- this._lightboxReactionDisposer = reaction(() => LightboxView.LightboxDoc, doc => setTimeout(() => !doc && this.onResize(undefined)));
+ this._lightboxReactionDisposer = reaction(
+ () => LightboxView.LightboxDoc,
+ doc => setTimeout(() => !doc && this.onResize(undefined))
+ );
new _global.ResizeObserver(this.onResize).observe(this._containerRef.current);
- this._reactionDisposer = reaction(() => StrCast(this.props.Document.dockingConfig),
+ this._reactionDisposer = reaction(
+ () => StrCast(this.props.Document.dockingConfig),
config => {
- if (!this._goldenLayout || this._ignoreStateChange !== config) { // bcz: TODO! really need to diff config with ignoreStateChange and modify the current goldenLayout instead of building a new one.
+ if (!this._goldenLayout || this._ignoreStateChange !== config) {
+ // bcz: TODO! really need to diff config with ignoreStateChange and modify the current goldenLayout instead of building a new one.
this.setupGoldenLayout();
}
- this._ignoreStateChange = "";
- });
+ this._ignoreStateChange = '';
+ }
+ );
setTimeout(this.setupGoldenLayout);
//window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
}
- }
+ };
componentWillUnmount: () => void = () => {
try {
this._goldenLayout.unbind('stackCreated', this.stackCreated);
this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- } catch (e) { }
+ } catch (e) {}
this._goldenLayout?.destroy();
window.removeEventListener('resize', this.onResize);
this._reactionDisposer?.();
this._lightboxReactionDisposer?.();
- }
+ };
@action
onResize = (event: any) => {
const cur = this._containerRef.current;
// bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
!LightboxView.LightboxDoc && cur && this._goldenLayout?.updateSize(cur.getBoundingClientRect().width, cur.getBoundingClientRect().height);
- }
+ };
@action
onPointerUp = (e: MouseEvent): void => {
- window.removeEventListener("pointerup", this.onPointerUp);
+ window.removeEventListener('pointerup', this.onPointerUp);
const flush = this._flush;
this._flush = undefined;
if (flush) {
@@ -350,69 +360,65 @@ export class CollectionDockingView extends CollectionSubView() {
if (!this.stateChanged()) flush.cancel();
else flush.end();
}
- }
+ };
@action
onPointerDown = (e: React.PointerEvent): void => {
let hitFlyout = false;
for (let par = e.target as any; !hitFlyout && par; par = par.parentElement) {
- hitFlyout = (par.className === "dockingViewButtonSelector");
+ hitFlyout = par.className === 'dockingViewButtonSelector';
}
if (!hitFlyout) {
const htmlTarget = e.target as HTMLElement;
- window.addEventListener("mouseup", this.onPointerUp);
- if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) {
- const className = typeof htmlTarget.className === "string" ? htmlTarget.className : "";
- if (!className.includes("lm_close") && !className.includes("lm_maximise")) {
- this._flush = UndoManager.StartBatch("golden layout edit");
+ window.addEventListener('mouseup', this.onPointerUp);
+ if (!htmlTarget.closest('*.lm_content') && (htmlTarget.closest('*.lm_tab') || htmlTarget.closest('*.lm_stack'))) {
+ const className = typeof htmlTarget.className === 'string' ? htmlTarget.className : '';
+ if (!className.includes('lm_close') && !className.includes('lm_maximise')) {
+ this._flush = UndoManager.StartBatch('golden layout edit');
}
}
}
- if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) &&
- ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.ActiveTool)) {
+ if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.ActiveTool)) {
e.stopPropagation();
}
- }
+ };
public CaptureThumbnail() {
const content = this.props.DocumentView?.()?.ContentDiv;
if (content) {
- const _width = Number(getComputedStyle(content).width.replace("px",""));
- const _height = Number(getComputedStyle(content).height.replace("px",""));
- return CollectionFreeFormView.UpdateIcon(
- this.layoutDoc[Id] + "-icon" + (new Date()).getTime(),
- content,
- _width, _height,
- _width, _height, 0, 1, true, this.layoutDoc[Id] + "-icon",
- (iconFile, _nativeWidth, _nativeHeight) => {
- const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title+"-icon", _width, _height, _nativeWidth, _nativeHeight});
- const proto = Cast(img.proto, Doc, null)!;
- proto["data-nativeWidth"] = _width;
- proto["data-nativeHeight"] = _height;
- this.dataDoc.thumb = img;
- });
+ const _width = Number(getComputedStyle(content).width.replace('px', ''));
+ const _height = Number(getComputedStyle(content).height.replace('px', ''));
+ return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => {
+ const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title + '-icon', _width, _height, _nativeWidth, _nativeHeight });
+ const proto = Cast(img.proto, Doc, null)!;
+ proto['data-nativeWidth'] = _width;
+ proto['data-nativeHeight'] = _height;
+ this.dataDoc.thumb = img;
+ });
}
-
}
- public static async TakeSnapshot(doc: Doc|undefined, clone = false) {
+ public static async TakeSnapshot(doc: Doc | undefined, clone = false) {
if (!doc) return undefined;
let json = StrCast(doc.dockingConfig);
if (clone) {
const cloned = await Doc.MakeClone(doc);
- Array.from(cloned.map.entries()).map(entry => json = json.replace(entry[0], entry[1][Id]));
+ Array.from(cloned.map.entries()).map(entry => (json = json.replace(entry[0], entry[1][Id])));
Doc.GetProto(cloned.clone).dockingConfig = json;
return CurrentUserUtils.openDashboard(cloned.clone);
}
const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const origtabids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) || [];
- const origtabs = origtabids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
+ const origtabids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')) || [];
+ const origtabs = origtabids
+ .map(id => DocServer.GetCachedRefField(id))
+ .filter(f => f)
+ .map(f => f as Doc);
const newtabs = origtabs.map(origtab => {
const origtabdocs = DocListCast(origtab.data);
const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeAlias(origtab);
const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeAlias(origtabdoc));
if (newtabdocs.length) {
Doc.GetProto(newtab).data = new List<Doc>(newtabdocs);
- newtabdocs.forEach(ntab => ntab.context = newtab);
+ newtabdocs.forEach(ntab => (ntab.context = newtab));
}
json = json.replace(origtab[Id], newtab[Id]);
return newtab;
@@ -426,22 +432,27 @@ export class CollectionDockingView extends CollectionSubView() {
this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
const json = JSON.stringify(this._goldenLayout.toConfig());
const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", ""));
- const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
+ const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', ''));
+ const docs = !docids
+ ? []
+ : docids
+ .map(id => DocServer.GetCachedRefField(id))
+ .filter(f => f)
+ .map(f => f as Doc);
const changesMade = this.props.Document.dockcingConfig !== json;
if (changesMade && !this._flush) {
UndoManager.RunInBatch(() => {
this.props.Document.dockingConfig = json;
this.props.Document.data = new List<Doc>(docs);
- }, "state changed");
+ }, 'state changed');
}
return changesMade;
- }
+ };
tabDestroyed = (tab: any) => {
- if(tab.DashDoc?.type !== DocumentType.KVP) {
- Doc.AddDocToList(CurrentUserUtils.MyHeaderBar, "data", tab.DashDoc);
- Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true);
+ if (tab.DashDoc?.type !== DocumentType.KVP) {
+ Doc.AddDocToList(CurrentUserUtils.MyHeaderBar, 'data', tab.DashDoc);
+ Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true);
}
const dview = CollectionDockingView.Instance.props.Document;
const fieldKey = CollectionDockingView.Instance.props.fieldKey;
@@ -450,63 +461,95 @@ export class CollectionDockingView extends CollectionSubView() {
tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
this.stateChanged();
- }
+ };
tabCreated = (tab: any) => {
this.tabMap.add(tab);
- tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
- }
+ tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
+ };
stackCreated = (stack: any) => {
stack.header?.element.on('mousedown', (e: any) => {
const dashboard = CurrentUserUtils.ActiveDashboard;
if (dashboard && e.target === stack.header?.element[0] && e.button === 2) {
- dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1;
+ dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
const docToAdd = Docs.Create.FreeformDocument([], {
- _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _backgroundGridShow: true, _fitWidth: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`,
+ _width: this.props.PanelWidth(),
+ _height: this.props.PanelHeight(),
+ _backgroundGridShow: true,
+ _fitWidth: true,
+ title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
});
this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
- CollectionDockingView.AddSplit(docToAdd, "", stack);
+ CollectionDockingView.AddSplit(docToAdd, '', stack);
}
});
- stack.header?.controlsContainer.find('.lm_close') //get the close icon
+ stack.header?.controlsContainer
+ .find('.lm_close') //get the close icon
.off('click') //unbind the current click handler
- .click(action(() => {
- //if (confirm('really close this?')) {
- if (!stack.parent.parent.isRoot || stack.parent.contentItems.length > 1) {
- stack.remove();
- } else {
- alert('cant delete the last stack');
- }
- }));
+ .click(
+ action(() => {
+ //if (confirm('really close this?')) {
+ if (!stack.parent.parent.isRoot || stack.parent.contentItems.length > 1) {
+ stack.remove();
+ } else {
+ alert('cant delete the last stack');
+ }
+ })
+ );
- stack.header?.controlsContainer.find('.lm_maximise') //get the close icon
+ stack.header?.controlsContainer
+ .find('.lm_maximise') //get the close icon
.click(() => setTimeout(this.stateChanged));
- stack.header?.controlsContainer.find('.lm_popout') //get the popout icon
+ stack.header?.controlsContainer
+ .find('.lm_popout') //get the popout icon
.off('click') //unbind the current click handler
- .click(action(() => {
- // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size
- const dashboard = CurrentUserUtils.ActiveDashboard;
- if (dashboard) {
- dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1;
- const docToAdd = Docs.Create.FreeformDocument([], {
- _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, _backgroundGridShow: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`
- });
- this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
- CollectionDockingView.AddSplit(docToAdd, "", stack);
- }
- }));
- }
+ .click(
+ action(() => {
+ // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size
+ const dashboard = CurrentUserUtils.ActiveDashboard;
+ if (dashboard) {
+ dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
+ const docToAdd = Docs.Create.FreeformDocument([], {
+ _width: this.props.PanelWidth(),
+ _height: this.props.PanelHeight(),
+ _fitWidth: true,
+ _backgroundGridShow: true,
+ title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
+ });
+ this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
+ CollectionDockingView.AddSplit(docToAdd, '', stack);
+ }
+ })
+ );
+ };
render() {
return <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} ref={this._containerRef} />;
}
}
-ScriptingGlobals.add(function openInLightbox(doc: any) { LightboxView.AddDocTab(doc, "lightbox"); },
- "opens up document in a lightbox", "(doc: any)");
-ScriptingGlobals.add(function openOnRight(doc: any) { return CollectionDockingView.AddSplit(doc, "right"); },
- "opens up document in tab on right side of the screen", "(doc: any)");
-ScriptingGlobals.add(function openInOverlay(doc: any) { return Doc.AddDocToList(CurrentUserUtils.MyOverlayDocs, undefined, doc); },
- "opens up document in screen overlay layer", "(doc: any)");
-ScriptingGlobals.add(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); }); \ No newline at end of file
+ScriptingGlobals.add(
+ function openInLightbox(doc: any) {
+ LightboxView.AddDocTab(doc, 'lightbox');
+ },
+ 'opens up document in a lightbox',
+ '(doc: any)'
+);
+ScriptingGlobals.add(
+ function openOnRight(doc: any) {
+ return CollectionDockingView.AddSplit(doc, 'right');
+ },
+ 'opens up document in tab on right side of the screen',
+ '(doc: any)'
+);
+ScriptingGlobals.add(
+ function openInOverlay(doc: any) {
+ return Doc.AddDocToList(CurrentUserUtils.MyOverlayDocs, undefined, doc);
+ },
+ 'opens up document in screen overlay layer',
+ '(doc: any)'
+);
+ScriptingGlobals.add(function useRightSplit(doc: any, shiftKey?: boolean) {
+ CollectionDockingView.ReplaceTab(doc, 'right', undefined, shiftKey);
+});
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 62d07b0e4..c0a61c90f 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -1,43 +1,41 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
-import 'golden-layout/src/css/goldenlayout-base.css';
-import 'golden-layout/src/css/goldenlayout-dark-theme.css';
import { clamp } from 'lodash';
-import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
-import { observer } from "mobx-react";
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { observer } from 'mobx-react';
import * as ReactDOM from 'react-dom';
-import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
-import { FieldId } from "../../../fields/RefField";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from "../../../Utils";
-import { DocServer } from "../../DocServer";
+import { FieldId } from '../../../fields/RefField';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
+import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils';
+import { DocServer } from '../../DocServer';
import { DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from "../../util/DragManager";
+import { DragManager, dropActionType } from '../../util/DragManager';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
-import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from '../../util/UndoManager';
import { Colors, Shadows } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { MainView } from '../MainView';
-import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
+import { DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView';
import { DashFieldView } from '../nodes/formattedText/DashFieldView';
import { PinProps, PresBox, PresMovement } from '../nodes/trails';
import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
import { CollectionDockingView } from './CollectionDockingView';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { CollectionView, CollectionViewType } from './CollectionView';
-import "./TabDocView.scss";
-import React = require("react");
+import './TabDocView.scss';
+import React = require('react');
import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
-const _global = (window /* browser */ || global /* node */) as any;
+const _global = (window /* browser */ || global) /* node */ as any;
interface TabDocViewProps {
documentId: FieldId;
@@ -54,9 +52,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
@observable _document: Doc | undefined;
@observable _view: DocumentView | undefined;
- @computed get layoutDoc() { return this._document && Doc.Layout(this._document); }
- @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor))); }
- @computed get tabTextColor() { return this._document?.type === DocumentType.PRES ? "black" : StrCast(this._document?._color, StrCast(this._document?.color, DefaultStyleProvider(this._document, undefined, StyleProp.Color))); }
+ @computed get layoutDoc() {
+ return this._document && Doc.Layout(this._document);
+ }
+ @computed get tabColor() {
+ return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor)));
+ }
+ @computed get tabTextColor() {
+ return this._document?.type === DocumentType.PRES ? 'black' : StrCast(this._document?._color, StrCast(this._document?.color, DefaultStyleProvider(this._document, undefined, StyleProp.Color)));
+ }
// @computed get renderBounds() {
// const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0];
// const xbounds = bounds[2] - bounds[0];
@@ -65,74 +69,91 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// return { l: bounds[0] + xbounds / 2 - dim / 2, t: bounds[1] + ybounds / 2 - dim / 2, cx: bounds[0] + xbounds / 2, cy: bounds[1] + ybounds / 2, dim };
// }
- get stack() { return (this.props as any).glContainer.parent.parent; }
- get tab() { return (this.props as any).glContainer.tab; }
- get view() { return this._view; }
+ get stack() {
+ return (this.props as any).glContainer.parent.parent;
+ }
+ get tab() {
+ return (this.props as any).glContainer.tab;
+ }
+ get view() {
+ return this._view;
+ }
_lastTab: any;
_lastView: DocumentView | undefined;
@action
init = (tab: any, doc: Opt<Doc>) => {
if (tab.contentItem === tab.header.parent.getActiveContentItem()) this._activated = true;
- if (tab.DashDoc !== doc && doc && tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
+ if (tab.DashDoc !== doc && doc && tab.hasOwnProperty('contentItem') && tab.contentItem.config.type !== 'stack') {
tab._disposers = {} as { [name: string]: IReactionDisposer };
tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true);
tab.DashDoc = doc;
const iconType: IconProp = Doc.toIcon(doc);
// setup the title element and set its size according to the # of chars in the title. Show the full title when clicked.
const titleEle = tab.titleElement[0];
- const iconWrap = document.createElement("div");
- const closeWrap = document.createElement("div");
+ const iconWrap = document.createElement('div');
+ const closeWrap = document.createElement('div');
titleEle.size = StrCast(doc.title).length + 3;
titleEle.value = doc.title;
titleEle.onkeydown = (e: KeyboardEvent) => {
e.stopPropagation();
};
- titleEle.onchange = undoBatch(action((e: any) => {
- titleEle.size = e.currentTarget.value.length + 3;
- Doc.GetProto(doc).title = e.currentTarget.value;
- }));
+ titleEle.onchange = undoBatch(
+ action((e: any) => {
+ titleEle.size = e.currentTarget.value.length + 3;
+ Doc.GetProto(doc).title = e.currentTarget.value;
+ })
+ );
if (tab.element[0].children[1].children.length === 1) {
- iconWrap.className = "lm_iconWrap lm_moreInfo";
+ iconWrap.className = 'lm_iconWrap lm_moreInfo';
const dragBtnDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, action(e => {
- if (this.view) {
- SelectionManager.SelectView(this.view, false);
- let child = this.view.ContentDiv!.children[0];
- while (child.children.length) {
- const next = Array.from(child.children).find(c => c.className?.toString().includes("SVGAnimatedString") || typeof (c.className) === "string");
- if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
- if (next?.className?.toString().includes(DashFieldView.name)) break;
- if (next) child = next;
- else break;
+ setupMoveUpEvents(
+ this,
+ e,
+ e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY),
+ returnFalse,
+ action(e => {
+ if (this.view) {
+ SelectionManager.SelectView(this.view, false);
+ let child = this.view.ContentDiv!.children[0];
+ while (child.children.length) {
+ const next = Array.from(child.children).find(c => c.className?.toString().includes('SVGAnimatedString') || typeof c.className === 'string');
+ if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
+ if (next?.className?.toString().includes(DashFieldView.name)) break;
+ if (next) child = next;
+ else break;
+ }
+ simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ } else {
+ this._activated = true;
+ setTimeout(() => this.view && SelectionManager.SelectView(this.view, false));
}
- simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
- }
- else { this._activated = true;
- setTimeout(() =>this.view && SelectionManager.SelectView(this.view, false));
- }
- }));
+ })
+ );
};
-
+
const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />;
- const closeIcon = <FontAwesomeIcon icon={"eye"} />;
+ const closeIcon = <FontAwesomeIcon icon={'eye'} />;
ReactDOM.render(docIcon, iconWrap);
ReactDOM.render(closeIcon, closeWrap);
tab.reactComponents = [iconWrap, closeWrap];
tab.element[0].prepend(iconWrap);
- tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
+ tab._disposers.layerDisposer = reaction(
+ () => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
({ layer, color }) => {
// console.log("TabDocView: " + this.tabColor);
// console.log("lightOrDark: " + lightOrDark(this.tabColor));
const textColor = lightOrDark(this.tabColor); //not working with StyleProp.Color
titleEle.style.color = textColor;
- titleEle.style.backgroundColor = "transparent";
+ titleEle.style.backgroundColor = 'transparent';
iconWrap.style.color = textColor;
closeWrap.style.color = textColor;
- tab.element[0].style.background = !layer ? color : "dimgrey";
- }, { fireImmediately: true });
+ tab.element[0].style.background = !layer ? color : 'dimgrey';
+ },
+ { fireImmediately: true }
+ );
}
// shifts the focus to this tab when another tab is dragged over it
tab.element[0].onmouseenter = (e: MouseEvent) => {
@@ -142,157 +163,167 @@ export class TabDocView extends React.Component<TabDocViewProps> {
}
};
-
// select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected
titleEle.onpointerdown = action((e: any) => {
- if (e.target.className !== "lm_iconWrap") {
+ if (e.target.className !== 'lm_iconWrap') {
if (this.view) SelectionManager.SelectView(this.view, false);
else this._activated = true;
if (Date.now() - titleEle.lastClick < 1000) titleEle.select();
titleEle.lastClick = Date.now();
- (document.activeElement !== titleEle) && titleEle.focus();
+ document.activeElement !== titleEle && titleEle.focus();
}
});
- tab._disposers.selectionDisposer = reaction(() => SelectionManager.Views().some(v => v.topMost && v.props.Document === doc),
- action((selected) => {
+ tab._disposers.selectionDisposer = reaction(
+ () => SelectionManager.Views().some(v => v.topMost && v.props.Document === doc),
+ action(selected => {
if (selected) this._activated = true;
const toggle = tab.element[0].children[1].children[0] as HTMLInputElement;
- selected && tab.contentItem !== tab.header.parent.getActiveContentItem() &&
- UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch");
+ selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), 'tab switch');
// toggle.style.fontWeight = selected ? "bold" : "";
// toggle.style.textTransform = selected ? "uppercase" : "";
- }));
-
+ })
+ );
// highlight the tab when the tab document is brushed in any part of the UI
- tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
- //titleEle.value = title;
- // titleEle.style.padding = degree ? 0 : 2;
- // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
- }, { fireImmediately: true });
+ tab._disposers.reactionDisposer = reaction(
+ () => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }),
+ ({ title, degree }) => {
+ //titleEle.value = title;
+ // titleEle.style.padding = degree ? 0 : 2;
+ // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
+ },
+ { fireImmediately: true }
+ );
// clean up the tab when it is closed
- tab.closeElement.off('click') //unbind the current click handler
+ tab.closeElement
+ .off('click') //unbind the current click handler
.click(function () {
Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
SelectionManager.DeselectAll();
- UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
+ UndoManager.RunInBatch(() => tab.contentItem.remove(), 'delete tab');
});
}
- }
+ };
/**
* Adds a document to the presentation view
**/
@action
- public static PinDoc(docs: Doc|Doc[], pinProps?: PinProps) {
- const docList = ((docs instanceof Doc) ? [docs]: docs);
- const batch = UndoManager.StartBatch("pinning doc");
+ public static PinDoc(docs: Doc | Doc[], pinProps?: PinProps) {
+ const docList = docs instanceof Doc ? [docs] : docs;
+ const batch = UndoManager.StartBatch('pinning doc');
// all docs will be added to the ActivePresentation as stored on CurrentUserUtils
const curPres = CurrentUserUtils.ActivePresentation;
- curPres && docList.forEach(doc => {
- // Edge Case 1: Cannot pin document to itself
- if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
- const pinDoc = Doc.MakeAlias(doc);
- pinDoc.presentationTargetDoc = doc;
- pinDoc.title = doc.title + " - Slide";
- pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children. the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
- pinDoc.presMovement = PresMovement.Zoom;
- pinDoc.groupWithUp = false;
- pinDoc.context = curPres;
- // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
- pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
- pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling.
- pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
- pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
- pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
- pinDoc.treeViewGrowsHorizontally = true;// the document expands horizontally when displayed as a tree view header
- pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
- const presArray: Doc[] = PresBox.Instance?.sortArray();
- const size: number = PresBox.Instance?._selectedArray.size;
- const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
- const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
- // If pinWithView option set then update scale and x / y props of slide
- if (pinProps?.pinWithView) {
- const viewProps = pinProps.pinWithView;
- pinDoc.presPinView = true;
- pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
- pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
- pinDoc.presPinViewScale = viewProps.scale;
- pinDoc.contentBounds = new List<number>([viewProps.bounds.left, viewProps.bounds.top, viewProps.bounds.left+viewProps.bounds.width, viewProps.bounds.top+viewProps.bounds.height]);
- }
- if (pinProps?.pinDocView) {
- const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(pinDoc.type as any) || pinDoc._viewType === CollectionViewType.Stacking;
- const pannable: boolean = ((pinDoc.type === DocumentType.COL && doc._viewType === CollectionViewType.Freeform) || doc.type === DocumentType.IMG);
- if (scrollable) {
- const scroll = doc._scrollTop;
- pinDoc.presPinView = true;
- pinDoc.presPinViewScroll = scroll;
- } else if ([DocumentType.AUDIO, DocumentType.VID].includes(doc.type as any)) {
- pinDoc.presPinView = true;
- pinDoc.presStartTime = doc._currentTimecode;
- pinDoc.presEndTime = NumCast(doc._currentTimecode) + 0.1;
- } else if (pannable) {
+ curPres &&
+ docList.forEach(doc => {
+ // Edge Case 1: Cannot pin document to itself
+ if (doc === curPres) {
+ alert('Cannot pin presentation document to itself');
+ return;
+ }
+ const pinDoc = Doc.MakeAlias(doc);
+ pinDoc.presentationTargetDoc = doc;
+ pinDoc.title = doc.title + ' - Slide';
+ pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children. the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
+ pinDoc.presMovement = PresMovement.Zoom;
+ pinDoc.groupWithUp = false;
+ pinDoc.context = curPres;
+ // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
+ pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
+ pinDoc.treeViewHeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
+ pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
+ pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
+ pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
+ pinDoc.treeViewGrowsHorizontally = true; // the document expands horizontally when displayed as a tree view header
+ pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
+ const presArray: Doc[] = PresBox.Instance?.sortArray();
+ const size: number = PresBox.Instance?._selectedArray.size;
+ const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
+ const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
+ // If pinWithView option set then update scale and x / y props of slide
+ if (pinProps?.pinWithView) {
+ const viewProps = pinProps.pinWithView;
pinDoc.presPinView = true;
- pinDoc.presPinViewX = pinDoc._panX;
- pinDoc.presPinViewY = pinDoc._panY;
- pinDoc.presPinViewScale = pinDoc._viewScale;
- const pw = NumCast(pinProps.panelWidth);
- const ph = NumCast(pinProps.panelHeight);
- const ps = NumCast(pinDoc._viewScale);
- if (pw && ph && ps) {
- pinDoc.contentBounds = new List<number>([
- NumCast(pinDoc.panX)-pw/2/ps,
- NumCast(pinDoc.panY)-ph/2/ps,
- NumCast(pinDoc.panX)+pw/2/ps,
- NumCast(pinDoc.panY)+ph/2/ps]);
+ pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
+ pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
+ pinDoc.presPinViewScale = viewProps.scale;
+ pinDoc.contentBounds = new List<number>([viewProps.bounds.left, viewProps.bounds.top, viewProps.bounds.left + viewProps.bounds.width, viewProps.bounds.top + viewProps.bounds.height]);
+ }
+ if (pinProps?.pinDocView) {
+ const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(pinDoc.type as any) || pinDoc._viewType === CollectionViewType.Stacking;
+ const pannable: boolean = (pinDoc.type === DocumentType.COL && doc._viewType === CollectionViewType.Freeform) || doc.type === DocumentType.IMG;
+ if (scrollable) {
+ const scroll = doc._scrollTop;
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewScroll = scroll;
+ } else if ([DocumentType.AUDIO, DocumentType.VID].includes(doc.type as any)) {
+ pinDoc.presPinView = true;
+ pinDoc.presStartTime = doc._currentTimecode;
+ pinDoc.presEndTime = NumCast(doc._currentTimecode) + 0.1;
+ } else if (pannable) {
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewX = pinDoc._panX;
+ pinDoc.presPinViewY = pinDoc._panY;
+ pinDoc.presPinViewScale = pinDoc._viewScale;
+ const pw = NumCast(pinProps.panelWidth);
+ const ph = NumCast(pinProps.panelHeight);
+ const ps = NumCast(pinDoc._viewScale);
+ if (pw && ph && ps) {
+ pinDoc.contentBounds = new List<number>([NumCast(pinDoc.panX) - pw / 2 / ps, NumCast(pinDoc.panY) - ph / 2 / ps, NumCast(pinDoc.panX) + pw / 2 / ps, NumCast(pinDoc.panY) + ph / 2 / ps]);
+ }
+ } else if (doc.type === DocumentType.COMPARISON) {
+ const width = doc._clipWidth;
+ pinDoc.presPinClipWidth = width;
+ pinDoc.presPinView = true;
}
- } else if (doc.type === DocumentType.COMPARISON) {
- const width = doc._clipWidth;
- pinDoc.presPinClipWidth = width;
- pinDoc.presPinView = true;
}
- }
- pinDoc.onClick = ScriptField.MakeFunction("navigateToDoc(self.presentationTargetDoc, self)");
- Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
- if (!pinProps?.audioRange && duration !== undefined) {
- pinDoc.mediaStart = "manual";
- pinDoc.mediaStop = "manual";
- pinDoc.presStartTime = NumCast(doc.clipStart);
- pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
- }
- //save position
- if (pinProps?.setPosition || pinDoc.isInkMask) {
- pinDoc.setPosition = true;
- pinDoc.y = doc.y;
- pinDoc.x = doc.x;
- pinDoc.presHideAfter = true;
- pinDoc.presHideBefore = true;
- pinDoc.title = doc.title + " (move)";
- pinDoc.presMovement = PresMovement.None;
- }
- if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
- PresBox.Instance?._selectedArray.clear();
- pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
- });
- if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+ pinDoc.onClick = ScriptField.MakeFunction('navigateToDoc(self.presentationTargetDoc, self)');
+ Doc.AddDocToList(curPres, 'data', pinDoc, presSelected);
+ if (!pinProps?.audioRange && duration !== undefined) {
+ pinDoc.mediaStart = 'manual';
+ pinDoc.mediaStop = 'manual';
+ pinDoc.presStartTime = NumCast(doc.clipStart);
+ pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
+ }
+ //save position
+ if (pinProps?.setPosition || pinDoc.isInkMask) {
+ pinDoc.setPosition = true;
+ pinDoc.y = doc.y;
+ pinDoc.x = doc.x;
+ pinDoc.presHideAfter = true;
+ pinDoc.presHideBefore = true;
+ pinDoc.title = doc.title + ' (move)';
+ pinDoc.presMovement = PresMovement.None;
+ }
+ if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
+ PresBox.Instance?._selectedArray.clear();
+ pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
+ });
+ if (
+ !Array.from(CollectionDockingView.Instance.tabMap)
+ .map(d => d.DashDoc)
+ .includes(curPres)
+ ) {
const docs = Cast(CurrentUserUtils.MyOverlayDocs.data, listSpec(Doc), []);
if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
- CollectionDockingView.AddSplit(curPres, "right");
+ CollectionDockingView.AddSplit(curPres, 'right');
setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
}
setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
}
componentDidMount() {
- new _global.ResizeObserver(action((entries: any) => {
- for (const entry of entries) {
- this._panelWidth = entry.contentRect.width;
- this._panelHeight = entry.contentRect.height;
- }
- })).observe(this.props.glContainer._element[0]);
- this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
+ new _global.ResizeObserver(
+ action((entries: any) => {
+ for (const entry of entries) {
+ this._panelWidth = entry.contentRect.width;
+ this._panelHeight = entry.contentRect.height;
+ }
+ })
+ ).observe(this.props.glContainer._element[0]);
+ this.props.glContainer.layoutManager.on('activeContentItemChanged', this.onActiveContentItemChanged);
this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(undefined);
// this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }),
// ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""),
@@ -306,7 +337,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
this._tabReaction?.();
this._view && DocumentManager.Instance.RemoveView(this._view);
- this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
+ this.props.glContainer.layoutManager.off('activeContentItemChanged', this.onActiveContentItemChanged);
}
@action.bound
@@ -326,25 +357,31 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack
addDocTab = (doc: Doc, location: string) => {
SelectionManager.DeselectAll();
- const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":");
- const locationParams = locationFields.length > 1 ? locationFields[1] : "";
+ const locationFields = doc._viewType === CollectionViewType.Docking ? ['dashboard'] : location.split(':');
+ const locationParams = locationFields.length > 1 ? locationFields[1] : '';
switch (locationFields[0]) {
- case "dashboard": return CurrentUserUtils.openDashboard(doc);
- case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
- case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
- case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
+ case 'dashboard':
+ return CurrentUserUtils.openDashboard(doc);
+ case 'close':
+ return CollectionDockingView.CloseSplit(doc, locationParams);
+ case 'fullScreen':
+ return CollectionDockingView.OpenFullScreen(doc);
+ case 'replace':
+ return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
// case "lightbox": {
// // TabDocView.PinDoc(doc, { hidePresBox: true });
// return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
// }
- case "lightbox": return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
- case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
- case "inPlace":
- case "add":
+ case 'lightbox':
+ return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
+ case 'toggle':
+ return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
+ case 'inPlace':
+ case 'add':
default:
return CollectionDockingView.AddSplit(doc, locationParams, this.stack);
}
- }
+ };
remDocTab = (doc: Doc | Doc[]) => {
if (doc === this._document) {
SelectionManager.DeselectAll();
@@ -352,11 +389,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
return true;
}
return false;
- }
+ };
getCurrentFrame = () => {
return NumCast(Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null)._currentFrame);
- }
+ };
@action
focusFunc = (doc: Doc, options?: DocFocusOptions) => {
const shrinkwrap = options?.originalTarget === this._document && this.view?.ComponentView?.shrinkWrap;
@@ -364,104 +401,113 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const focusSpeed = 1000;
shrinkwrap();
this._document._viewTransition = `transform ${focusSpeed}ms`;
- setTimeout(action(() => {
- this._document!._viewTransition = undefined;
- options?.afterFocus?.(false);
- }), focusSpeed);
+ setTimeout(
+ action(() => {
+ this._document!._viewTransition = undefined;
+ options?.afterFocus?.(false);
+ }),
+ focusSpeed
+ );
} else {
options?.afterFocus?.(false);
}
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
}
- }
+ };
active = () => this._isActive;
@observable _forceInvalidateScreenToLocal = 0;
ScreenToLocalTransform = () => {
this._forceInvalidateScreenToLocal;
const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont?.children?.[0] as HTMLElement);
return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY);
- }
+ };
PanelWidth = () => this._panelWidth;
PanelHeight = () => this._panelHeight;
miniMapColor = () => this.tabColor;
tabView = () => this._view;
- disableMinimap = () => !this._document || (this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform);
+ disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform;
hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap);
@computed get docView() {
- return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) :
- <><DocumentView key={this._document[Id]} ref={action((r: DocumentView) => {
- this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
- this._view = r;
- this._lastView = this._view;
- })}
- renderDepth={0}
- Document={this._document}
- DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
- ContainingCollectionView={undefined}
- ContainingCollectionDoc={undefined}
- onBrowseClick={MainView.Instance.exploreMode}
- isContentActive={returnTrue}
- PanelWidth={this.PanelWidth}
- PanelHeight={this.PanelHeight}
- styleProvider={DefaultStyleProvider}
- docFilters={CollectionDockingView.Instance.childDocFilters}
- docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
- searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
- addDocument={undefined}
- removeDocument={this.remDocTab}
- addDocTab={this.addDocTab}
- ScreenToLocalTransform={this.ScreenToLocalTransform}
- dontCenter={"y"}
- rootSelected={returnTrue}
- whenChildContentsActiveChanged={emptyFunction}
- focus={this.focusFunc}
- docViewPath={returnEmptyDoclist}
- bringToFront={emptyFunction}
- pinToPres={TabDocView.PinDoc} />
- <TabMinimapView key="minimap"
- hideMinimap={this.hideMinimap}
- addDocTab={this.addDocTab}
- PanelHeight={this.PanelHeight}
+ return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? null : (
+ <>
+ <DocumentView
+ key={this._document[Id]}
+ ref={action((r: DocumentView) => {
+ this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
+ this._view = r;
+ this._lastView = this._view;
+ })}
+ renderDepth={0}
+ Document={this._document}
+ DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ onBrowseClick={MainView.Instance.exploreMode}
+ isContentActive={returnTrue}
PanelWidth={this.PanelWidth}
- background={this.miniMapColor}
- document={this._document}
- tabView={this.tabView} />
- <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? "Open minimap" : "Close minimap"}</div>}>
- <div className="miniMap-hidden"
+ PanelHeight={this.PanelHeight}
+ styleProvider={DefaultStyleProvider}
+ docFilters={CollectionDockingView.Instance.childDocFilters}
+ docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
+ searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
+ addDocument={undefined}
+ removeDocument={this.remDocTab}
+ addDocTab={this.addDocTab}
+ ScreenToLocalTransform={this.ScreenToLocalTransform}
+ dontCenter={'y'}
+ rootSelected={returnTrue}
+ whenChildContentsActiveChanged={emptyFunction}
+ focus={this.focusFunc}
+ docViewPath={returnEmptyDoclist}
+ bringToFront={emptyFunction}
+ pinToPres={TabDocView.PinDoc}
+ />
+ <TabMinimapView key="minimap" hideMinimap={this.hideMinimap} addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />
+ <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? 'Open minimap' : 'Close minimap'}</div>}>
+ <div
+ className="miniMap-hidden"
style={{
- display: this.disableMinimap() || this._document._viewType !== "freeform" ? "none" : undefined,
+ display: this.disableMinimap() || this._document._viewType !== 'freeform' ? 'none' : undefined,
color: this._document.hideMinimap ? Colors.BLACK : Colors.WHITE,
backgroundColor: this._document.hideMinimap ? Colors.LIGHT_GRAY : Colors.MEDIUM_BLUE,
- boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined
+ boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined,
}}
onPointerDown={e => e.stopPropagation()}
- onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} >
- <FontAwesomeIcon icon={"globe-asia"} size="lg" />
+ onClick={action(e => {
+ e.stopPropagation();
+ this._document!.hideMinimap = !this._document!.hideMinimap;
+ })}>
+ <FontAwesomeIcon icon={'globe-asia'} size="lg" />
</div>
</Tooltip>
- </>;
+ </>
+ );
}
render() {
return (
- <div className="collectionDockingView-content" style={{
- fontFamily: Doc.UserDoc().renderStyle === "comic" ? "Comic Sans MS" : undefined,
- height: "100%", width: "100%"
- }} ref={ref => {
- if (this._mainCont = ref) {
- if (this._lastTab) {
- this._view && DocumentManager.Instance.RemoveView(this._view);
+ <div
+ className="collectionDockingView-content"
+ style={{
+ fontFamily: Doc.UserDoc().renderStyle === 'comic' ? 'Comic Sans MS' : undefined,
+ height: '100%',
+ width: '100%',
+ }}
+ ref={ref => {
+ if ((this._mainCont = ref)) {
+ if (this._lastTab) {
+ this._view && DocumentManager.Instance.RemoveView(this._view);
+ }
+ this._lastTab = this.tab;
+ (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
+ DocServer.GetRefField(this.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
+ new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
}
- this._lastTab = this.tab;
- (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
- DocServer.GetRefField(this.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
- new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
- }
- }} >
+ }}>
{this.docView}
- </div >
+ </div>
);
}
}
@@ -479,29 +525,38 @@ interface TabMinimapViewProps {
export class TabMinimapView extends React.Component<TabMinimapViewProps> {
static miniStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
if (doc) {
- switch (property.split(":")[0]) {
- default: return DefaultStyleProvider(doc, props, property);
- case StyleProp.PointerEvents: return "none";
+ switch (property.split(':')[0]) {
+ default:
+ return DefaultStyleProvider(doc, props, property);
+ case StyleProp.PointerEvents:
+ return 'none';
case StyleProp.DocContents:
const background = ((type: DocumentType) => {
switch (type) {
- case DocumentType.PDF: return "pink";
- case DocumentType.AUDIO: return "lightgreen";
- case DocumentType.WEB: return "brown";
- case DocumentType.IMG: return "blue";
- case DocumentType.MAP: return "orange";
- case DocumentType.VID: return "purple";
- case DocumentType.RTF: return "yellow";
- case DocumentType.COL: return undefined;
- default: return "gray";
+ case DocumentType.PDF:
+ return 'pink';
+ case DocumentType.AUDIO:
+ return 'lightgreen';
+ case DocumentType.WEB:
+ return 'brown';
+ case DocumentType.IMG:
+ return 'blue';
+ case DocumentType.MAP:
+ return 'orange';
+ case DocumentType.VID:
+ return 'purple';
+ case DocumentType.RTF:
+ return 'yellow';
+ case DocumentType.COL:
+ return undefined;
+ default:
+ return 'gray';
}
})(doc.type as DocumentType);
- return !background ?
- undefined :
- <div style={{ width: doc[WidthSym](), height: doc[HeightSym](), position: "absolute", display: "block", background }} />;
+ return !background ? undefined : <div style={{ width: doc[WidthSym](), height: doc[HeightSym](), position: 'absolute', display: 'block', background }} />;
}
}
- }
+ };
@computed get renderBounds() {
const compView = this.props.tabView()?.ComponentView as CollectionFreeFormView;
const bounds = compView?.freeformData?.(true)?.bounds;
@@ -517,20 +572,27 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
const doc = this.props.document;
const renderBounds = this.renderBounds ?? { l: 0, r: 0, t: 0, b: 0, dim: 1 };
const miniSize = this.returnMiniSize();
- doc && setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
- doc._panX = clamp(NumCast(doc._panX) + delta[0] / miniSize * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
- doc._panY = clamp(NumCast(doc._panY) + delta[1] / miniSize * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
- return false;
- }), emptyFunction, emptyFunction);
- }
+ doc &&
+ setupMoveUpEvents(
+ this,
+ e,
+ action((e: PointerEvent, down: number[], delta: number[]) => {
+ doc._panX = clamp(NumCast(doc._panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
+ doc._panY = clamp(NumCast(doc._panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
+ return false;
+ }),
+ emptyFunction,
+ emptyFunction
+ );
+ };
render() {
- if (!this.renderBounds) return (null);
- const miniWidth = this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim * 100;
- const miniHeight = this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim * 100;
- const miniLeft = 50 + (NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim * 100 - miniWidth / 2;
- const miniTop = 50 + (NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim * 100 - miniHeight / 2;
+ if (!this.renderBounds) return null;
+ const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100;
+ const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100;
+ const miniLeft = 50 + ((NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2;
+ const miniTop = 50 + ((NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2;
const miniSize = this.returnMiniSize();
- return this.props.hideMinimap() ? (null) :
+ return this.props.hideMinimap() ? null : (
<div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
<CollectionFreeFormView
Document={this.props.document}
@@ -567,9 +629,10 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
fitContentsToBox={returnTrue}
/>
- <div className="miniOverlay" onPointerDown={this.miniDown} >
- <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% `, }} />
+ <div className="miniOverlay" onPointerDown={this.miniDown}>
+ <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% ` }} />
</div>
- </div>;
+ </div>
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index b64e9dac1..19401c7f0 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -1,4 +1,5 @@
-@import "../../global/globalCssVariables.scss";
+@import '../../global/globalCssVariables.scss';
+@import '../../../../../node_modules/react-table/react-table.css';
.collectionSchemaView-container {
border-width: $COLLECTION_BORDER_WIDTH;
border-color: $medium-gray;
@@ -218,8 +219,6 @@
}
}
-
-
.collectionSchemaView-header {
height: 100%;
color: gray;
@@ -289,8 +288,6 @@ button.add-column {
}
}
-
-
.keys-dropdown {
position: relative;
//width: 100%;
@@ -300,13 +297,12 @@ button.add-column {
padding: 3px;
height: 28px;
font-weight: bold;
- letter-spacing: "2px";
- text-transform: "uppercase";
+ letter-spacing: '2px';
+ text-transform: 'uppercase';
&:focus {
font-weight: normal;
}
}
-
}
.columnMenu-colors {
display: flex;
@@ -338,7 +334,6 @@ button.add-column {
margin-right: 5px;
font-size: 10px;
border-radius: 3px;
-
}
.keys-options-wrapper {
@@ -348,7 +343,7 @@ button.add-column {
top: 100%;
z-index: 21;
background-color: #ffffff;
- box-shadow: 0px 3px 4px rgba(0,0,0,30%);
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%);
padding: 1px;
.key-option {
cursor: pointer;
@@ -473,8 +468,8 @@ button.add-column {
}
.collectionSchemaView-cellContents-docButton {
float: right;
- width: "15px";
- height: "15px";
+ width: '15px';
+ height: '15px';
}
.collectionSchemaView-dropdownWrapper {
border: grey;
@@ -490,10 +485,10 @@ button.add-column {
display: inline-block;
//float: right;
height: 100%;
- display: "flex";
+ display: 'flex';
font-size: 13;
- justify-content: "center";
- align-items: "center";
+ justify-content: 'center';
+ align-items: 'center';
}
}
.collectionSchemaView-dropdownContainer {
@@ -601,4 +596,4 @@ button.add-column {
font-size: 10.5px;
margin-left: 50px;
margin-top: 10px;
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 9eba788a9..c4ee1805f 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,30 +1,29 @@
-import React = require("react");
+import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, untracked } from "mobx";
-import { observer } from "mobx-react";
-import Measure from "react-measure";
-import { Resize } from "react-table";
-import "react-table/react-table.css";
-import { Doc, Opt } from "../../../../fields/Doc";
-import { List } from "../../../../fields/List";
-import { listSpec } from "../../../../fields/Schema";
-import { PastelSchemaPalette, SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
-import { Cast, NumCast } from "../../../../fields/Types";
-import { TraceMobx } from "../../../../fields/util";
-import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from "../../../../Utils";
-import { DocUtils } from "../../../documents/Documents";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { SnappingManager } from "../../../util/SnappingManager";
-import { Transform } from "../../../util/Transform";
-import { undoBatch } from "../../../util/UndoManager";
-import { ContextMenu } from "../../ContextMenu";
-import { ContextMenuProps } from "../../ContextMenuItem";
+import { action, computed, observable, untracked } from 'mobx';
+import { observer } from 'mobx-react';
+import Measure from 'react-measure';
+import { Resize } from 'react-table';
+import { Doc, Opt } from '../../../../fields/Doc';
+import { List } from '../../../../fields/List';
+import { listSpec } from '../../../../fields/Schema';
+import { PastelSchemaPalette, SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
+import { Cast, NumCast } from '../../../../fields/Types';
+import { TraceMobx } from '../../../../fields/util';
+import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
+import { DocUtils } from '../../../documents/Documents';
+import { SelectionManager } from '../../../util/SelectionManager';
+import { SnappingManager } from '../../../util/SnappingManager';
+import { Transform } from '../../../util/Transform';
+import { undoBatch } from '../../../util/UndoManager';
+import { ContextMenu } from '../../ContextMenu';
+import { ContextMenuProps } from '../../ContextMenuItem';
import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss';
-import { DocumentView } from "../../nodes/DocumentView";
-import { DefaultStyleProvider } from "../../StyleProvider";
-import { CollectionSubView } from "../CollectionSubView";
-import "./CollectionSchemaView.scss";
-import { SchemaTable } from "./SchemaTable";
+import { DocumentView } from '../../nodes/DocumentView';
+import { DefaultStyleProvider } from '../../StyleProvider';
+import { CollectionSubView } from '../CollectionSubView';
+import './CollectionSchemaView.scss';
+import { SchemaTable } from './SchemaTable';
// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
export enum ColumnType {
@@ -35,14 +34,21 @@ export enum ColumnType {
Doc,
Image,
List,
- Date
+ Date,
}
// this map should be used for keys that should have a const type of value
const columnTypes: Map<string, ColumnType> = new Map([
- ["title", ColumnType.String],
- ["x", ColumnType.Number], ["y", ColumnType.Number], ["_width", ColumnType.Number], ["_height", ColumnType.Number],
- ["_nativeWidth", ColumnType.Number], ["_nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean],
- ["_curPage", ColumnType.Number], ["_currentTimecode", ColumnType.Number], ["zIndex", ColumnType.Number]
+ ['title', ColumnType.String],
+ ['x', ColumnType.Number],
+ ['y', ColumnType.Number],
+ ['_width', ColumnType.Number],
+ ['_height', ColumnType.Number],
+ ['_nativeWidth', ColumnType.Number],
+ ['_nativeHeight', ColumnType.Number],
+ ['isPrototype', ColumnType.Boolean],
+ ['_curPage', ColumnType.Number],
+ ['_currentTimecode', ColumnType.Number],
+ ['zIndex', ColumnType.Number],
]);
@observer
@@ -51,7 +57,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _previewDoc: Doc | undefined = undefined;
@observable _focusedTable: Doc = this.props.Document;
- @observable _col: any = "";
+ @observable _col: any = '';
@observable _menuWidth = 0;
@observable _headerOpen = false;
@observable _headerIsEditing = false;
@@ -60,19 +66,33 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _pointerY = 0;
@observable _openTypes: boolean = false;
- @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
- @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
- @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth(); }
- @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
- @computed get scale() { return this.props.ScreenToLocalTransform().Scale; }
- @computed get columns() { return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); }
- set columns(columns: SchemaHeaderField[]) { this.props.Document._schemaHeaders = new List<SchemaHeaderField>(columns); }
+ @computed get previewWidth() {
+ return () => NumCast(this.props.Document.schemaPreviewWidth);
+ }
+ @computed get previewHeight() {
+ return () => this.props.PanelHeight() - 2 * this.borderWidth;
+ }
+ @computed get tableWidth() {
+ return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth();
+ }
+ @computed get borderWidth() {
+ return Number(COLLECTION_BORDER_WIDTH);
+ }
+ @computed get scale() {
+ return this.props.ScreenToLocalTransform().Scale;
+ }
+ @computed get columns() {
+ return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []);
+ }
+ set columns(columns: SchemaHeaderField[]) {
+ this.props.Document._schemaHeaders = new List<SchemaHeaderField>(columns);
+ }
@computed get menuCoordinates() {
let searchx = 0;
let searchy = 0;
if (this.props.Document._searchDoc) {
- const el = document.getElementsByClassName("collectionSchemaView-searchContainer")[0];
+ const el = document.getElementsByClassName('collectionSchemaView-searchContainer')[0];
if (el !== undefined) {
const rect = el.getBoundingClientRect();
searchx = rect.x;
@@ -93,13 +113,13 @@ export class CollectionSchemaView extends CollectionSubView() {
// then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
// is displayed (unlikely) it won't show up until something else changes.
//TODO Types
- untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
+ untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)))));
- this.columns.forEach(key => keys[key.heading] = true);
+ this.columns.forEach(key => (keys[key.heading] = true));
return Array.from(Object.keys(keys));
}
- @action setHeaderIsEditing = (isEditing: boolean) => this._headerIsEditing = isEditing;
+ @action setHeaderIsEditing = (isEditing: boolean) => (this._headerIsEditing = isEditing);
@undoBatch
setColumnType = action((columnField: SchemaHeaderField, type: ColumnType): void => {
@@ -124,7 +144,7 @@ export class CollectionSchemaView extends CollectionSubView() {
columns[index] = columnField;
this.columns = columns; // need to set the columns to trigger rerender
}
- }
+ };
@undoBatch
@action
@@ -137,80 +157,109 @@ export class CollectionSchemaView extends CollectionSubView() {
column.setDesc(descending);
columns[index] = column;
this.columns = columns;
- }
+ };
renderTypes = (col: any) => {
- if (columnTypes.get(col.heading)) return (null);
+ if (columnTypes.get(col.heading)) return null;
const type = col.type;
- const anyType = <div className={"columnMenu-option" + (type === ColumnType.Any ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Any)}>
- <FontAwesomeIcon icon={"align-justify"} size="sm" />
- Any
- </div>;
-
- const numType = <div className={"columnMenu-option" + (type === ColumnType.Number ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Number)}>
- <FontAwesomeIcon icon={"hashtag"} size="sm" />
- Number
- </div>;
-
- const textType = <div className={"columnMenu-option" + (type === ColumnType.String ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.String)}>
- <FontAwesomeIcon icon={"font"} size="sm" />
- Text
- </div>;
-
- const boolType = <div className={"columnMenu-option" + (type === ColumnType.Boolean ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
- <FontAwesomeIcon icon={"check-square"} size="sm" />
- Checkbox
- </div>;
-
- const listType = <div className={"columnMenu-option" + (type === ColumnType.List ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.List)}>
- <FontAwesomeIcon icon={"list-ul"} size="sm" />
- List
- </div>;
-
- const docType = <div className={"columnMenu-option" + (type === ColumnType.Doc ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
- <FontAwesomeIcon icon={"file"} size="sm" />
- Document
- </div>;
-
- const imageType = <div className={"columnMenu-option" + (type === ColumnType.Image ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Image)}>
- <FontAwesomeIcon icon={"image"} size="sm" />
- Image
- </div>;
-
- const dateType = <div className={"columnMenu-option" + (type === ColumnType.Date ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Date)}>
- <FontAwesomeIcon icon={"calendar"} size="sm" />
- Date
- </div>;
-
-
- const allColumnTypes = <div className="columnMenu-types">
- {anyType}
- {numType}
- {textType}
- {boolType}
- {listType}
- {docType}
- {imageType}
- {dateType}
- </div>;
-
- const justColType = type === ColumnType.Any ? anyType : type === ColumnType.Number ? numType :
- type === ColumnType.String ? textType : type === ColumnType.Boolean ? boolType :
- type === ColumnType.List ? listType : type === ColumnType.Doc ? docType :
- type === ColumnType.Date ? dateType : imageType;
+ const anyType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Any ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Any)}>
+ <FontAwesomeIcon icon={'align-justify'} size="sm" />
+ Any
+ </div>
+ );
+
+ const numType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Number ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Number)}>
+ <FontAwesomeIcon icon={'hashtag'} size="sm" />
+ Number
+ </div>
+ );
+
+ const textType = (
+ <div className={'columnMenu-option' + (type === ColumnType.String ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.String)}>
+ <FontAwesomeIcon icon={'font'} size="sm" />
+ Text
+ </div>
+ );
+
+ const boolType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Boolean ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
+ <FontAwesomeIcon icon={'check-square'} size="sm" />
+ Checkbox
+ </div>
+ );
+
+ const listType = (
+ <div className={'columnMenu-option' + (type === ColumnType.List ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.List)}>
+ <FontAwesomeIcon icon={'list-ul'} size="sm" />
+ List
+ </div>
+ );
+
+ const docType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Doc ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
+ <FontAwesomeIcon icon={'file'} size="sm" />
+ Document
+ </div>
+ );
+
+ const imageType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Image ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Image)}>
+ <FontAwesomeIcon icon={'image'} size="sm" />
+ Image
+ </div>
+ );
+
+ const dateType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Date ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Date)}>
+ <FontAwesomeIcon icon={'calendar'} size="sm" />
+ Date
+ </div>
+ );
+
+ const allColumnTypes = (
+ <div className="columnMenu-types">
+ {anyType}
+ {numType}
+ {textType}
+ {boolType}
+ {listType}
+ {docType}
+ {imageType}
+ {dateType}
+ </div>
+ );
+
+ const justColType =
+ type === ColumnType.Any
+ ? anyType
+ : type === ColumnType.Number
+ ? numType
+ : type === ColumnType.String
+ ? textType
+ : type === ColumnType.Boolean
+ ? boolType
+ : type === ColumnType.List
+ ? listType
+ : type === ColumnType.Doc
+ ? docType
+ : type === ColumnType.Date
+ ? dateType
+ : imageType;
return (
- <div className="collectionSchema-headerMenu-group" onClick={action(() => this._openTypes = !this._openTypes)}>
+ <div className="collectionSchema-headerMenu-group" onClick={action(() => (this._openTypes = !this._openTypes))}>
<div>
- <label style={{ cursor: "pointer" }}>Column type:</label>
- <FontAwesomeIcon icon={"caret-down"} size="lg" style={{ float: "right", transform: `rotate(${this._openTypes ? "180deg" : 0})`, transition: "0.2s all ease" }} />
+ <label style={{ cursor: 'pointer' }}>Column type:</label>
+ <FontAwesomeIcon icon={'caret-down'} size="lg" style={{ float: 'right', transform: `rotate(${this._openTypes ? '180deg' : 0})`, transition: '0.2s all ease' }} />
</div>
{this._openTypes ? allColumnTypes : justColType}
- </div >
+ </div>
);
- }
+ };
renderSorting = (col: any) => {
const sort = col.desc;
@@ -218,11 +267,11 @@ export class CollectionSchemaView extends CollectionSubView() {
<div className="collectionSchema-headerMenu-group">
<label>Sort by:</label>
<div className="columnMenu-sort">
- <div className={"columnMenu-option" + (sort === true ? " active" : "")} onClick={() => this.setColumnSort(col, true)}>
+ <div className={'columnMenu-option' + (sort === true ? ' active' : '')} onClick={() => this.setColumnSort(col, true)}>
<FontAwesomeIcon icon="sort-amount-down" size="sm" />
Sort descending
</div>
- <div className={"columnMenu-option" + (sort === false ? " active" : "")} onClick={() => this.setColumnSort(col, false)}>
+ <div className={'columnMenu-option' + (sort === false ? ' active' : '')} onClick={() => this.setColumnSort(col, false)}>
<FontAwesomeIcon icon="sort-amount-up" size="sm" />
Sort ascending
</div>
@@ -233,42 +282,42 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
</div>
);
- }
+ };
renderColors = (col: any) => {
const selected = col.color;
- const pink = PastelSchemaPalette.get("pink2");
- const purple = PastelSchemaPalette.get("purple2");
- const blue = PastelSchemaPalette.get("bluegreen1");
- const yellow = PastelSchemaPalette.get("yellow4");
- const red = PastelSchemaPalette.get("red2");
- const gray = "#f1efeb";
+ const pink = PastelSchemaPalette.get('pink2');
+ const purple = PastelSchemaPalette.get('purple2');
+ const blue = PastelSchemaPalette.get('bluegreen1');
+ const yellow = PastelSchemaPalette.get('yellow4');
+ const red = PastelSchemaPalette.get('red2');
+ const gray = '#f1efeb';
return (
<div className="collectionSchema-headerMenu-group">
<label>Color:</label>
<div className="columnMenu-colors">
- <div className={"columnMenu-colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.setColumnColor(col, pink!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.setColumnColor(col, purple!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.setColumnColor(col, blue!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.setColumnColor(col, yellow!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.setColumnColor(col, red!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.setColumnColor(col, gray)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.setColumnColor(col, pink!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.setColumnColor(col, purple!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.setColumnColor(col, blue!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.setColumnColor(col, yellow!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.setColumnColor(col, red!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.setColumnColor(col, gray)}></div>
</div>
</div>
);
- }
+ };
@undoBatch
@action
changeColumns = (oldKey: string, newKey: string, addNew: boolean, filter?: string) => {
const columns = this.columns;
if (columns === undefined) {
- this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]);
+ this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, 'f1efeb')]);
} else {
if (addNew) {
- columns.push(new SchemaHeaderField(newKey, "f1efeb"));
+ columns.push(new SchemaHeaderField(newKey, 'f1efeb'));
this.columns = columns;
} else {
const index = columns.map(c => c.heading).indexOf(oldKey);
@@ -278,15 +327,14 @@ export class CollectionSchemaView extends CollectionSubView() {
columns[index] = column;
this.columns = columns;
if (filter) {
- Doc.setDocFilter(this.props.Document, newKey, filter, "match");
- }
- else {
+ Doc.setDocFilter(this.props.Document, newKey, filter, 'match');
+ } else {
this.props.Document._docFilters = undefined;
}
}
}
}
- }
+ };
@action
openHeader = (col: any, screenx: number, screeny: number) => {
@@ -294,10 +342,12 @@ export class CollectionSchemaView extends CollectionSubView() {
this._headerOpen = true;
this._pointerX = screenx;
this._pointerY = screeny;
- }
+ };
@action
- closeHeader = () => { this._headerOpen = false; }
+ closeHeader = () => {
+ this._headerOpen = false;
+ };
@undoBatch
@action
@@ -313,16 +363,16 @@ export class CollectionSchemaView extends CollectionSubView() {
}
}
this.closeHeader();
- }
+ };
getPreviewTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(- this.borderWidth - NumCast(COLLECTION_BORDER_WIDTH) - this.tableWidth, - this.borderWidth);
- }
+ return this.props.ScreenToLocalTransform().translate(-this.borderWidth - NumCast(COLLECTION_BORDER_WIDTH) - this.tableWidth, -this.borderWidth);
+ };
@action
onHeaderClick = (e: React.PointerEvent) => {
e.stopPropagation();
- }
+ };
@action
onWheel(e: React.WheelEvent) {
@@ -332,40 +382,45 @@ export class CollectionSchemaView extends CollectionSubView() {
@computed get renderMenuContent() {
TraceMobx();
- return <div className="collectionSchema-header-menuOptions">
- {this.renderTypes(this._col)}
- {this.renderColors(this._col)}
- <div className="collectionSchema-headerMenu-group">
- <button onClick={() => { this.deleteColumn(this._col.heading); }}>
- Hide Column
- </button>
+ return (
+ <div className="collectionSchema-header-menuOptions">
+ {this.renderTypes(this._col)}
+ {this.renderColors(this._col)}
+ <div className="collectionSchema-headerMenu-group">
+ <button
+ onClick={() => {
+ this.deleteColumn(this._col.heading);
+ }}>
+ Hide Column
+ </button>
+ </div>
</div>
- </div>;
+ );
}
private createTarget = (ele: HTMLDivElement) => {
this._previewCont = ele;
super.CreateDropTarget(ele);
- }
+ };
isFocused = (doc: Doc, outsideReaction: boolean): boolean => this.props.isSelected(outsideReaction) && doc === this._focusedTable;
- @action setFocused = (doc: Doc) => this._focusedTable = doc;
+ @action setFocused = (doc: Doc) => (this._focusedTable = doc);
@action setPreviewDoc = (doc: Opt<Doc>) => {
SelectionManager.SelectSchemaViewDoc(doc);
this._previewDoc = doc;
- }
+ };
//toggles preview side-panel of schema
@action
toggleExpander = () => {
this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0;
- }
+ };
onDividerDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, this.toggleExpander);
- }
+ };
@action
onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
const nativeWidth = this._previewCont!.getBoundingClientRect();
@@ -375,136 +430,146 @@ export class CollectionSchemaView extends CollectionSubView() {
const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
this.props.Document.schemaPreviewWidth = width;
return false;
- }
+ };
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
if (this.props.isSelected(true)) e.stopPropagation();
else this.props.select(false);
}
- }
+ };
@computed
- get previewDocument(): Doc | undefined { return this._previewDoc; }
+ get previewDocument(): Doc | undefined {
+ return this._previewDoc;
+ }
@computed
get dividerDragger() {
- return this.previewWidth() === 0 ? (null) :
- <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} >
+ return this.previewWidth() === 0 ? null : (
+ <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown}>
<div className="collectionSchemaView-dividerDragger" />
- </div>;
+ </div>
+ );
}
@computed
get previewPanel() {
- return <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
- {!this.previewDocument ? (null) :
- <DocumentView
- Document={this.previewDocument}
- DataDoc={undefined}
- fitContentsToBox={returnTrue}
- dontCenter={"y"}
- focus={DocUtils.DefaultFocus}
- renderDepth={this.props.renderDepth}
- rootSelected={this.rootSelected}
- PanelWidth={this.previewWidth}
- PanelHeight={this.previewHeight}
- isContentActive={returnTrue}
- isDocumentActive={returnFalse}
- ScreenToLocalTransform={this.getPreviewTransform}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- styleProvider={DefaultStyleProvider}
- docViewPath={returnEmptyDoclist}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- moveDocument={this.props.moveDocument}
- addDocument={this.props.addDocument}
- removeDocument={this.props.removeDocument}
- whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}
- />}
- </div>;
+ return (
+ <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
+ {!this.previewDocument ? null : (
+ <DocumentView
+ Document={this.previewDocument}
+ DataDoc={undefined}
+ fitContentsToBox={returnTrue}
+ dontCenter={'y'}
+ focus={DocUtils.DefaultFocus}
+ renderDepth={this.props.renderDepth}
+ rootSelected={this.rootSelected}
+ PanelWidth={this.previewWidth}
+ PanelHeight={this.previewHeight}
+ isContentActive={returnTrue}
+ isDocumentActive={returnFalse}
+ ScreenToLocalTransform={this.getPreviewTransform}
+ docFilters={this.childDocFilters}
+ docRangeFilters={this.childDocRangeFilters}
+ searchFilterDocs={this.searchFilterDocs}
+ styleProvider={DefaultStyleProvider}
+ docViewPath={returnEmptyDoclist}
+ ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+ ContainingCollectionView={this.props.CollectionView}
+ moveDocument={this.props.moveDocument}
+ addDocument={this.props.addDocument}
+ removeDocument={this.props.removeDocument}
+ whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ bringToFront={returnFalse}
+ />
+ )}
+ </div>
+ );
}
@computed
get schemaTable() {
- return <SchemaTable
- Document={this.props.Document}
- PanelHeight={this.props.PanelHeight}
- PanelWidth={this.props.PanelWidth}
- childDocs={this.childDocs}
- CollectionView={this.props.CollectionView}
- ContainingCollectionView={this.props.ContainingCollectionView}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc}
- fieldKey={this.props.fieldKey}
- renderDepth={this.props.renderDepth}
- moveDocument={this.props.moveDocument}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform}
- active={this.props.isContentActive}
- onDrop={this.onExternalDrop}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- isSelected={this.props.isSelected}
- isFocused={this.isFocused}
- setFocused={this.setFocused}
- setPreviewDoc={this.setPreviewDoc}
- deleteDocument={this.props.removeDocument}
- addDocument={this.props.addDocument}
- dataDoc={this.props.DataDoc}
- columns={this.columns}
- documentKeys={this.documentKeys}
- headerIsEditing={this._headerIsEditing}
- openHeader={this.openHeader}
- onClick={this.onTableClick}
- onPointerDown={emptyFunction}
- onResizedChange={this.onResizedChange}
- setColumns={this.setColumns}
- reorderColumns={this.reorderColumns}
- changeColumns={this.changeColumns}
- setHeaderIsEditing={this.setHeaderIsEditing}
- changeColumnSort={this.setColumnSort}
- />;
+ return (
+ <SchemaTable
+ Document={this.props.Document}
+ PanelHeight={this.props.PanelHeight}
+ PanelWidth={this.props.PanelWidth}
+ childDocs={this.childDocs}
+ CollectionView={this.props.CollectionView}
+ ContainingCollectionView={this.props.ContainingCollectionView}
+ ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+ fieldKey={this.props.fieldKey}
+ renderDepth={this.props.renderDepth}
+ moveDocument={this.props.moveDocument}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+ active={this.props.isContentActive}
+ onDrop={this.onExternalDrop}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ isSelected={this.props.isSelected}
+ isFocused={this.isFocused}
+ setFocused={this.setFocused}
+ setPreviewDoc={this.setPreviewDoc}
+ deleteDocument={this.props.removeDocument}
+ addDocument={this.props.addDocument}
+ dataDoc={this.props.DataDoc}
+ columns={this.columns}
+ documentKeys={this.documentKeys}
+ headerIsEditing={this._headerIsEditing}
+ openHeader={this.openHeader}
+ onClick={this.onTableClick}
+ onPointerDown={emptyFunction}
+ onResizedChange={this.onResizedChange}
+ setColumns={this.setColumns}
+ reorderColumns={this.reorderColumns}
+ changeColumns={this.changeColumns}
+ setHeaderIsEditing={this.setHeaderIsEditing}
+ changeColumnSort={this.setColumnSort}
+ />
+ );
}
@computed
public get schemaToolbar() {
- return <div className="collectionSchemaView-toolbar">
- <div className="collectionSchemaView-toolbar-item">
- <div id="preview-schema-checkbox-div">
- <input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />
- Show Preview
+ return (
+ <div className="collectionSchemaView-toolbar">
+ <div className="collectionSchemaView-toolbar-item">
+ <div id="preview-schema-checkbox-div">
+ <input type="checkbox" key={'Show Preview'} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />
+ Show Preview
+ </div>
</div>
</div>
- </div>;
+ );
}
onSpecificMenu = (e: React.MouseEvent) => {
- if ((e.target as any)?.className?.includes?.("collectionSchemaView-cell") || (e.target instanceof HTMLSpanElement)) {
+ if ((e.target as any)?.className?.includes?.('collectionSchemaView-cell') || e.target instanceof HTMLSpanElement) {
const cm = ContextMenu.Instance;
- const options = cm.findByDescription("Options...");
- const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
- optionItems.push({ description: "remove", event: () => this._previewDoc && this.props.removeDocument?.(this._previewDoc), icon: "trash" });
- !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
+ const options = cm.findByDescription('Options...');
+ const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
+ optionItems.push({ description: 'remove', event: () => this._previewDoc && this.props.removeDocument?.(this._previewDoc), icon: 'trash' });
+ !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
cm.displayMenu(e.clientX, e.clientY);
(e.nativeEvent as any).SchemaHandled = true; // not sure why this is needed, but if you right-click quickly on a cell, the Document/Collection contextMenu handlers still fire without this.
e.stopPropagation();
}
- }
+ };
@action
onTableClick = (e: React.MouseEvent): void => {
- if (!(e.target as any)?.className?.includes?.("collectionSchemaView-cell") && !(e.target instanceof HTMLSpanElement)) {
+ if (!(e.target as any)?.className?.includes?.('collectionSchemaView-cell') && !(e.target instanceof HTMLSpanElement)) {
this.setPreviewDoc(undefined);
} else {
e.stopPropagation();
}
this.setFocused(this.props.Document);
this.closeHeader();
- }
+ };
onResizedChange = (newResized: Resize[], event: any) => {
const columns = this.columns;
@@ -515,23 +580,23 @@ export class CollectionSchemaView extends CollectionSubView() {
columns[index] = column;
});
this.columns = columns;
- }
+ };
@action
- setColumns = (columns: SchemaHeaderField[]) => this.columns = columns
+ setColumns = (columns: SchemaHeaderField[]) => (this.columns = columns);
@undoBatch
reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => {
const columns = [...columnsValues];
const oldIndex = columns.indexOf(toMove);
const relIndex = columns.indexOf(relativeTo);
- const newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
+ const newIndex = oldIndex > relIndex && !before ? relIndex + 1 : oldIndex < relIndex && before ? relIndex - 1 : relIndex;
if (oldIndex === newIndex) return;
columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
this.columns = columns;
- }
+ };
onZoomMenu = (e: React.WheelEvent) => this.props.isContentActive(true) && e.stopPropagation();
@@ -539,35 +604,44 @@ export class CollectionSchemaView extends CollectionSubView() {
TraceMobx();
if (!this.props.isContentActive()) setTimeout(() => this.closeHeader(), 0);
const menuContent = this.renderMenuContent;
- const menu = <div className="collectionSchema-header-menu"
- onWheel={e => this.onZoomMenu(e)}
- onPointerDown={e => this.onHeaderClick(e)}
- style={{ transform: `translate(${(this.menuCoordinates[0])}px, ${(this.menuCoordinates[1])}px)` }}>
- <Measure offset onResize={action((r: any) => {
- const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
- this._menuWidth = dim[0]; this._menuHeight = dim[1];
- })}>
- {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
- </Measure>
- </div>;
- return <div className={"collectionSchemaView" + (this.props.Document._searchDoc ? "-searchContainer" : "-container")}
- style={{
- overflow: this.props.scrollOverflow === true ? "scroll" : undefined, backgroundColor: "white",
- pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined,
- width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
- }} >
- <div className="collectionSchemaView-tableContainer"
- style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
- onContextMenu={this.onSpecificMenu}
- onPointerDown={this.onPointerDown}
- onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}
- onDrop={e => this.onExternalDrop(e, {})}
- ref={this.createTarget}>
- {this.schemaTable}
+ const menu = (
+ <div className="collectionSchema-header-menu" onWheel={e => this.onZoomMenu(e)} onPointerDown={e => this.onHeaderClick(e)} style={{ transform: `translate(${this.menuCoordinates[0]}px, ${this.menuCoordinates[1]}px)` }}>
+ <Measure
+ offset
+ onResize={action((r: any) => {
+ const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
+ this._menuWidth = dim[0];
+ this._menuHeight = dim[1];
+ })}>
+ {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
+ </Measure>
</div>
- {this.dividerDragger}
- {!this.previewWidth() ? (null) : this.previewPanel}
- {this._headerOpen && this.props.isContentActive() ? menu : null}
- </div>;
+ );
+ return (
+ <div
+ className={'collectionSchemaView' + (this.props.Document._searchDoc ? '-searchContainer' : '-container')}
+ style={{
+ overflow: this.props.scrollOverflow === true ? 'scroll' : undefined,
+ backgroundColor: 'white',
+ pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined,
+ width: this.props.PanelWidth() || '100%',
+ height: this.props.PanelHeight() || '100%',
+ position: 'relative',
+ }}>
+ <div
+ className="collectionSchemaView-tableContainer"
+ style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
+ onContextMenu={this.onSpecificMenu}
+ onPointerDown={this.onPointerDown}
+ onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}
+ onDrop={e => this.onExternalDrop(e, {})}
+ ref={this.createTarget}>
+ {this.schemaTable}
+ </div>
+ {this.dividerDragger}
+ {!this.previewWidth() ? null : this.previewPanel}
+ {this._headerOpen && this.props.isContentActive() ? menu : null}
+ </div>
+ );
}
-} \ No newline at end of file
+}