aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/ContextMenu.tsx30
-rw-r--r--src/client/views/ContextMenuItem.tsx27
-rw-r--r--src/client/views/DashboardView.tsx62
-rw-r--r--src/client/views/DocComponent.tsx51
-rw-r--r--src/client/views/DocumentButtonBar.tsx18
-rw-r--r--src/client/views/DocumentDecorations.tsx98
-rw-r--r--src/client/views/FilterPanel.tsx162
-rw-r--r--src/client/views/GestureOverlay.tsx214
-rw-r--r--src/client/views/GlobalKeyHandler.ts73
-rw-r--r--src/client/views/InkControlPtHandles.tsx2
-rw-r--r--src/client/views/InkTangentHandles.tsx3
-rw-r--r--src/client/views/InkingStroke.tsx15
-rw-r--r--src/client/views/LightboxView.tsx9
-rw-r--r--src/client/views/MainView.tsx132
-rw-r--r--src/client/views/MainViewModal.tsx4
-rw-r--r--src/client/views/MarqueeAnnotator.tsx2
-rw-r--r--src/client/views/MetadataEntryMenu.tsx9
-rw-r--r--src/client/views/ObservableReactComponent.tsx7
-rw-r--r--src/client/views/OverlayView.tsx37
-rw-r--r--src/client/views/PreviewCursor.tsx2
-rw-r--r--src/client/views/PropertiesButtons.tsx8
-rw-r--r--src/client/views/PropertiesView.tsx1062
-rw-r--r--src/client/views/ScriptBox.tsx2
-rw-r--r--src/client/views/SidebarAnnos.tsx13
-rw-r--r--src/client/views/StyleProvider.tsx23
-rw-r--r--src/client/views/TemplateMenu.tsx70
-rw-r--r--src/client/views/Touchable.tsx213
-rw-r--r--src/client/views/animationtimeline/Timeline.tsx3
-rw-r--r--src/client/views/animationtimeline/TimelineMenu.tsx25
-rw-r--r--src/client/views/collections/CollectionCalendarView.tsx3
-rw-r--r--src/client/views/collections/CollectionCarousel3DView.tsx97
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx5
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx156
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx3
-rw-r--r--src/client/views/collections/CollectionMenu.tsx38
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx15
-rw-r--r--src/client/views/collections/CollectionNoteTakingViewColumn.tsx2
-rw-r--r--src/client/views/collections/CollectionNoteTakingViewDivider.tsx3
-rw-r--r--src/client/views/collections/CollectionPileView.tsx5
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx3
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx79
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx80
-rw-r--r--src/client/views/collections/CollectionSubView.tsx173
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx5
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx6
-rw-r--r--src/client/views/collections/CollectionView.tsx75
-rw-r--r--src/client/views/collections/TabDocView.tsx69
-rw-r--r--src/client/views/collections/TreeView.tsx307
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx31
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx18
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx18
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx122
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx50
-rw-r--r--src/client/views/collections/collectionGrid/CollectionGridView.tsx3
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx66
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx24
-rw-r--r--src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx3
-rw-r--r--src/client/views/collections/collectionSchema/SchemaRowBox.tsx3
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx12
-rw-r--r--src/client/views/global/globalScripts.ts137
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx6
-rw-r--r--src/client/views/linking/LinkPopup.tsx3
-rw-r--r--src/client/views/newlightbox/NewLightboxView.tsx3
-rw-r--r--src/client/views/nodes/AudioBox.tsx106
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx9
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx54
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx10
-rw-r--r--src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx5
-rw-r--r--src/client/views/nodes/DataVizBox/components/Histogram.tsx26
-rw-r--r--src/client/views/nodes/DataVizBox/components/LineChart.tsx80
-rw-r--r--src/client/views/nodes/DataVizBox/components/PieChart.tsx24
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx5
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx5
-rw-r--r--src/client/views/nodes/DocumentIcon.tsx63
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx9
-rw-r--r--src/client/views/nodes/DocumentView.tsx282
-rw-r--r--src/client/views/nodes/EquationBox.tsx2
-rw-r--r--src/client/views/nodes/FieldView.tsx10
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx5
-rw-r--r--src/client/views/nodes/FunctionPlotBox.tsx10
-rw-r--r--src/client/views/nodes/ImageBox.tsx117
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx10
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx3
-rw-r--r--src/client/views/nodes/LabelBox.tsx10
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx15
-rw-r--r--src/client/views/nodes/LinkBox.tsx3
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx3
-rw-r--r--src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx3
-rw-r--r--src/client/views/nodes/MapBox/MapAnchorMenu.tsx3
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx11
-rw-r--r--src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx76
-rw-r--r--src/client/views/nodes/PDFBox.tsx31
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingBox.tsx15
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingView.tsx2
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx17
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx2
-rw-r--r--src/client/views/nodes/VideoBox.tsx21
-rw-r--r--src/client/views/nodes/WebBox.tsx38
-rw-r--r--src/client/views/nodes/calendarBox/CalendarBox.tsx2
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx3
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx8
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx137
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx7
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts60
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx2
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts121
-rw-r--r--src/client/views/nodes/formattedText/marks_rts.ts7
-rw-r--r--src/client/views/nodes/formattedText/nodes_rts.ts4
-rw-r--r--src/client/views/nodes/generativeFill/GenerativeFill.tsx91
-rw-r--r--src/client/views/nodes/importBox/ImportElementBox.tsx2
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx176
-rw-r--r--src/client/views/nodes/trails/PresElementBox.tsx3
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx22
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx100
-rw-r--r--src/client/views/pdf/PDFViewer.tsx21
-rw-r--r--src/client/views/search/SearchBox.tsx4
-rw-r--r--src/client/views/topbar/TopBar.tsx5
118 files changed, 3069 insertions, 2796 deletions
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index ca877b93e..18b433a77 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -1,16 +1,16 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { StrCast } from '../../fields/Types';
-import { SettingsManager } from '../util/SettingsManager';
+import { DivHeight, DivWidth } from '../../ClientUtils';
+import { SnappingManager } from '../util/SnappingManager';
import './ContextMenu.scss';
import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem';
import { ObservableReactComponent } from './ObservableReactComponent';
-import { DivHeight, DivWidth } from '../../Utils';
@observer
export class ContextMenu extends ObservableReactComponent<{}> {
+ // eslint-disable-next-line no-use-before-define
static Instance: ContextMenu;
private _ignoreUp = false;
@@ -124,8 +124,8 @@ export class ContextMenu extends ObservableReactComponent<{}> {
@action
displayMenu = (x: number, y: number, initSearch = '', showSearch = false, onDisplay?: () => void) => {
- //maxX and maxY will change if the UI/font size changes, but will work for any amount
- //of items added to the menu
+ // maxX and maxY will change if the UI/font size changes, but will work for any amount
+ // of items added to the menu
this._showSearch = showSearch;
this._pageX = x;
@@ -192,7 +192,7 @@ export class ContextMenu extends ObservableReactComponent<{}> {
key={index + value.join(' -> ')}
className="contextMenu-group"
style={{
- background: StrCast(SettingsManager.userVariantColor),
+ background: SnappingManager.userVariantColor,
}}>
<div className="contextMenu-description">{value.join(' -> ')}</div>
</div>
@@ -224,11 +224,11 @@ export class ContextMenu extends ObservableReactComponent<{}> {
display: this._display ? '' : 'none',
left: this.pageX,
...(this._yRelativeToTop ? { top: Math.max(0, this.pageY) } : { bottom: this.pageY }),
- background: SettingsManager.userBackgroundColor,
- color: SettingsManager.userColor,
+ background: SnappingManager.userBackgroundColor,
+ color: SnappingManager.userColor,
}}>
{!this.itemsNeedSearch ? null : (
- <span className={'search-icon'}>
+ <span className="search-icon">
<span className="icon-background">
<FontAwesomeIcon icon="search" size="lg" />
</span>
@@ -267,7 +267,7 @@ export class ContextMenu extends ObservableReactComponent<{}> {
if (item) {
item.event({ x: this.pageX, y: this.pageY });
} else {
- //if (this._searchString.startsWith(this._defaultPrefix)) {
+ // if (this._searchString.startsWith(this._defaultPrefix)) {
this._defaultItem?.(this._searchString.substring(this._defaultPrefix.length));
}
this.closeMenu();
@@ -281,12 +281,10 @@ export class ContextMenu extends ObservableReactComponent<{}> {
this._searchString = e.target.value;
if (!this._searchString) {
this._selectedIndex = -1;
+ } else if (this._selectedIndex === -1) {
+ this._selectedIndex = 0;
} else {
- if (this._selectedIndex === -1) {
- this._selectedIndex = 0;
- } else {
- this._selectedIndex = Math.min(this.flatItems.length - 1, this._selectedIndex);
- }
+ this._selectedIndex = Math.min(this.flatItems.length - 1, this._selectedIndex);
}
};
}
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index d15ab749c..5760872fb 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -1,17 +1,17 @@
-import * as React from 'react';
-import { observable, action, runInAction, makeObservable } from 'mobx';
-import { observer } from 'mobx-react';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, makeObservable, observable, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
-import { SettingsManager } from '../util/SettingsManager';
import { ObservableReactComponent } from './ObservableReactComponent';
export interface OriginalMenuProps {
description: string;
event: (stuff?: any) => void;
undoable?: boolean;
- icon: IconProp | JSX.Element; //maybe should be optional (icon?)
+ icon: IconProp | JSX.Element; // maybe should be optional (icon?)
closeMenu?: () => void;
}
@@ -20,7 +20,7 @@ export interface SubmenuProps {
subitems: ContextMenuProps[];
noexpand?: boolean;
addDivider?: boolean;
- icon: IconProp; //maybe should be optional (icon?)
+ icon: IconProp; // maybe should be optional (icon?)
closeMenu?: () => void;
}
@@ -67,7 +67,9 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
this._overPosY = e.clientY;
this._overPosX = e.clientX;
this.currentTimeout = setTimeout(
- action(() => (this.overItem = true)),
+ action(() => {
+ this.overItem = true;
+ }),
ContextMenuItem.timeout
);
};
@@ -97,14 +99,15 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
{this._props.icon ? <span className="contextMenu-item-icon-background">{this.isJSXElement(this._props.icon) ? this._props.icon : <FontAwesomeIcon icon={this._props.icon} size="sm" />}</span> : null}
<div className="contextMenu-description">{this._props.description.replace(':', '')}</div>
<div
- className={`contextMenu-item-background`}
+ className="contextMenu-item-background"
style={{
- background: SettingsManager.userColor,
+ background: SnappingManager.userColor,
}}
/>
</div>
);
- } else if ('subitems' in this._props) {
+ }
+ if ('subitems' in this._props) {
const where = !this.overItem ? '' : this._overPosY < window.innerHeight / 3 ? 'flex-start' : this._overPosY > (window.innerHeight * 2) / 3 ? 'flex-end' : 'center';
const marginTop = !this.overItem ? '' : this._overPosY < window.innerHeight / 3 ? '20px' : this._overPosY > (window.innerHeight * 2) / 3 ? '-20px' : '';
@@ -115,7 +118,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
style={{
marginLeft: window.innerWidth - this._overPosX - 50 > 0 ? '90%' : '20%',
marginTop,
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
}}>
{this._items.map(prop => (
<ContextMenuItem {...prop} key={prop.description} closeMenu={this._props.closeMenu} />
@@ -149,7 +152,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
<div
className={`contextMenu-item-background`}
style={{
- background: SettingsManager.userColor,
+ background: SnappingManager.userColor,
}}
/>
{submenu}
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index a4f598d1a..1d286c987 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -4,6 +4,7 @@ import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { FaPlus } from 'react-icons/fa';
+import { ClientUtils } from '../../ClientUtils';
import { Doc, DocListCast } from '../../fields/Doc';
import { AclPrivate, DocAcl, DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
@@ -14,21 +15,19 @@ import { ScriptField } from '../../fields/ScriptField';
import { Cast, ImageCast, StrCast } from '../../fields/Types';
import { normalizeEmail } from '../../fields/util';
import { DocServer } from '../DocServer';
-import { Docs, DocumentOptions, DocUtils } from '../documents/Documents';
+import { DocUtils, Docs, DocumentOptions } from '../documents/Documents';
+import { dropActionType } from '../util/DropActionTypes';
import { HistoryUtil } from '../util/History';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
-import { SettingsManager } from '../util/SettingsManager';
import { SharingManager } from '../util/SharingManager';
-import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
-import { CollectionDockingView } from './collections/CollectionDockingView';
-import { CollectionView } from './collections/CollectionView';
+import { SnappingManager } from '../util/SnappingManager';
+import { undoBatch, undoable } from '../util/UndoManager';
import { ContextMenu } from './ContextMenu';
import './DashboardView.scss';
-import { Colors } from './global/globalEnums';
import { MainViewModal } from './MainViewModal';
-import { ButtonType } from './nodes/FontIconBox/FontIconBox';
import { ObservableReactComponent } from './ObservableReactComponent';
-import { dropActionType } from '../util/DragManager';
+import { Colors } from './global/globalEnums';
+import { ButtonType } from './nodes/FontIconBox/FontIconBox';
enum DashboardGroup {
MyDashboards,
@@ -65,7 +64,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
getDashboards = (whichGroup: DashboardGroup) => {
if (whichGroup === DashboardGroup.MyDashboards) {
- return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard[DocData].author === Doc.CurrentUserEmail);
+ return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard[DocData].author === ClientUtils.CurrentUserEmail);
}
return DocListCast(Doc.MySharedDocs.data_dashboards).filter(doc => doc.dockingConfig);
};
@@ -84,11 +83,11 @@ export class DashboardView extends ObservableReactComponent<{}> {
<div
className="new-dashboard"
style={{
- background: SettingsManager.userBackgroundColor,
- color: SettingsManager.userColor,
+ background: SnappingManager.userBackgroundColor,
+ color: SnappingManager.userColor,
}}>
<div className="header">Create New Dashboard</div>
- <EditableText formLabel="Title" placeholder={this.newDashboardName} type={Type.SEC} color={SettingsManager.userColor} setVal={val => this.setNewDashboardName(val as string)} fillWidth />
+ <EditableText formLabel="Title" placeholder={this.newDashboardName} type={Type.SEC} color={SnappingManager.userColor} setVal={val => this.setNewDashboardName(val as string)} fillWidth />
<ColorPicker
formLabel="Background" //
colorPickerType="github"
@@ -98,8 +97,8 @@ export class DashboardView extends ObservableReactComponent<{}> {
setSelectedColor={this.setNewDashboardColor}
/>
<div className="button-bar">
- <Button text="Cancel" color={SettingsManager.userColor} onClick={this.abortCreateNewDashboard} />
- <Button text="Create" color={SettingsManager.userVariantColor} type={Type.TERT} onClick={() => this.createNewDashboard(this.newDashboardName, this.newDashboardColor)} />
+ <Button text="Cancel" color={SnappingManager.userColor} onClick={this.abortCreateNewDashboard} />
+ <Button text="Create" color={SnappingManager.userVariantColor} type={Type.TERT} onClick={() => this.createNewDashboard(this.newDashboardName, this.newDashboardColor)} />
</div>
</div>
);
@@ -133,8 +132,8 @@ export class DashboardView extends ObservableReactComponent<{}> {
};
render() {
- const color = SettingsManager.userColor;
- const variant = SettingsManager.userVariantColor;
+ const color = SnappingManager.userColor;
+ const variant = SnappingManager.userVariantColor;
return (
<>
<div className="dashboard-view">
@@ -156,7 +155,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
: this.getDashboards(this.selectedDashboardGroup).map(dashboard => {
const href = ImageCast(dashboard.thumb)?.url?.href;
const shared = Object.keys(dashboard[DocAcl])
- .filter(key => key !== `acl-${normalizeEmail(Doc.CurrentUserEmail)}` && !['acl-Me', 'acl-Guest'].includes(key))
+ .filter(key => key !== `acl-${normalizeEmail(ClientUtils.CurrentUserEmail)}` && !['acl-Me', 'acl-Guest'].includes(key))
.some(key => dashboard[DocAcl][key] !== AclPrivate);
return (
<div
@@ -187,7 +186,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
<div
className="background"
style={{
- background: SettingsManager.userColor,
+ background: SnappingManager.userColor,
filter: 'opacity(0.2)',
}}
/>
@@ -201,7 +200,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
<div
className="background"
style={{
- background: SettingsManager.userColor,
+ background: SnappingManager.userColor,
filter: 'opacity(0.2)',
}}
/>
@@ -217,9 +216,6 @@ export class DashboardView extends ObservableReactComponent<{}> {
public static closeActiveDashboard() {
Doc.ActiveDashboard = undefined;
}
- public static snapshotDashboard() {
- return CollectionDockingView.TakeSnapshot(Doc.ActiveDashboard);
- }
public static openSharedDashboard = (dashboard: Doc) => {
Doc.AddDocToList(Doc.MySharedDocs, 'viewed', dashboard);
@@ -250,16 +246,16 @@ export class DashboardView extends ObservableReactComponent<{}> {
});
if (state.readonly === true || state.readonly === null) {
DocServer.Control.makeReadOnly();
- } else if (state.safe) {
- if (!state.nro) {
- DocServer.Control.makeReadOnly();
- }
- CollectionView.SetSafeMode(true);
+ // } else if (state.safe) {
+ // if (!state.nro) {
+ // DocServer.Control.makeReadOnly();
+ // }
+ // CollectionView.SetSafeMode(true);
} else if (state.nro || state.nro === null || state.readonly === false) {
} else if (doc.readOnly) {
DocServer.Control.makeReadOnly();
} else {
- Doc.CurrentUserEmail !== 'guest' && DocServer.Control.makeEditable();
+ ClientUtils.CurrentUserEmail !== 'guest' && DocServer.Control.makeEditable();
}
}
@@ -473,23 +469,23 @@ export class DashboardView extends ObservableReactComponent<{}> {
}
}
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function createNewDashboard() {
return DashboardView.createNewDashboard();
}, 'creates a new dashboard when called');
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function shareDashboard(dashboard: Doc) {
SharingManager.Instance.open(undefined, dashboard);
}, 'opens sharing dialog for Dashboard');
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function removeDashboard(dashboard: Doc) {
DashboardView.removeDashboard(dashboard);
}, 'Remove Dashboard from Dashboards');
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function resetDashboard(dashboard: Doc) {
DashboardView.resetDashboard(dashboard);
}, 'move all dashboard tabs to single stack');
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function addToDashboards(dashboard: Doc) {
DashboardView.openDashboard(Doc.MakeEmbedding(dashboard));
}, 'adds Dashboard to set of Dashboards');
-ScriptingGlobals.add(async function snapshotDashboard() {
- const batch = UndoManager.StartBatch('snapshot');
- await DashboardView.snapshotDashboard();
- batch.end();
-}, 'creates a snapshot copy of a dashboard');
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index de4df1830..348b18129 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -1,22 +1,52 @@
import { action, computed, makeObservable, observable } from 'mobx';
import * as React from 'react';
-import { returnFalse } from '../../Utils';
+import { returnFalse } from '../../ClientUtils';
import { DateField } from '../../fields/DateField';
-import { Doc, DocListCast, Field, Opt } from '../../fields/Doc';
-import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols';
+import { Doc, DocListCast, FieldType, Opt } from '../../fields/Doc';
+import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData, DocViews } from '../../fields/DocSymbols';
import { List } from '../../fields/List';
import { RefField } from '../../fields/RefField';
import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util';
import { DocumentType } from '../documents/DocumentTypes';
-import { DocUtils } from '../documents/Documents';
-import { DocumentManager } from '../util/DocumentManager';
import { DragManager } from '../util/DragManager';
import { ObservableReactComponent } from './ObservableReactComponent';
-import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { DocumentView, OpenWhere } from './nodes/DocumentView';
import { FieldViewProps, FocusViewOptions } from './nodes/FieldView';
-import { PinProps } from './nodes/trails';
+// import { DocUtils } from '../documents/Documents';
+export interface pinDataTypes {
+ scrollable?: boolean;
+ dataviz?: number[];
+ pannable?: boolean;
+ type_collection?: boolean;
+ inkable?: boolean;
+ filters?: boolean;
+ pivot?: boolean;
+ temporal?: boolean;
+ clippable?: boolean;
+ datarange?: boolean;
+ dataview?: boolean;
+ poslayoutview?: boolean;
+ dataannos?: boolean;
+ map?: boolean;
+}
+
+export interface MarqueeViewBounds {
+ left: number;
+ top: number;
+ width: number;
+ height: number;
+}
+export interface PinProps {
+ audioRange?: boolean;
+ activeFrame?: number;
+ currentFrame?: number;
+ hidePresBox?: boolean;
+ pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected)
+ pinDocLayout?: boolean; // pin layout info (width/height/x/y)
+ pinAudioPlay?: boolean; // pin audio annotation
+ pinData?: pinDataTypes;
+}
/**
* Shared interface among all viewBox'es (ie, react classes that render the contents of a Doc)
* Many of these methods only make sense for specific viewBox'es, but they should be written to
@@ -25,6 +55,7 @@ import { PinProps } from './nodes/trails';
export interface ViewBoxInterface {
fieldKey?: string;
annotationKey?: string;
+ promoteCollection?: () => void; // moves contents of collection to parent
updateIcon?: () => void; // updates the icon representation of the document
getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
restoreView?: (viewSpec: Doc) => boolean;
@@ -46,7 +77,7 @@ export interface ViewBoxInterface {
IsPlaying?: () => boolean; // is a media document playing
TogglePause?: (keep?: boolean) => void; // toggle media document playing state
setFocus?: () => void; // sets input focus to the componentView
- setData?: (data: Field | Promise<RefField | undefined>) => boolean;
+ setData?: (data: FieldType | Promise<RefField | undefined>) => boolean;
componentUI?: (boundsLeft: number, boundsTop: number) => JSX.Element | null;
dragStarting?: (snapToDraggedDoc: boolean, showGroupDragTarget: boolean, visited: Set<Doc>) => void;
dragConfig?: (dragData: DragManager.DocumentDragData) => void; // function to setup dragData in custom way (see TreeViews which add a tree view flag)
@@ -228,7 +259,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
if (toRemove.length !== 0) {
const recentlyClosed = this.Document !== Doc.MyRecentlyClosed ? Doc.MyRecentlyClosed : undefined;
toRemove.forEach(doc => {
- leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey);
+ // leavePushpin && DocUtils.LeavePushpin(doc, annotationKey ?? this.annotationKey);
Doc.RemoveDocFromList(targetDataDoc, annotationKey ?? this.annotationKey, doc, true);
doc.embedContainer = undefined;
if (recentlyClosed && !dontAddToRemoved && doc.type !== DocumentType.LOADING) {
@@ -237,7 +268,7 @@ export function ViewBoxAnnotatableComponent<P extends FieldViewProps>() {
}
});
if (targetDataDoc.isGroup && DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]).length < 2) {
- (DocumentManager.Instance.getFirstDocumentView(targetDataDoc)?.ComponentView as CollectionFreeFormView)?.promoteCollection();
+ Array.from(targetDataDoc[DocViews])[0]?.ComponentView?.promoteCollection?.();
} else {
this.isAnyChildContentActive() && this._props.select(false);
}
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 15ce4c15f..16586d922 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -1,32 +1,34 @@
import { IconLookup, IconProp } from '@fortawesome/fontawesome-svg-core';
+import { faCalendarDays } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
-import { action, computed, makeObservable, observable, runInAction } from 'mobx';
+import { Popup } from 'browndash-components';
+import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../Utils';
+import { FaEdit } from 'react-icons/fa';
+import { returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
import { Doc } from '../../fields/Doc';
import { Cast, DocCast } from '../../fields/Types';
import { DocUtils } from '../documents/Documents';
import { CalendarManager } from '../util/CalendarManager';
-import { DragManager, dropActionType } from '../util/DragManager';
+import { DragManager } from '../util/DragManager';
+import { dropActionType } from '../util/DropActionTypes';
import { IsFollowLinkScript } from '../util/LinkFollower';
import { SelectionManager } from '../util/SelectionManager';
import { SharingManager } from '../util/SharingManager';
import { UndoManager, undoBatch } from '../util/UndoManager';
+import { PinProps } from './DocComponent';
import './DocumentButtonBar.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
+import { TemplateMenu } from './TemplateMenu';
import { TabDocView } from './collections/TabDocView';
import { Colors } from './global/globalEnums';
import { LinkPopup } from './linking/LinkPopup';
import { DocumentLinksButton } from './nodes/DocumentLinksButton';
import { DocumentView, DocumentViewInternal, OpenWhere } from './nodes/DocumentView';
import { DashFieldView } from './nodes/formattedText/DashFieldView';
-import { PinProps } from './nodes/trails';
-import { faCalendarDays } from '@fortawesome/free-solid-svg-icons';
-import { Popup } from 'browndash-components';
-import { TemplateMenu } from './TemplateMenu';
-import { FaEdit } from 'react-icons/fa';
@observer
export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: any }> {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 2a44a9739..009097b3b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -5,9 +5,10 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx'
import { observer } from 'mobx-react';
import * as React from 'react';
import { FaUndo } from 'react-icons/fa';
-import { Utils, emptyFunction, lightOrDark, numberValue, returnFalse, setupMoveUpEvents } from '../../Utils';
+import { lightOrDark, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
+import { Utils, numberValue, emptyFunction } from '../../Utils';
import { DateField } from '../../fields/DateField';
-import { Doc, DocListCast, Field, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, DocData } from '../../fields/DocSymbols';
import { InkField } from '../../fields/InkField';
import { ScriptField } from '../../fields/ScriptField';
@@ -34,7 +35,7 @@ import { DocumentView, OpenWhereMod } from './nodes/DocumentView';
import { ImageBox } from './nodes/ImageBox';
import { KeyValueBox } from './nodes/KeyValueBox';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import { identity } from 'lodash';
+import { Id } from '../../fields/FieldSymbols';
interface DocumentDecorationsProps {
PanelWidth: number;
@@ -44,6 +45,7 @@ interface DocumentDecorationsProps {
}
@observer
export class DocumentDecorations extends ObservableReactComponent<DocumentDecorationsProps> {
+ // eslint-disable-next-line no-use-before-define
static Instance: DocumentDecorations;
private _resizeHdlId = '';
private _keyinput = React.createRef<HTMLInputElement>();
@@ -123,7 +125,9 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._titleControlString = this._accumulatedTitle;
} else if (this._titleControlString.startsWith('$')) {
if (this._accumulatedTitle.startsWith('-->#')) {
- SelectionManager.Docs.forEach(doc => (doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`)));
+ SelectionManager.Docs.forEach(doc => {
+ doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`);
+ });
}
const titleFieldKey = this._titleControlString.substring(1);
UndoManager.RunInBatch(
@@ -149,7 +153,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
onContainerDown = (e: React.PointerEvent) => {
const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document);
- if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) {
+ if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
setupMoveUpEvents(this, e, e => this.onBackgroundMove(true, e), emptyFunction, emptyFunction);
e.stopPropagation();
}
@@ -157,13 +161,13 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
onTitleDown = (e: React.PointerEvent) => {
const effectiveLayoutAcl = GetEffectiveAcl(SelectionManager.Views[0].Document);
- if (effectiveLayoutAcl == AclAdmin || effectiveLayoutAcl == AclEdit || effectiveLayoutAcl == AclAugment) {
+ if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
setupMoveUpEvents(
this,
e,
e => this.onBackgroundMove(true, e),
emptyFunction,
- action(e => {
+ action(() => {
const selected = SelectionManager.Views.length === 1 ? SelectionManager.Docs[0] : undefined;
!this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('$') ? (selected && Field.toKeyValueString(selected, this._titleControlString.substring(1))) || '-unset-' : this._titleControlString);
this._editingTitle = true;
@@ -182,7 +186,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
const dragDocView = SelectionManager.Views[0];
const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document);
- if (effectiveLayoutAcl != AclAdmin && effectiveLayoutAcl != AclEdit && effectiveLayoutAcl != AclAugment) {
+ if (effectiveLayoutAcl !== AclAdmin && effectiveLayoutAcl !== AclEdit && effectiveLayoutAcl !== AclAugment) {
return false;
}
const containers = new Set<Doc | undefined>();
@@ -205,7 +209,9 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
e.x,
e.y,
{
- dragComplete: action(e => (this._hidden = false)),
+ dragComplete: action(() => {
+ this._hidden = false;
+ }),
hideSource: true,
}
);
@@ -217,15 +223,16 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
onCloseClick = (forceDeleteOrIconify: boolean | undefined) => {
const views = SelectionManager.Views.filter(v => v && v._props.renderDepth > 0);
if (forceDeleteOrIconify === false && this._iconifyBatch) return;
- this._deleteAfterIconify = forceDeleteOrIconify || this._iconifyBatch ? true : false;
- var iconifyingCount = views.length;
+ this._deleteAfterIconify = !!(forceDeleteOrIconify || this._iconifyBatch);
+ let iconifyingCount = views.length;
const finished = action((force?: boolean) => {
if ((force || --iconifyingCount === 0) && this._iconifyBatch) {
if (this._deleteAfterIconify) {
views.forEach(iconView => {
- Doc.setNativeView(iconView.Document);
- if (iconView.Document.activeFrame) {
- iconView.Document.opacity = 0; // bcz: hacky ... allows inkMasks and other documents to be "turned off" without removing them from the animated collection which allows them to function properly in a presenation.
+ const iconViewDoc = iconView.Document;
+ Doc.setNativeView(iconViewDoc);
+ if (iconViewDoc.activeFrame) {
+ iconViewDoc.opacity = 0; // bcz: hacky ... allows inkMasks and other documents to be "turned off" without removing them from the animated collection which allows them to function properly in a presenation.
} else {
iconView._props.removeDocument?.(iconView.Document);
}
@@ -240,6 +247,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
(document.activeElement as any).blur?.();
this._iconifyBatch = UndoManager.StartBatch(forceDeleteOrIconify ? 'delete selected docs' : 'iconifying');
} else {
+ // eslint-disable-next-line no-param-reassign
forceDeleteOrIconify = false; // can't force immediate close in the middle of iconifying -- have to wait until iconifying completes
}
@@ -268,7 +276,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
// open same document in new tab
CollectionDockingView.ToggleSplit(selectedDocs[0].Document, OpenWhereMod.right);
} else {
- var openDoc = selectedDocs[0].Document;
+ let openDoc = selectedDocs[0].Document;
if (openDoc.layout_fieldKey === 'layout_icon') {
openDoc = Doc.GetEmbeddings(openDoc).find(embedding => !embedding.embedContainer) ?? Doc.MakeEmbedding(openDoc);
Doc.deiconifyView(openDoc);
@@ -294,7 +302,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
*/
@action
onRadiusDown = (e: React.PointerEvent): void => {
- SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement());
+ SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()?.[Id]);
this._isRounding = true;
this._resizeUndo = UndoManager.StartBatch('DocDecs set radius');
setupMoveUpEvents(
@@ -304,14 +312,14 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const [x, y] = [this.Bounds.x + 3, this.Bounds.y + 3];
const maxDist = Math.min((this.Bounds.r - this.Bounds.x) / 2, (this.Bounds.b - this.Bounds.y) / 2);
const dist = e.clientX < x && e.clientY < y ? 0 : Math.sqrt((e.clientX - x) * (e.clientX - x) + (e.clientY - y) * (e.clientY - y));
- SelectionManager.Docs.map(doc => {
+ SelectionManager.Docs.forEach(doc => {
const docMax = Math.min(NumCast(doc.width) / 2, NumCast(doc.height) / 2);
const radius = Math.min(1, dist / maxDist) * docMax; // set radius based on ratio of drag distance to half diagonal distance of bounding box
doc._layout_borderRounding = `${radius}px`;
});
return false;
},
- action(e => {
+ action(() => {
SnappingManager.SetIsResizing(undefined);
this._isRounding = false;
this._resizeUndo?.end();
@@ -329,17 +337,18 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
e,
returnFalse, // don't care about move or up event,
emptyFunction, // just care about whether we get a click event
- e => UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => Doc.toggleLockedPosition(doc)), 'toggleBackground')
+ () => UndoManager.RunInBatch(() => SelectionManager.Docs.forEach(doc => Doc.toggleLockedPosition(doc)), 'toggleBackground')
);
e.stopPropagation();
};
setRotateCenter = (seldocview: DocumentView, rotCenter: number[]) => {
+ const selDoc = seldocview.Document;
const newloccentern = seldocview.screenToContentsTransform().transformPoint(rotCenter[0], rotCenter[1]);
const newlocenter = [newloccentern[0] - NumCast(seldocview.layoutDoc._width) / 2, newloccentern[1] - NumCast(seldocview.layoutDoc._height) / 2];
const final = Utils.rotPt(newlocenter[0], newlocenter[1], -(NumCast(seldocview.Document._rotation) / 180) * Math.PI);
- seldocview.Document._rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width);
- seldocview.Document._rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height);
+ selDoc._rotation_centerX = final.x / NumCast(seldocview.layoutDoc._width);
+ selDoc._rotation_centerY = final.y / NumCast(seldocview.layoutDoc._height);
};
@action
@@ -351,8 +360,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
e,
(e: PointerEvent, down: number[], delta: number[]) => // return false to keep getting events
this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]) as any as boolean,
- action(e => (this._isRotating = false)), // upEvent
- action(e => (seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0)),
+ action(() => { this._isRotating = false; }), // upEvent
+ action(() => { seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0; }),
true
); // prettier-ignore
e.stopPropagation();
@@ -418,13 +427,15 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
this._isRotating = false;
rotateUndo?.end();
}), // upEvent
- action(e => (this._showRotCenter = !this._showRotCenter)) // clickEvent
+ action(() => {
+ this._showRotCenter = !this._showRotCenter;
+ }) // clickEvent
);
};
@action
onPointerDown = (e: React.PointerEvent): void => {
- SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
+ SnappingManager.SetIsResizing(SelectionManager.Docs.lastElement()?.[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
e.stopPropagation();
const id = (this._resizeHdlId = e.currentTarget.className);
@@ -453,12 +464,12 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const tl = docView.screenToContentsTransform().inverse().transformPoint(0, 0);
return project([e.clientX + this._offset.x, e.clientY + this._offset.y], tl, [tl[0] + fixedAspect, tl[1] + 1]);
};
- onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
+ onPointerMove = (e: PointerEvent): boolean => {
const first = SelectionManager.Views[0];
const effectiveAcl = GetEffectiveAcl(first.Document);
- if (!(effectiveAcl == AclAdmin || effectiveAcl == AclEdit || effectiveAcl == AclAugment)) return false;
+ if (!(effectiveAcl === AclAdmin || effectiveAcl === AclEdit || effectiveAcl === AclAugment)) return false;
if (!first) return false;
- var fixedAspect = Doc.NativeAspect(first.layoutDoc);
+ const fixedAspect = Doc.NativeAspect(first.layoutDoc);
const dragHdl = this._resizeHdlId.split(' ')[0].replace('documentDecorations-', '').replace('Resizer', '');
const thisPt = // do snapping of drag point
@@ -476,7 +487,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const scaleAspect = {x:scale.x === 1 && fixedAspect ? scale.y : scale.x, y: scale.x !== 1 && fixedAspect ? scale.x : scale.y};
SelectionManager.Views.forEach(docView =>
this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore
- await new Promise<any>(res => setTimeout(() => res(this._interactionLock = undefined)));
+ await new Promise<any>(res => { setTimeout(() => { res(this._interactionLock = undefined)})});
}); // prettier-ignore
return false;
@@ -553,10 +564,11 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
doc._layout_modificationDate = new DateField();
if (scale.y !== 1) {
- docView.layoutDoc._layout_autoHeight = undefined;
+ const docLayout = docView.layoutDoc;
+ docLayout._layout_autoHeight = undefined;
if (docView.layoutDoc._layout_autoHeight) {
// if autoHeight is still on because of a prototype
- docView.layoutDoc._layout_autoHeight = false; // then don't inherit, but explicitly set it to false
+ docLayout._layout_autoHeight = false; // then don't inherit, but explicitly set it to false
}
}
}
@@ -586,15 +598,17 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
};
@action
- onPointerUp = (e: PointerEvent): void => {
+ onPointerUp = (): void => {
SnappingManager.SetIsResizing(undefined);
SnappingManager.clearSnapLines();
this._resizeHdlId = '';
this._resizeUndo?.end();
// detect layout_autoHeight gesture and apply
- SelectionManager.Views.forEach(view => NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true));
- //need to change points for resize, or else rotation/control points will fail.
+ SelectionManager.Views.forEach(view => {
+ NumCast(view.Document._height) < 20 && (view.layoutDoc._layout_autoHeight = true);
+ });
+ // need to change points for resize, or else rotation/control points will fail.
this._inkDragDocs
.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
.forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
@@ -613,7 +627,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
if (SelectionManager.Views.length === 1) {
const selected = SelectionManager.Views[0];
if (this._titleControlString.startsWith('$')) {
- return Field.toJavascriptString(selected.Document[this._titleControlString.substring(1)] as Field) || '-unset-';
+ return Field.toJavascriptString(selected.Document[this._titleControlString.substring(1)] as FieldType) || '-unset-';
}
return this._accumulatedTitle;
}
@@ -648,7 +662,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const acl = GetEffectiveAcl(!this._showLayoutAcl ? Doc.GetProto(seldocview.Document) : seldocview.Document);
const docShareMode = HierarchyMapping.get(acl)!.name;
const shareMode = StrCast(docShareMode);
- var shareSymbolIcon = ReverseHierarchyMap.get(shareMode)?.image;
+ const shareSymbolIcon = ReverseHierarchyMap.get(shareMode)?.image;
// hide the decorations if the parent chooses to hide it or if the document itself hides it
const hideDecorations = SnappingManager.IsResizing || seldocview._props.hideDecorations || seldocview.Document.layout_hideDecorations;
@@ -687,7 +701,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const bounds = this.ClippedBounds;
const useLock = bounds.r - bounds.x > 135;
const useRotation = !hideResizers && seldocview.Document.type !== DocumentType.EQUATION && seldocview.CollectionFreeFormDocumentView; // when do we want an object to not rotate?
- const rotation = SelectionManager.Views.length == 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0;
+ const rotation = SelectionManager.Views.length === 1 ? seldocview.screenToContentsTransform().inverse().RotateDeg : 0;
// Radius constants
const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
@@ -727,11 +741,13 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
name="dynbox"
autoComplete="on"
value={hideTitle ? '' : this._accumulatedTitle}
- onBlur={action((e: React.FocusEvent) => {
+ onBlur={action(() => {
this._editingTitle = false;
this.titleBlur();
})}
- onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))}
+ onChange={action(e => {
+ !hideTitle && (this._accumulatedTitle = e.target.value);
+ })}
onKeyDown={hideTitle ? emptyFunction : this.titleEntered}
onPointerDown={e => e.stopPropagation()}
/>
@@ -789,8 +805,8 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
display: hideDeleteButton && hideTitle && hideOpenButton ? 'none' : undefined,
}}
onPointerDown={this.onContainerDown}>
- {hideDeleteButton ? null : topBtn('close', 'times', undefined, e => this.onCloseClick(true), 'Close')}
- {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, e => this.onCloseClick(undefined), 'Minimize')}
+ {hideDeleteButton ? null : topBtn('close', 'times', undefined, () => this.onCloseClick(true), 'Close')}
+ {hideResizers || hideDeleteButton ? null : topBtn('minimize', 'window-maximize', undefined, () => this.onCloseClick(undefined), 'Minimize')}
{titleArea}
{hideOpenButton ? <div /> : topBtn('open', 'external-link-alt', this.onMaximizeDown, undefined, 'Open in Lightbox (ctrl: as alias, shift: in new collection)')}
</div>
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index 0521c4a4b..d3cebd1c3 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -1,10 +1,12 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, makeObservable, observable, ObservableMap } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider';
import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai';
import { CiCircleRemove } from 'react-icons/ci';
-import { Doc, DocListCast, Field, LinkedTo, StrListCast } from '../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, LinkedTo, StrListCast } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { List } from '../../fields/List';
import { RichTextField } from '../../fields/RichTextField';
@@ -58,7 +60,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
@computed get mapActiveFiltersToFacets() {
const filters = new Map<string, string>();
- //this.targetDoc.docFilters
+ // this.targetDoc.docFilters
this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1], filter.split(Doc.FilterSep)[0]));
return filters;
}
@@ -73,7 +75,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
// ["#tags", "width", "height"]
//
@computed get activeFacetHeaders() {
- const activeHeaders = new Array();
+ const activeHeaders = [] as string[];
this.activeFilters.map(filter => activeHeaders.push(filter.split(Doc.FilterSep)[0]));
return activeHeaders;
@@ -83,19 +85,20 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
const valueSet = new Set<string>(childFilters.map(filter => filter.split(Doc.FilterSep)[1]));
let rtFields = 0;
let subDocs = childDocs;
- let gatheredDocs = [] as Doc[];
+ const gatheredDocs = [] as Doc[];
if (subDocs.length > 0) {
let newarray: Doc[] = [];
while (subDocs.length > 0) {
newarray = [];
+ // eslint-disable-next-line no-loop-func
subDocs.forEach(t => {
gatheredDocs.push(t);
const facetVal = t[facetKey];
if (facetVal instanceof RichTextField || typeof facetVal === 'string') rtFields++;
- facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field));
- (facetVal === true || facetVal == false) && valueSet.add(Field.toString(!facetVal));
+ facetVal !== undefined && valueSet.add(Field.toString(facetVal as FieldType));
+ (facetVal === true || facetVal === false) && valueSet.add(Field.toString(!facetVal));
const fieldKey = Doc.LayoutFieldKey(t);
- const annos = !Field.toString(Doc.LayoutField(t) as Field).includes('CollectionView');
+ const annos = !Field.toString(Doc.LayoutField(t) as FieldType).includes('CollectionView');
DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
annos && DocListCast(t[fieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc));
});
@@ -115,7 +118,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
// @observable _chosenFacets = new ObservableMap<string, 'text' | 'checkbox' | 'slider' | 'range'>();
@observable _chosenFacetsCollapse = new ObservableMap<string, boolean>();
- @observable _collapseReturnKeys = new Array();
+ @observable _collapseReturnKeys = [] as string[];
// this computed function gets the active filters and maps them to their headers
//
@@ -130,11 +133,11 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
const facetValues = FilterPanel.gatherFieldValues(this.targetDocChildren, facetHeader, StrListCast(this.Document.childFilters));
let nonNumbers = 0;
- let minVal = Number.MAX_VALUE,
- maxVal = -Number.MAX_VALUE;
- facetValues.strings.map(val => {
+ let minVal = Number.MAX_VALUE;
+ let maxVal = -Number.MAX_VALUE;
+ facetValues.strings.forEach(val => {
const num = val ? Number(val) : Number.NaN;
- if (Number.isNaN(num)) {
+ if (isNaN(num)) {
val && nonNumbers++;
} else {
minVal = Math.min(num, minVal);
@@ -144,14 +147,14 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
if (facetHeader === 'text') {
return { facetHeader, renderType: 'text' };
- } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) {
+ }
+ if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) {
const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1));
const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05)));
- const ranged = Doc.readDocRangeFilter(this.Document, facetHeader); // not the filter range, but the zooomed in range on the filter
- return { facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] };
- } else {
- return { facetHeader, renderType: 'checkbox' };
+ const ranged: number[] | undefined = Doc.readDocRangeFilter(this.Document, facetHeader); // not the filter range, but the zooomed in range on the filter
+ return { facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged || [extendedMinVal, extendedMaxVal] };
}
+ return { facetHeader, renderType: 'checkbox' };
})
);
}
@@ -171,17 +174,17 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
sortingCurrentFacetValues = (facetHeader: string) => {
this._collapseReturnKeys.splice(0);
- Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => {
+ Array.from(this.activeRenderedFacetInfos.keys()).forEach(renderInfo => {
if (renderInfo.renderType === 'range' && renderInfo.facetHeader === facetHeader && renderInfo.range) {
- this._collapseReturnKeys.push(renderInfo.range.map(number => number.toFixed(2)));
+ this._collapseReturnKeys.push(...renderInfo.range.map(number => number.toFixed(2)));
}
});
- for (var key of this.facetValues(facetHeader)) {
+ this.facetValues(facetHeader).forEach(key => {
if (this.mapActiveFiltersToFacets.get(key)) {
this._collapseReturnKeys.push(key);
}
- }
+ });
return <div className=" filterbox-collpasedAndActive">{this._collapseReturnKeys.join(', ')}</div>;
};
@@ -198,7 +201,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
);
else
allCollectionDocs.forEach(child => {
- const fieldVal = child[facetHeader] as Field;
+ const fieldVal = child[facetHeader] as FieldType;
if (!(fieldVal instanceof List)) {
// currently we have no good way of filtering based on a field that is a list
set.add(Field.toString(fieldVal));
@@ -209,7 +212,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
let nonNumbers = 0;
- facetValues.map(val => Number.isNaN(Number(val)) && nonNumbers++);
+ facetValues.map(val => isNaN(Number(val)) && nonNumbers++);
return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2));
};
@@ -218,7 +221,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
<div className="filterBox-treeView">
<div className="filterBox-select">
<div style={{ width: '100%' }}>
- <FieldsDropdown Document={this.Document} selectFunc={this.facetClick} showPlaceholder={true} placeholder="add a filter" addedFields={['acl-Guest', LinkedTo]} />
+ <FieldsDropdown Document={this.Document} selectFunc={this.facetClick} showPlaceholder placeholder="add a filter" addedFields={['acl-Guest', LinkedTo]} />
</div>
{/* THE FOLLOWING CODE SHOULD BE DEVELOPER FOR BOOLEAN EXPRESSION (AND / OR) */}
{/* <div className="filterBox-select-bool">
@@ -234,34 +237,31 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
<div className="filterBox-tree" key="tree">
{Array.from(this.activeRenderedFacetInfos.keys()).map(
- (
- renderInfo // iterato over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
- ) => (
+ // iterate over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
+ renderInfo => (
<div>
<div className="filterBox-facetHeader">
<div className="filterBox-facetHeader-Header"> </div>
{renderInfo.facetHeader.charAt(0).toUpperCase() + renderInfo.facetHeader.slice(1)}
-
<div
className="filterBox-facetHeader-collapse"
- onClick={action(e => {
+ onClick={action(() => {
const collapseBoolValue = this._chosenFacetsCollapse.get(renderInfo.facetHeader);
this._chosenFacetsCollapse.set(renderInfo.facetHeader, !collapseBoolValue);
})}>
{this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? <AiOutlinePlusSquare /> : <AiOutlineMinusSquare />}
</div>
-
<div
className="filterBox-facetHeader-remove"
- onClick={action(e => {
+ onClick={action(() => {
if (renderInfo.facetHeader === 'text') {
Doc.setDocFilter(this.Document, renderInfo.facetHeader, 'match', 'remove');
} else {
- for (var key of this.facetValues(renderInfo.facetHeader)) {
+ this.facetValues(renderInfo.facetHeader).forEach((key: string) => {
if (this.mapActiveFiltersToFacets.get(key)) {
Doc.setDocFilter(this.Document, renderInfo.facetHeader, key, 'remove');
}
- }
+ });
}
this._selectedFacetHeaders.delete(renderInfo.facetHeader);
this._chosenFacetsCollapse.delete(renderInfo.facetHeader);
@@ -292,7 +292,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
return (
<input
key={this.Document[Id]}
- placeholder={'enter text to match'}
+ placeholder="enter text to match"
defaultValue={
StrListCast(this.Document._childFilters)
.find(filter => filter.split(Doc.FilterSep)[0] === facetHeader)
@@ -312,7 +312,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
style={{ width: 20, marginLeft: 20 }}
checked={['check', 'exists'].includes(
StrListCast(this.Document._childFilters)
- .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue)
+ .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] === facetValue)
?.split(Doc.FilterSep)[2] ?? ''
)}
type={type}
@@ -324,55 +324,56 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
});
case 'range':
- const domain = renderInfoDomain;
- const range = renderInfoRange;
- if (domain) {
- return (
- <div className="sliderBox-outerDiv" style={{ width: '95%', height: 45, float: 'right' }}>
- <Slider
- mode={2}
- step={Math.min(1, 0.1 * (domain[1] - domain[0]))}
- domain={[domain[0], domain[1]]} // -1000, 1000
- rootStyle={{ position: 'relative', width: '100%' }}
- onChange={values => Doc.setDocRangeFilter(this.Document, facetHeader, values)}
- values={renderInfoRange!}>
- <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
- <Handles>
- {({ handles, activeHandleID, getHandleProps }) => (
- <div className="slider-handles">
- {handles.map((handle, i) => {
- // const value = i === 0 ? defaultValues[0] : defaultValues[1];
- return (
+ {
+ const domain = renderInfoDomain;
+ if (domain) {
+ return (
+ <div className="sliderBox-outerDiv" style={{ width: '95%', height: 45, float: 'right' }}>
+ <Slider
+ mode={2}
+ step={Math.min(1, 0.1 * (domain[1] - domain[0]))}
+ domain={[domain[0], domain[1]]} // -1000, 1000
+ rootStyle={{ position: 'relative', width: '100%' }}
+ onChange={values => Doc.setDocRangeFilter(this.Document, facetHeader, values)}
+ values={renderInfoRange!}>
+ <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
+ <Handles>
+ {({ handles, activeHandleID, getHandleProps }) => (
+ <div className="slider-handles">
+ {handles.map(handle => (
+ // const value = i === 0 ? defaultValues[0] : defaultValues[1];
<div>
<Handle key={handle.id} handle={handle} domain={domain} isActive={handle.id === activeHandleID} getHandleProps={getHandleProps} />
</div>
- );
- })}
- </div>
- )}
- </Handles>
- <Tracks left={false} right={false}>
- {({ tracks, getTrackProps }) => (
- <div className="slider-tracks">
- {tracks.map(({ id, source, target }) => (
- <Track key={id} source={source} target={target} disabled={false} getTrackProps={getTrackProps} />
- ))}
- </div>
- )}
- </Tracks>
- <Ticks count={5}>
- {({ ticks }) => (
- <div className="slider-ticks">
- {ticks.map(tick => (
- <Tick key={tick.id} tick={tick} count={ticks.length} format={(val: number) => val.toString()} />
- ))}
- </div>
- )}
- </Ticks>
- </Slider>
- </div>
- );
+ ))}
+ </div>
+ )}
+ </Handles>
+ <Tracks left={false} right={false}>
+ {({ tracks, getTrackProps }) => (
+ <div className="slider-tracks">
+ {tracks.map(({ id, source, target }) => (
+ <Track key={id} source={source} target={target} disabled={false} getTrackProps={getTrackProps} />
+ ))}
+ </div>
+ )}
+ </Tracks>
+ <Ticks count={5}>
+ {({ ticks }) => (
+ <div className="slider-ticks">
+ {ticks.map(tick => (
+ <Tick key={tick.id} tick={tick} count={ticks.length} format={(val: number) => val.toString()} />
+ ))}
+ </div>
+ )}
+ </Ticks>
+ </Slider>
+ </div>
+ );
+ }
}
+ break;
+ default:
// case 'range'
// return <Slider ...
@@ -386,5 +387,6 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
// <dimain changing handles >
// <?div
}
+ return undefined;
}
}
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 86b9f5e40..46fa04d72 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -2,11 +2,13 @@ import * as fitCurve from 'fit-curve';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
import { Doc, Opt } from '../../fields/Doc';
import { InkData, InkTool } from '../../fields/InkField';
import { BoolCast, NumCast } from '../../fields/Types';
import MobileInkOverlay from '../../mobile/MobileInkOverlay';
+import { Gestures } from '../../pen-gestures/GestureTypes';
import { GestureUtils } from '../../pen-gestures/GestureUtils';
import { MobileInkOverlayContent } from '../../server/Message';
import { InteractionUtils } from '../util/InteractionUtils';
@@ -29,15 +31,22 @@ import {
SetActiveInkWidth,
} from './InkingStroke';
import { ObservableReactComponent } from './ObservableReactComponent';
-import { checkInksToGroup } from './global/globalScripts';
import { DocumentView } from './nodes/DocumentView';
+export enum ToolglassTools {
+ InkToText = 'inktotext',
+ IgnoreGesture = 'ignoregesture',
+ RadialMenu = 'radialmenu',
+ None = 'none',
+}
interface GestureOverlayProps {
isActive: boolean;
}
@observer
export class GestureOverlay extends ObservableReactComponent<React.PropsWithChildren<GestureOverlayProps>> {
+ // eslint-disable-next-line no-use-before-define
static Instance: GestureOverlay;
+ // eslint-disable-next-line no-use-before-define
static Instances: GestureOverlay[] = [];
public static set RecognizeGestures(active) {
@@ -47,7 +56,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
return BoolCast(Doc.UserDoc().recognizeGestures);
}
- @observable public InkShape: Opt<GestureUtils.Gestures> = undefined;
+ @observable public InkShape: Opt<Gestures> = undefined;
@observable public SavedColor?: string = undefined;
@observable public SavedWidth?: number = undefined;
@observable public Tool: ToolglassTools = ToolglassTools.None;
@@ -55,9 +64,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
@observable private _thumbX?: number = undefined;
@observable private _thumbY?: number = undefined;
- @observable private _selectedIndex: number = -1;
- @observable private _menuX: number = -300;
- @observable private _menuY: number = -300;
@observable private _pointerY?: number = undefined;
@observable private _points: { X: number; Y: number }[] = [];
@observable private _strokes: InkData[] = [];
@@ -117,9 +123,9 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
const yInGlass = initialPoint.Y > (this._thumbY ?? Number.MAX_SAFE_INTEGER) - this.height && initialPoint.Y < (this._thumbY ?? Number.MAX_SAFE_INTEGER);
if (this.Tool !== ToolglassTools.None && xInGlass && yInGlass) {
switch (this.Tool) {
- case ToolglassTools.RadialMenu:
- return true;
- }
+ case ToolglassTools.RadialMenu: return true;
+ default:
+ } // prettier-ignore
}
}
return false;
@@ -128,8 +134,8 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
@action primCreated() {
if (!this.KeepPrimitiveMode) {
this.InkShape = undefined;
- //get out of ink mode after each stroke=
- //if (Doc.ActiveTool === InkTool.Highlighter && GestureOverlay.Instance.SavedColor) SetActiveInkColor(GestureOverlay.Instance.SavedColor);
+ // get out of ink mode after each stroke=
+ // if (Doc.ActiveTool === InkTool.Highlighter && GestureOverlay.Instance.SavedColor) SetActiveInkColor(GestureOverlay.Instance.SavedColor);
Doc.ActiveTool = InkTool.None;
// SetActiveArrowStart('none');
// SetActiveArrowEnd('none');
@@ -142,7 +148,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
const B = this.svgBounds;
const points = this._points.map(p => ({ X: p.X - B.left, Y: p.Y - B.top }));
- //if any of the shape is activated in the CollectionFreeFormViewChrome
+ // if any of the shape is activated in the CollectionFreeFormViewChrome
if (this.InkShape) {
this.makeBezierPolygon(this.InkShape, false);
this.dispatchGesture(this.InkShape);
@@ -155,16 +161,17 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
let actionPerformed = false;
if (GestureOverlay.RecognizeGestures && result && result.Score > 0.7) {
switch (result.Name) {
- case GestureUtils.Gestures.Line:
- case GestureUtils.Gestures.Triangle:
- case GestureUtils.Gestures.Rectangle:
- case GestureUtils.Gestures.Circle:
+ case Gestures.Line:
+ case Gestures.Triangle:
+ case Gestures.Rectangle:
+ case Gestures.Circle:
this.makeBezierPolygon(result.Name, true);
actionPerformed = this.dispatchGesture(result.Name);
break;
- case GestureUtils.Gestures.Scribble:
+ case Gestures.Scribble:
console.log('scribble');
break;
+ default:
}
}
@@ -178,21 +185,20 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
const controlPoints: { X: number; Y: number }[] = [];
const bezierCurves = (fitCurve as any)(newPoints, 10);
- for (const curve of bezierCurves) {
+ Array.from(bezierCurves).forEach((curve: any) => {
controlPoints.push({ X: curve[0][0], Y: curve[0][1] });
controlPoints.push({ X: curve[1][0], Y: curve[1][1] });
controlPoints.push({ X: curve[2][0], Y: curve[2][1] });
controlPoints.push({ X: curve[3][0], Y: curve[3][1] });
- }
+ });
const dist = Math.sqrt(
(controlPoints[0].X - controlPoints.lastElement().X) * (controlPoints[0].X - controlPoints.lastElement().X) + (controlPoints[0].Y - controlPoints.lastElement().Y) * (controlPoints[0].Y - controlPoints.lastElement().Y)
);
+ // eslint-disable-next-line prefer-destructuring
if (controlPoints.length > 4 && dist < 10) controlPoints[controlPoints.length - 1] = controlPoints[0];
this._points.length = 0;
this._points.push(...controlPoints);
- this.dispatchGesture(GestureUtils.Gestures.Stroke);
- // TODO: nda - check inks to group here
- checkInksToGroup();
+ this.dispatchGesture(Gestures.Stroke);
}
}
}
@@ -202,34 +208,34 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
makeBezierPolygon = (shape: string, gesture: boolean) => {
const xs = this._points.map(p => p.X);
const ys = this._points.map(p => p.Y);
- var right = Math.max(...xs);
- var left = Math.min(...xs);
- var bottom = Math.max(...ys);
- var top = Math.min(...ys);
+ let right = Math.max(...xs);
+ let left = Math.min(...xs);
+ let bottom = Math.max(...ys);
+ let top = Math.min(...ys);
const firstx = this._points[0].X;
const firsty = this._points[0].Y;
- var lastx = this._points[this._points.length - 2].X;
- var lasty = this._points[this._points.length - 2].Y;
- var fourth = (lastx - firstx) / 4;
+ let lastx = this._points[this._points.length - 2].X;
+ let lasty = this._points[this._points.length - 2].Y;
+ let fourth = (lastx - firstx) / 4;
if (isNaN(fourth) || fourth === 0) {
fourth = 0.01;
}
- var m = (lasty - firsty) / (lastx - firstx);
+ let m = (lasty - firsty) / (lastx - firstx);
if (isNaN(m) || m === 0) {
m = 0.01;
}
- const b = firsty - m * firstx;
+ // const b = firsty - m * firstx;
if (shape === 'noRec') {
return false;
}
if (!gesture) {
- //if shape options is activated in inkOptionMenu
- //take second to last point because _point[length-1] is _points[0]
+ // if shape options is activated in inkOptionMenu
+ // take second to last point because _point[length-1] is _points[0]
right = this._points[this._points.length - 2].X;
left = this._points[0].X;
bottom = this._points[this._points.length - 2].Y;
top = this._points[0].Y;
- if (shape !== GestureUtils.Gestures.Arrow && shape !== GestureUtils.Gestures.Line && shape !== GestureUtils.Gestures.Circle) {
+ if (shape !== Gestures.Arrow && shape !== Gestures.Line && shape !== Gestures.Circle) {
if (left > right) {
const temp = right;
right = left;
@@ -244,7 +250,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
}
this._points.length = 0;
switch (shape) {
- case GestureUtils.Gestures.Rectangle:
+ case Gestures.Rectangle:
this._points.push({ X: left, Y: top });
this._points.push({ X: left, Y: top });
this._points.push({ X: right, Y: top });
@@ -267,7 +273,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
break;
- case GestureUtils.Gestures.Triangle:
+ case Gestures.Triangle:
this._points.push({ X: left, Y: bottom });
this._points.push({ X: left, Y: bottom });
@@ -285,39 +291,40 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
this._points.push({ X: left, Y: bottom });
break;
- case GestureUtils.Gestures.Circle:
- // Approximation of a circle using 4 Bézier curves in which the constant "c" reduces the maximum radial drift to 0.019608%,
- // making the curves indistinguishable from a circle.
- // Source: https://spencermortensen.com/articles/bezier-circle/
- const c = 0.551915024494;
- const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
- const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
- const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
-
- // Dividing the circle into four equal sections, and fitting each section to a cubic Bézier curve.
- this._points.push({ X: centerX, Y: centerY + radius });
- this._points.push({ X: centerX + c * radius, Y: centerY + radius });
- this._points.push({ X: centerX + radius, Y: centerY + c * radius });
- this._points.push({ X: centerX + radius, Y: centerY });
-
- this._points.push({ X: centerX + radius, Y: centerY });
- this._points.push({ X: centerX + radius, Y: centerY - c * radius });
- this._points.push({ X: centerX + c * radius, Y: centerY - radius });
- this._points.push({ X: centerX, Y: centerY - radius });
-
- this._points.push({ X: centerX, Y: centerY - radius });
- this._points.push({ X: centerX - c * radius, Y: centerY - radius });
- this._points.push({ X: centerX - radius, Y: centerY - c * radius });
- this._points.push({ X: centerX - radius, Y: centerY });
-
- this._points.push({ X: centerX - radius, Y: centerY });
- this._points.push({ X: centerX - radius, Y: centerY + c * radius });
- this._points.push({ X: centerX - c * radius, Y: centerY + radius });
- this._points.push({ X: centerX, Y: centerY + radius });
-
+ case Gestures.Circle:
+ {
+ // Approximation of a circle using 4 Bézier curves in which the constant "c" reduces the maximum radial drift to 0.019608%,
+ // making the curves indistinguishable from a circle.
+ // Source: https://spencermortensen.com/articles/bezier-circle/
+ const c = 0.551915024494;
+ const centerX = (Math.max(left, right) + Math.min(left, right)) / 2;
+ const centerY = (Math.max(top, bottom) + Math.min(top, bottom)) / 2;
+ const radius = Math.max(centerX - Math.min(left, right), centerY - Math.min(top, bottom));
+
+ // Dividing the circle into four equal sections, and fitting each section to a cubic Bézier curve.
+ this._points.push({ X: centerX, Y: centerY + radius });
+ this._points.push({ X: centerX + c * radius, Y: centerY + radius });
+ this._points.push({ X: centerX + radius, Y: centerY + c * radius });
+ this._points.push({ X: centerX + radius, Y: centerY });
+
+ this._points.push({ X: centerX + radius, Y: centerY });
+ this._points.push({ X: centerX + radius, Y: centerY - c * radius });
+ this._points.push({ X: centerX + c * radius, Y: centerY - radius });
+ this._points.push({ X: centerX, Y: centerY - radius });
+
+ this._points.push({ X: centerX, Y: centerY - radius });
+ this._points.push({ X: centerX - c * radius, Y: centerY - radius });
+ this._points.push({ X: centerX - radius, Y: centerY - c * radius });
+ this._points.push({ X: centerX - radius, Y: centerY });
+
+ this._points.push({ X: centerX - radius, Y: centerY });
+ this._points.push({ X: centerX - radius, Y: centerY + c * radius });
+ this._points.push({ X: centerX - c * radius, Y: centerY + radius });
+ this._points.push({ X: centerX, Y: centerY + radius });
+ }
break;
- case GestureUtils.Gestures.Line:
+ case Gestures.Line:
if (Math.abs(firstx - lastx) < 10 && Math.abs(firsty - lasty) > 10) {
lastx = firstx;
}
@@ -330,28 +337,32 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
this._points.push({ X: lastx, Y: lasty });
this._points.push({ X: lastx, Y: lasty });
break;
- case GestureUtils.Gestures.Arrow:
- const x1 = left;
- const y1 = top;
- const x2 = right;
- const y2 = bottom;
- const L1 = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + Math.pow(Math.abs(y1 - y2), 2));
- const L2 = L1 / 5;
- const angle = 0.785398;
- const x3 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) + (y1 - y2) * Math.sin(angle));
- const y3 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) - (x1 - x2) * Math.sin(angle));
- const x4 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle));
- const y4 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) + (x1 - x2) * Math.sin(angle));
- this._points.push({ X: x1, Y: y1 });
- this._points.push({ X: x2, Y: y2 });
- this._points.push({ X: x3, Y: y3 });
- this._points.push({ X: x4, Y: y4 });
- this._points.push({ X: x2, Y: y2 });
+ case Gestures.Arrow:
+ {
+ const x1 = left;
+ const y1 = top;
+ const x2 = right;
+ const y2 = bottom;
+ const L1 = Math.sqrt(Math.abs(x1 - x2) ** 2 + Math.abs(y1 - y2) ** 2);
+ const L2 = L1 / 5;
+ const angle = 0.785398;
+ const x3 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) + (y1 - y2) * Math.sin(angle));
+ const y3 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) - (x1 - x2) * Math.sin(angle));
+ const x4 = x2 + (L2 / L1) * ((x1 - x2) * Math.cos(angle) - (y1 - y2) * Math.sin(angle));
+ const y4 = y2 + (L2 / L1) * ((y1 - y2) * Math.cos(angle) + (x1 - x2) * Math.sin(angle));
+ this._points.push({ X: x1, Y: y1 });
+ this._points.push({ X: x2, Y: y2 });
+ this._points.push({ X: x3, Y: y3 });
+ this._points.push({ X: x4, Y: y4 });
+ this._points.push({ X: x2, Y: y2 });
+ }
+ break;
+ default:
}
return false;
};
- dispatchGesture = (gesture: GestureUtils.Gestures, stroke?: InkData, text?: any) => {
+ dispatchGesture = (gesture: Gestures, stroke?: InkData, text?: any) => {
const points = (stroke ?? this._points).slice();
return (
document.elementFromPoint(points[0].X, points[0].Y)?.dispatchEvent(
@@ -387,11 +398,11 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
const selView = GestureOverlay.DownDocView;
const width = Number(ActiveInkWidth()) * NumCast(selView?.Document._freeform_scale, 1); // * (selView?.screenToViewTransform().Scale || 1);
const rect = this._overlayRef.current?.getBoundingClientRect();
- const B = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; //this.getBounds(this._points, true);
- B.left = B.left - width / 2;
- B.right = B.right + width / 2;
+ const B = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; // this.getBounds(this._points, true);
+ B.left -= width / 2;
+ B.right += width / 2;
B.top = B.top - width / 2 - (rect?.y || 0);
- B.bottom = B.bottom + width / 2;
+ B.bottom += width / 2;
B.width += width;
B.height += width;
const fillColor = ActiveFillColor();
@@ -401,7 +412,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
this._palette,
[
this._strokes.map((l, i) => {
- const b = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; //this.getBounds(l, true);
+ const b = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; // this.getBounds(l, true);
return (
<svg key={i} width={b.width} height={b.height} style={{ top: 0, left: 0, transform: `translate(${b.left}px, ${b.top}px)`, pointerEvents: 'none', position: 'absolute', zIndex: 30000, overflow: 'visible' }}>
{InteractionUtils.CreatePolyline(
@@ -414,7 +425,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
'miter',
'round',
ActiveInkBezierApprox(),
- 'none' /*ActiveFillColor()*/,
+ 'none' /* ActiveFillColor() */,
ActiveArrowStart(),
ActiveArrowEnd(),
ActiveArrowScale(),
@@ -441,7 +452,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
'miter',
'round',
'',
- 'none' /*ActiveFillColor()*/,
+ 'none' /* ActiveFillColor() */,
ActiveArrowStart(),
ActiveArrowEnd(),
ActiveArrowScale(),
@@ -529,19 +540,14 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
}
}
-// export class
-
-export enum ToolglassTools {
- InkToText = 'inktotext',
- IgnoreGesture = 'ignoregesture',
- RadialMenu = 'radialmenu',
- None = 'none',
-}
-
ScriptingGlobals.add('GestureOverlay', GestureOverlay);
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setToolglass(tool: any) {
- runInAction(() => (GestureOverlay.Instance.Tool = tool));
+ runInAction(() => {
+ GestureOverlay.Instance.Tool = tool;
+ });
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setPen(width: any, color: any, fill: any, arrowStart: any, arrowEnd: any, dash: any) {
runInAction(() => {
GestureOverlay.Instance.SavedColor = ActiveInkColor();
@@ -554,6 +560,7 @@ ScriptingGlobals.add(function setPen(width: any, color: any, fill: any, arrowSta
SetActiveDash(dash);
});
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function resetPen() {
runInAction(() => {
SetActiveInkColor(GestureOverlay.Instance.SavedColor ?? 'rgb(0, 0, 0)');
@@ -561,8 +568,9 @@ ScriptingGlobals.add(function resetPen() {
});
}, 'resets the pen tool');
ScriptingGlobals.add(
+ // eslint-disable-next-line prefer-arrow-callback
function createText(text: any, x: any, y: any) {
- GestureOverlay.Instance.dispatchGesture(GestureUtils.Gestures.Text, [{ X: x, Y: y }], text);
+ GestureOverlay.Instance.dispatchGesture(Gestures.Text, [{ X: x, Y: y }], text);
},
'creates a text document with inputted text and coordinates',
'(text: any, x: any, y: any)'
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 2f64ea28c..5c923d301 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -67,7 +67,6 @@ export class KeyManager {
// accumulate buffer of characters to insert in a new text note. once the note is created, it will stop keyboard events from reaching this function.
if (FormattedTextBox.SelectOnLoadChar) FormattedTextBox.SelectOnLoadChar = FormattedTextBox.SelectOnLoadChar + (e.key === 'Enter' ? '\n' : e.key);
e.key === 'Control' && (CtrlKey = true);
- //if (!Doc.noviceMode && e.key.toLocaleLowerCase() === "shift") DocServer.UPDATE_SERVER_CACHE(true);
const keyname = e.key && e.key.toLowerCase();
this.handleGreedy(keyname);
@@ -89,10 +88,7 @@ export class KeyManager {
control.preventDefault && e.preventDefault();
});
- private handleGreedy = action((keyname: string) => {
- switch (keyname) {
- }
- });
+ private handleGreedy = action((/* keyname: string */) => {});
nudge = (x: number, y: number, label: string) => {
const nudgeable = SelectionManager.Views.some(dv => dv.CollectionFreeFormDocumentView?.nudge);
@@ -105,7 +101,7 @@ export class KeyManager {
case 'u':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
const ungroupings = SelectionManager.Views;
- UndoManager.RunInBatch(() => ungroupings.map(dv => (dv.layoutDoc.group = undefined)), 'ungroup');
+ UndoManager.RunInBatch(() => ungroupings.forEach(dv => { dv.layoutDoc.group = undefined; }), 'ungroup');
SelectionManager.DeselectAll();
}
break;
@@ -124,41 +120,41 @@ export class KeyManager {
case ' ':
// MarqueeView.DragMarquee = !MarqueeView.DragMarquee; // bcz: this needs a better disclosure UI
break;
- case 'escape':
- DocumentLinksButton.StartLink = undefined;
- DocumentLinksButton.StartLinkView = undefined;
- InkStrokeProperties.Instance._controlButton = false;
- Doc.ActiveTool = InkTool.None;
- DragManager.CompleteWindowDrag?.(true);
- var doDeselect = true;
- if (SnappingManager.IsDragging) {
- DragManager.AbortDrag();
- }
- if (CollectionDockingView.Instance?.HasFullScreen) {
- CollectionDockingView.Instance?.CloseFullScreen();
- }
- if (CollectionStackedTimeline.SelectingRegions.size) {
- CollectionStackedTimeline.StopSelecting();
- doDeselect = false;
- } else {
- doDeselect = !ContextMenu.Instance.closeMenu();
- }
- if (doDeselect) {
- SelectionManager.DeselectAll();
- LightboxView.Instance.SetLightboxDoc(undefined);
+ case 'escape': {
+ DocumentLinksButton.StartLink = undefined;
+ DocumentLinksButton.StartLinkView = undefined;
+ InkStrokeProperties.Instance._controlButton = false;
+ Doc.ActiveTool = InkTool.None;
+ DragManager.CompleteWindowDrag?.(true);
+ let doDeselect = true;
+ if (SnappingManager.IsDragging) {
+ DragManager.AbortDrag();
+ }
+ if (CollectionDockingView.Instance?.HasFullScreen) {
+ CollectionDockingView.Instance?.CloseFullScreen();
+ }
+ if (CollectionStackedTimeline.SelectingRegions.size) {
+ CollectionStackedTimeline.StopSelecting();
+ doDeselect = false;
+ } else {
+ doDeselect = !ContextMenu.Instance.closeMenu();
+ }
+ if (doDeselect) {
+ SelectionManager.DeselectAll();
+ LightboxView.Instance.SetLightboxDoc(undefined);
+ }
+ // DictationManager.Controls.stop();
+ GoogleAuthenticationManager.Instance.cancel();
+ SharingManager.Instance.close();
+ if (!GroupManager.Instance.isOpen) SettingsManager.Instance.close();
+ GroupManager.Instance.close();
+ window.getSelection()?.empty();
+ document.body.focus();
}
- // DictationManager.Controls.stop();
- GoogleAuthenticationManager.Instance.cancel();
- SharingManager.Instance.close();
- if (!GroupManager.Instance.isOpen) SettingsManager.Instance.close();
- GroupManager.Instance.close();
- window.getSelection()?.empty();
- document.body.focus();
break;
- case 'enter': {
- //DocumentDecorations.Instance.onCloseClick(false);
+ case 'enter':
+ // DocumentDecorations.Instance.onCloseClick(false);
break;
- }
case 'delete':
case 'backspace':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
@@ -173,6 +169,7 @@ export class KeyManager {
case 'arrowright': return this.nudge(1,0, 'nudge right');
case 'arrowup': return this.nudge(0, -1, 'nudge up');
case 'arrowdown': return this.nudge(0, 1, 'nudge down');
+ default:
} // prettier-ignore
return {
diff --git a/src/client/views/InkControlPtHandles.tsx b/src/client/views/InkControlPtHandles.tsx
index edc6b404b..0358344b9 100644
--- a/src/client/views/InkControlPtHandles.tsx
+++ b/src/client/views/InkControlPtHandles.tsx
@@ -6,7 +6,7 @@ import { ControlPoint, InkData, PointData } from '../../fields/InkField';
import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
import { Cast } from '../../fields/Types';
-import { returnFalse, setupMoveUpEvents } from '../../Utils';
+import { returnFalse, setupMoveUpEvents } from '../../ClientUtils';
import { SelectionManager } from '../util/SelectionManager';
import { UndoManager } from '../util/UndoManager';
import { Colors } from './global/globalEnums';
diff --git a/src/client/views/InkTangentHandles.tsx b/src/client/views/InkTangentHandles.tsx
index c20399698..f3a757f19 100644
--- a/src/client/views/InkTangentHandles.tsx
+++ b/src/client/views/InkTangentHandles.tsx
@@ -6,7 +6,8 @@ import { HandleLine, HandlePoint, InkData } from '../../fields/InkField';
import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
import { Cast } from '../../fields/Types';
-import { emptyFunction, setupMoveUpEvents } from '../../Utils';
+import { emptyFunction } from '../../Utils';
+import { setupMoveUpEvents } from '../../ClientUtils';
import { Transform } from '../util/Transform';
import { UndoManager } from '../util/UndoManager';
import { Colors } from './global/globalEnums';
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 51baaa23e..9f82fdb18 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -23,18 +23,18 @@
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { DashColor, returnFalse, setupMoveUpEvents } from '../../ClientUtils';
import { Doc } from '../../fields/Doc';
import { InkData, InkField } from '../../fields/InkField';
import { BoolCast, Cast, NumCast, RTFCast, StrCast } from '../../fields/Types';
import { TraceMobx } from '../../fields/util';
-import { DashColor, returnFalse, setupMoveUpEvents } from '../../Utils';
import { CognitiveServices } from '../cognitive_services/CognitiveServices';
import { Docs } from '../documents/Documents';
import { InteractionUtils } from '../util/InteractionUtils';
import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
import { ContextMenu } from './ContextMenu';
-import { ViewBoxAnnotatableComponent, ViewBoxBaseComponent, ViewBoxInterface } from './DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from './DocComponent';
import { Colors } from './global/globalEnums';
import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles';
import './InkStroke.scss';
@@ -42,8 +42,9 @@ import { InkStrokeProperties } from './InkStrokeProperties';
import { InkTangentHandles } from './InkTangentHandles';
import { FieldView, FieldViewProps } from './nodes/FieldView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import { PinProps, PresBox } from './nodes/trails';
+import { PresBox } from './nodes/trails';
import { StyleProp } from './StyleProvider';
+
const { INK_MASK_SIZE } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
@observer
export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -387,8 +388,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
1.0,
false,
undefined,
- undefined,
- color === 'transparent' ? highlightColor : undefined
+ undefined
);
const higlightMargin = Math.min(12, Math.max(2, 0.3 * inkStrokeWidth));
// Invisible polygonal line that enables the ink to be selected by the user.
@@ -415,8 +415,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
0.0,
false,
downHdlr,
- mask,
- highlightColor
+ mask
);
// bootsrap 3 style sheet sets line height to be 20px for default 14 point font size.
// this attempts to figure out the lineHeight ratio by inquiring the body's lineHeight and dividing by the fontsize which should yield 1.428571429
@@ -438,7 +437,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
<svg
className="inkStroke"
style={{
- transform: isInkMask ? `rotate(-${NumCast(this._props.CollectionFreeFormDocumentView?.()._props.rotation ?? 0)}deg) translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
+ transform: isInkMask ? `rotate(-${NumCast(this._props.LocalRotation?.() ?? 0)}deg) translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined,
// mixBlendMode: this.layoutDoc.tool === InkTool.Highlighter ? 'multiply' : 'unset',
cursor: this._props.isSelected() ? 'default' : undefined,
}}
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index ef4b5b4ca..c34554b56 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -4,7 +4,8 @@ import { Toggle, ToggleType, Type } from 'browndash-components';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../Utils';
+import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
import { Doc, DocListCast, FieldResult, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { InkTool } from '../../fields/InkField';
@@ -127,7 +128,9 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
DocumentManager.Instance.showDocument(target, { willZoomCentered: true, zoomScale: 0.9 });
if (this._history.lastElement().target !== target) this._history.push({ doc: lightDoc, target });
} else if (!target && this._path.length) {
- savedKeys.forEach(key => (lightDoc[key] = this._savedState[key]));
+ savedKeys.forEach(key => {
+ lightDoc[key] = this._savedState[key];
+ });
this._path.pop();
} else {
this.SetLightboxDoc(target);
@@ -239,7 +242,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
downx = e.clientX;
downy = e.clientY;
}}
- onClick={e => Utils.isClick(e.clientX, e.clientY, downx, downy, Date.now()) && this.SetLightboxDoc(undefined)}>
+ onClick={e => ClientUtils.isClick(e.clientX, e.clientY, downx, downy, Date.now()) && this.SetLightboxDoc(undefined)}>
<div
className="lightboxView-contents"
style={{
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 58b8d255a..8a060d0e0 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -7,7 +7,8 @@ import { action, computed, configure, makeObservable, observable, reaction, runI
import { observer } from 'mobx-react';
import * as React from 'react';
import '../../../node_modules/browndash-components/dist/styles/global.min.css';
-import { Utils, emptyFunction, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../Utils';
+import { ClientUtils, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
import { Doc, DocListCast, Opt } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { DocCast, StrCast } from '../../fields/Types';
@@ -18,10 +19,12 @@ import { Docs } from '../documents/Documents';
import { CalendarManager } from '../util/CalendarManager';
import { CaptureManager } from '../util/CaptureManager';
import { DocumentManager } from '../util/DocumentManager';
-import { DragManager, dropActionType } from '../util/DragManager';
+import { DragManager } from '../util/DragManager';
+import { dropActionType } from '../util/DropActionTypes';
import { GroupManager } from '../util/GroupManager';
import { HistoryUtil } from '../util/History';
import { Hypothesis } from '../util/HypothesisUtils';
+import { UPDATE_SERVER_CACHE } from '../util/LinkManager';
import { RTFMarkup } from '../util/RTFMarkup';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { SelectionManager } from '../util/SelectionManager';
@@ -57,7 +60,7 @@ import { AudioBox } from './nodes/AudioBox';
import { SchemaCSVPopUp } from './nodes/DataVizBox/SchemaCSVPopUp';
import { DocButtonState } from './nodes/DocumentLinksButton';
import { DocumentView, DocumentViewInternal, OpenWhere, OpenWhereMod, returnEmptyDocViewList } from './nodes/DocumentView';
-import { ImageBox, ImageEditorData as ImageEditor } from './nodes/ImageBox';
+import { ImageEditorData as ImageEditor } from './nodes/ImageBox';
import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
import { LinkDocPreview, LinkInfo } from './nodes/LinkDocPreview';
import { DirectionsAnchorMenu } from './nodes/MapBox/DirectionsAnchorMenu';
@@ -71,11 +74,13 @@ import { PresBox } from './nodes/trails';
import { AnchorMenu } from './pdf/AnchorMenu';
import { GPTPopup } from './pdf/GPTPopup/GPTPopup';
import { TopBar } from './topbar/TopBar';
-const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
+
const _global = (window /* browser */ || global) /* node */ as any;
+const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
@observer
export class MainView extends ObservableReactComponent<{}> {
+ // eslint-disable-next-line no-use-before-define
public static Instance: MainView;
public static Live: boolean = false;
private _docBtnRef = React.createRef<HTMLDivElement>();
@@ -117,8 +122,12 @@ export class MainView extends ObservableReactComponent<{}> {
}
@observable mainDoc: Opt<Doc> = undefined;
@computed private get mainContainer() {
- if (window.location.pathname.startsWith('/doc/') && Doc.CurrentUserEmail === 'guest') {
- DocServer.GetRefField(window.location.pathname.substring('/doc/'.length)).then(main => runInAction(() => (this.mainDoc = main as Doc)));
+ if (window.location.pathname.startsWith('/doc/') && ClientUtils.CurrentUserEmail === 'guest') {
+ DocServer.GetRefField(window.location.pathname.substring('/doc/'.length)).then(main =>
+ runInAction(() => {
+ this.mainDoc = main as Doc;
+ })
+ );
return this.mainDoc;
}
return this.userDoc ? Doc.ActiveDashboard : Doc.GuestDashboard;
@@ -165,7 +174,11 @@ export class MainView extends ObservableReactComponent<{}> {
scriptTag.async = true;
scriptTag.defer = true;
document.body.appendChild(scriptTag);
- document.getElementById('root')?.addEventListener('scroll', e => (ele => (ele.scrollLeft = ele.scrollTop = 0))(document.getElementById('root')!));
+ document.getElementById('root')?.addEventListener('scroll', () =>
+ (ele => {
+ ele.scrollLeft = ele.scrollTop = 0;
+ })(document.getElementById('root')!)
+ );
const ele = document.getElementById('loader');
const prog = document.getElementById('dash-progress');
if (ele && prog) {
@@ -174,7 +187,9 @@ export class MainView extends ObservableReactComponent<{}> {
prog.style.transition = '1s';
prog.style.width = '100%';
}, 0);
- setTimeout(() => (ele.outerHTML = ''), 1000);
+ setTimeout(() => {
+ ele.outerHTML = '';
+ }, 1000);
}
this._sidebarContent.proto = undefined;
if (!MainView.Live) {
@@ -202,7 +217,7 @@ export class MainView extends ObservableReactComponent<{}> {
'text_scrollHeight',
'text_height',
'hidden',
- //'type_collection',
+ // 'type_collection',
'chromeHidden',
'currentFrame',
]); // can play with these fields on someone else's
@@ -530,7 +545,7 @@ export class MainView extends ObservableReactComponent<{}> {
}
private longPressTimer: NodeJS.Timeout | undefined;
- globalPointerClick = action((e: any) => {
+ globalPointerClick = action(() => {
this.longPressTimer && clearTimeout(this.longPressTimer);
DocumentView.LongPress = false;
});
@@ -540,7 +555,9 @@ export class MainView extends ObservableReactComponent<{}> {
globalPointerDown = action((e: PointerEvent) => {
DocumentView.LongPress = false;
this.longPressTimer = setTimeout(
- action(() => (DocumentView.LongPress = true)),
+ action(() => {
+ DocumentView.LongPress = true;
+ }),
1000
);
DocumentManager.removeOverlayViews();
@@ -559,7 +576,7 @@ export class MainView extends ObservableReactComponent<{}> {
});
initEventListeners = () => {
- window.addEventListener('beforeunload', DocServer.UPDATE_SERVER_CACHE);
+ window.addEventListener('beforeunload', UPDATE_SERVER_CACHE);
window.addEventListener('drop', e => e.preventDefault(), false); // prevent default behavior of navigating to a new web page
window.addEventListener('dragover', e => e.preventDefault(), false);
document.addEventListener('pointerdown', this.globalPointerDown, true);
@@ -625,10 +642,10 @@ export class MainView extends ObservableReactComponent<{}> {
isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events)
isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive
ScreenToLocalTransform={this.headerBarScreenXf}
- childHideResizeHandles={true}
+ childHideResizeHandles
childDragAction={dropActionType.move}
- dontRegisterView={true}
- hideResizeHandles={true}
+ dontRegisterView
+ hideResizeHandles
PanelWidth={this.headerBarDocWidth}
PanelHeight={this.headerBarDocHeight}
renderDepth={0}
@@ -664,7 +681,7 @@ export class MainView extends ObservableReactComponent<{}> {
childFilters={returnEmptyFilter}
childFiltersByRanges={returnEmptyFilter}
searchFilterDocs={returnEmptyDoclist}
- suppressSetHeight={true}
+ suppressSetHeight
renderDepth={this._hideUI ? 0 : -1}
/>
</>
@@ -673,7 +690,7 @@ export class MainView extends ObservableReactComponent<{}> {
@computed get dockingContent() {
return (
- <GestureOverlay isActive={LightboxView.LightboxDoc ? false : true}>
+ <GestureOverlay isActive={!LightboxView.LightboxDoc}>
<div
key="docking"
className={`mainView-dockingContent${this._leftMenuFlyoutWidth ? '-flyout' : ''}`}
@@ -697,9 +714,16 @@ export class MainView extends ObservableReactComponent<{}> {
setupMoveUpEvents(
this,
e,
- action(e => ((SettingsManager.Instance.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false)),
- action(() => SettingsManager.Instance.propertiesWidth < 5 && (SettingsManager.Instance.propertiesWidth = 0)),
- action(() => (SettingsManager.Instance.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0)),
+ action(() => {
+ SettingsManager.Instance.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX);
+ return !SettingsManager.Instance.propertiesWidth;
+ }),
+ action(() => {
+ SettingsManager.Instance.propertiesWidth < 5 && (SettingsManager.Instance.propertiesWidth = 0);
+ }),
+ action(() => {
+ SettingsManager.Instance.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0;
+ }),
false
);
};
@@ -709,7 +733,10 @@ export class MainView extends ObservableReactComponent<{}> {
setupMoveUpEvents(
this,
e,
- action(e => ((this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false)),
+ action(e => {
+ this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0);
+ return false;
+ }),
() => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(),
this.closeFlyout
);
@@ -734,7 +761,7 @@ export class MainView extends ObservableReactComponent<{}> {
@computed get flyout() {
return !this._leftMenuFlyoutWidth ? (
- <div key="flyout" className={`mainView-libraryFlyout-out`}>
+ <div key="flyout" className="mainView-libraryFlyout-out">
{this.docButtons}
</div>
) : (
@@ -837,11 +864,9 @@ export class MainView extends ObservableReactComponent<{}> {
</div>
)}
<div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
- {
- <div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
- <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
- </div>
- }
+ <div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
+ <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
+ </div>
</div>
</div>
</div>
@@ -878,7 +903,7 @@ export class MainView extends ObservableReactComponent<{}> {
// generate the wrong value from getClientRectangle() -- specifically they return an 'x' that is the flyout's width greater than it should be.
// interactively adjusting the flyout fixes the problem. So does programmatically changing the value after a timeout to something *fractionally* different (ie, 1.5, not 1);)
this._leftMenuFlyoutWidth = this._leftMenuFlyoutWidth || 250;
- //setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5)));
+ // setTimeout(action(() => (this._leftMenuFlyoutWidth += 0.5)));
this._sidebarContent.proto = DocCast(button.target);
SettingsManager.Instance.SetLastPressedBtn(button);
@@ -897,7 +922,7 @@ export class MainView extends ObservableReactComponent<{}> {
buttonBarXf = () => {
if (!this._docBtnRef.current) return Transform.Identity();
- const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current);
+ const { scale, translateX, translateY } = ClientUtils.GetScreenTransform(this._docBtnRef.current);
return new Transform(-translateX, -translateY, 1 / scale);
};
@@ -940,9 +965,11 @@ export class MainView extends ObservableReactComponent<{}> {
<div className="mainView-snapLines">
<svg style={{ width: '100%', height: '100%' }}>
{SnappingManager.HorizSnapLines.map((l, i) => (
+ // eslint-disable-next-line react/no-array-index-key
<line key={i} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(dragPar.layoutDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray={'2 2'} />
))}
{SnappingManager.VertSnapLines.map((l, i) => (
+ // eslint-disable-next-line react/no-array-index-key
<line key={i} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(dragPar.layoutDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray={'2 2'} />
))}
</svg>
@@ -961,13 +988,14 @@ export class MainView extends ObservableReactComponent<{}> {
values="1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
- 0 0 0 1 0"></feColorMatrix>
- <feGaussianBlur in="color" stdDeviation="4" result="blur"></feGaussianBlur>
- <feOffset in="blur" dx="0" dy="0" result="offset"></feOffset>
+ 0 0 0 1 0"
+ />
+ <feGaussianBlur in="color" stdDeviation="4" result="blur" />
+ <feOffset in="blur" dx="0" dy="0" result="offset" />
<feMerge>
- <feMergeNode in="bg"></feMergeNode>
- <feMergeNode in="offset"></feMergeNode>
- <feMergeNode in="SourceGraphic"></feMergeNode>
+ <feMergeNode in="bg" />
+ <feMergeNode in="offset" />
+ <feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
@@ -984,7 +1012,11 @@ export class MainView extends ObservableReactComponent<{}> {
color: SettingsManager.userColor,
background: SettingsManager.userBackgroundColor,
}}
- onScroll={() => (ele => (ele.scrollTop = ele.scrollLeft = 0))(document.getElementById('root')!)}
+ onScroll={() =>
+ (ele => {
+ ele.scrollTop = ele.scrollLeft = 0;
+ })(document.getElementById('root')!)
+ }
ref={r => {
r &&
new _global.ResizeObserver(
@@ -1009,23 +1041,31 @@ export class MainView extends ObservableReactComponent<{}> {
<ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
{this._hideUI ? null : <TopBar />}
<LinkDescriptionPopup />
- {DocButtonState.Instance.LinkEditorDocView ? <LinkMenu clearLinkEditor={action(() => (DocButtonState.Instance.LinkEditorDocView = undefined))} docView={DocButtonState.Instance.LinkEditorDocView} /> : null}
- {LinkInfo.Instance?.LinkInfo ? <LinkDocPreview {...LinkInfo.Instance.LinkInfo} /> : null}
-
+ {DocButtonState.Instance.LinkEditorDocView ? (
+ <LinkMenu
+ clearLinkEditor={action(() => {
+ DocButtonState.Instance.LinkEditorDocView = undefined;
+ })}
+ docView={DocButtonState.Instance.LinkEditorDocView}
+ />
+ ) : null}
+ {LinkInfo.Instance?.LinkInfo ? (
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ <LinkDocPreview {...LinkInfo.Instance.LinkInfo} />
+ ) : null}
{((page: string) => {
// prettier-ignore
switch (page) {
- default:
- case 'dashboard': return (<>
+ case 'home': return <DashboardView />;
+ case 'dashboard':
+ default: return (<>
<div key="dashdiv" style={{ position: 'relative', display: this._hideUI || LightboxView.LightboxDoc ? 'none' : undefined, zIndex: 2001 }}>
<CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} toggleTopBar={this.toggleTopBar} topBarHeight={this.headerBarHeightFunc}/>
</div>
{this.mainDashboardArea}
</> );
- case 'home': return <DashboardView />;
}
})(Doc.ActivePage)}
-
<PreviewCursor />
<TaskCompletionBox />
<ContextMenu />
@@ -1049,15 +1089,19 @@ export class MainView extends ObservableReactComponent<{}> {
}
}
-ScriptingGlobals.add(function selectMainMenu(doc: Doc, title: string) {
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(function selectMainMenu(doc: Doc) {
MainView.Instance.selectMenu(doc);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function createNewPresentation() {
return MainView.Instance.createNewPresentation();
}, 'creates a new presentation when called');
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function openPresentation(pres: Doc) {
return MainView.Instance.openPresentation(pres);
}, 'creates a new presentation when called');
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function createNewFolder() {
return MainView.Instance.createNewFolder();
}, 'creates a new folder in myFiles when called');
diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx
index af7f38937..e52562625 100644
--- a/src/client/views/MainViewModal.tsx
+++ b/src/client/views/MainViewModal.tsx
@@ -1,7 +1,7 @@
import { isDark } from 'browndash-components';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import './MainViewModal.scss';
export interface MainViewOverlayProps {
@@ -43,7 +43,7 @@ export class MainViewModal extends React.Component<MainViewOverlayProps> {
className="overlay"
onClick={this.props?.closeOnExternalClick}
style={{
- backgroundColor: isDark(SettingsManager.userColor) ? '#DFDFDF30' : '#32323230',
+ backgroundColor: isDark(SnappingManager.userColor) ? '#DFDFDF30' : '#32323230',
...(p.overlayStyle || {}),
}}
/>
diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx
index 9fa20f642..f92bd68a3 100644
--- a/src/client/views/MarqueeAnnotator.tsx
+++ b/src/client/views/MarqueeAnnotator.tsx
@@ -14,8 +14,8 @@ import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
import './MarqueeAnnotator.scss';
import { DocumentView } from './nodes/DocumentView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import { AnchorMenu } from './pdf/AnchorMenu';
import { ObservableReactComponent } from './ObservableReactComponent';
+import { AnchorMenu } from './pdf/AnchorMenu';
const _global = (window /* browser */ || global) /* node */ as any;
export interface MarqueeAnnotatorProps {
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index 89c3c41f8..9626f1653 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -3,7 +3,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import * as Autosuggest from 'react-autosuggest';
import { emptyFunction, emptyPath } from '../../Utils';
-import { Doc, DocListCast, Field } from '../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType } from '../../fields/Doc';
import { undoBatch } from '../util/UndoManager';
import './MetadataEntryMenu.scss';
import { KeyValueBox } from './nodes/KeyValueBox';
@@ -12,7 +12,6 @@ export type DocLike = Doc | Doc[] | Promise<Doc> | Promise<Doc[]>;
export interface MetadataEntryProps {
docs: Doc[];
onError?: () => boolean;
- suggestWithFunction?: boolean;
}
@observer
@@ -35,10 +34,10 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps> {
};
previewValue = async () => {
- let field: Field | undefined | null = null;
+ let field: FieldType | undefined | null = null;
let onProto: boolean = false;
- let value: string | undefined = undefined;
- const docs = this.props.docs;
+ let value: string | undefined;
+ const { docs } = this.props;
for (const doc of docs) {
const v = await doc[this._currentKey];
onProto = onProto || !Object.keys(doc).includes(this._currentKey);
diff --git a/src/client/views/ObservableReactComponent.tsx b/src/client/views/ObservableReactComponent.tsx
index 394d1eae2..266411770 100644
--- a/src/client/views/ObservableReactComponent.tsx
+++ b/src/client/views/ObservableReactComponent.tsx
@@ -14,7 +14,10 @@ export abstract class ObservableReactComponent<T> extends React.Component<T, {}>
makeObservable(this);
}
componentDidUpdate(prevProps: Readonly<T>): void {
- Object.keys(prevProps).filter(pkey => (prevProps as any)[pkey] !== (this.props as any)[pkey]).forEach(action(pkey =>
- ((this._props as any)[pkey] = (this.props as any)[pkey]))); // prettier-ignore
+ Object.keys(prevProps)
+ .filter(pkey => (prevProps as any)[pkey] !== (this.props as any)[pkey])
+ .forEach(action(pkey => {
+ (this._props as any)[pkey] = (this.props as any)[pkey];
+ })); // prettier-ignore
}
}
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 15b1f0275..6539c0834 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -3,13 +3,15 @@ import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import * as React from 'react';
import ReactLoading from 'react-loading';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../ClientUtils';
+import { Utils, emptyFunction } from '../../Utils';
import { Doc } from '../../fields/Doc';
import { Height, Width } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { NumCast } from '../../fields/Types';
import { DocumentType } from '../documents/DocumentTypes';
-import { DragManager, dropActionType } from '../util/DragManager';
+import { DragManager } from '../util/DragManager';
+import { dropActionType } from '../util/DropActionTypes';
import { Transform } from '../util/Transform';
import { LightboxView } from './LightboxView';
import { ObservableReactComponent } from './ObservableReactComponent';
@@ -50,14 +52,14 @@ export class OverlayWindow extends ObservableReactComponent<OverlayWindowProps>
this.height = opts.height || 200;
}
- onPointerDown = (_: React.PointerEvent) => {
+ onPointerDown = () => {
document.removeEventListener('pointermove', this.onPointerMove);
document.removeEventListener('pointerup', this.onPointerUp);
document.addEventListener('pointermove', this.onPointerMove);
document.addEventListener('pointerup', this.onPointerUp);
};
- onResizerPointerDown = (_: React.PointerEvent) => {
+ onResizerPointerDown = () => {
document.removeEventListener('pointermove', this.onResizerPointerMove);
document.removeEventListener('pointerup', this.onResizerPointerUp);
document.addEventListener('pointermove', this.onResizerPointerMove);
@@ -95,12 +97,12 @@ export class OverlayWindow extends ObservableReactComponent<OverlayWindowProps>
<div className="overlayWindow-outerDiv" style={{ transform: `translate(${this.x}px, ${this.y}px)`, width: this.width, height: this.height }}>
<div className="overlayWindow-titleBar" onPointerDown={this.onPointerDown}>
{this._props.overlayOptions.title || 'Untitled'}
- <button onClick={this._props.onClick} className="overlayWindow-closeButton">
+ <button type="button" onClick={this._props.onClick} className="overlayWindow-closeButton">
X
</button>
</div>
<div className="overlayWindow-content">{this.props.children}</div>
- <div className="overlayWindow-resizeDragger" onPointerDown={this.onResizerPointerDown}></div>
+ <div className="overlayWindow-resizeDragger" onPointerDown={this.onResizerPointerDown} />
</div>
);
}
@@ -108,6 +110,7 @@ export class OverlayWindow extends ObservableReactComponent<OverlayWindowProps>
@observer
export class OverlayView extends ObservableReactComponent<{}> {
+ // eslint-disable-next-line no-use-before-define
public static Instance: OverlayView;
@observable.shallow _elements: JSX.Element[] = [];
@@ -118,8 +121,9 @@ export class OverlayView extends ObservableReactComponent<{}> {
OverlayView.Instance = this;
new _global.ResizeObserver(
action((entries: any) => {
- for (const entry of entries) {
- Doc.MyOverlayDocs.forEach(doc => {
+ Array.from(entries).forEach((entry: any) => {
+ Doc.MyOverlayDocs.forEach(docIn => {
+ const doc = docIn;
if (NumCast(doc.overlayX) > entry.contentRect.width - 10) {
doc.overlayX = entry.contentRect.width - 10;
}
@@ -127,7 +131,7 @@ export class OverlayView extends ObservableReactComponent<{}> {
doc.overlayY = entry.contentRect.height - 10;
}
});
- }
+ });
})
).observe(window.document.body);
}
@@ -162,7 +166,7 @@ export class OverlayView extends ObservableReactComponent<{}> {
const index = this._elements.indexOf(contents);
if (index !== -1) this._elements.splice(index, 1);
});
- contents = (
+ const wincontents = (
<OverlayWindow onClick={remove} key={Utils.GenerateGuid()} overlayOptions={options}>
{contents}
</OverlayWindow>
@@ -177,15 +181,16 @@ export class OverlayView extends ObservableReactComponent<{}> {
};
docScreenToLocalXf = computedFn(
+ // eslint-disable-next-line prefer-arrow-callback
function docScreenToLocalXf(this: any, doc: Doc) {
return () => new Transform(-NumCast(doc.overlayX), -NumCast(doc.overlayY), 1);
- }.bind(this)
+ }
);
@computed get overlayDocs() {
return Doc.MyOverlayDocs.filter(d => !LightboxView.LightboxDoc || d.type === DocumentType.PRES).map(d => {
- let offsetx = 0,
- offsety = 0;
+ let offsetx = 0;
+ let offsety = 0;
const dref = React.createRef<HTMLDivElement>();
const onPointerMove = action((e: PointerEvent, down: number[]) => {
if (e.cancelBubble) return false; // if the overlay doc processed the move event (e.g., to pan its contents), then the event should be marked as canceled since propagation can't be stopped
@@ -198,9 +203,7 @@ export class OverlayView extends ObservableReactComponent<{}> {
dragData.offset = [-offsetx, -offsety];
dragData.dropAction = dropActionType.move;
dragData.removeDocument = this.removeOverlayDoc;
- dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => {
- return dragData.removeDocument!(doc) ? addDocument(doc) : false;
- };
+ dragData.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => (dragData.removeDocument?.(doc) ? addDocument(doc) : false);
DragManager.StartDocumentDrag([dref.current!], dragData, down[0], down[1]);
return true;
}
@@ -227,7 +230,7 @@ export class OverlayView extends ObservableReactComponent<{}> {
PanelHeight={d[Height]}
ScreenToLocalTransform={this.docScreenToLocalXf(d)}
renderDepth={1}
- hideDecorations={true}
+ hideDecorations
isDocumentActive={returnTrue}
isContentActive={returnTrue}
whenChildContentsActiveChanged={emptyFunction}
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 4b7771f27..6d03034ec 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -1,7 +1,7 @@
import { action, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { lightOrDark, returnFalse } from '../../Utils';
+import { lightOrDark, returnFalse } from '../../ClientUtils';
import { Doc, Opt } from '../../fields/Doc';
import { DocUtils, Docs, DocumentOptions } from '../documents/Documents';
import { ImageUtils } from '../util/Import & Export/ImageUtils';
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 517a80d63..c7720d834 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -46,7 +46,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
propertyToggleBtn = (label: (on?: any) => string, property: string, tooltip: (on?: any) => string, icon: (on?: any) => any, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void, useUserDoc?: boolean) => {
const targetDoc = useUserDoc ? Doc.UserDoc() : this.selectedLayoutDoc;
- const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => ((dv?.layoutDoc || doc)[prop] = (dv?.layoutDoc || doc)[prop] ? false : true);
+ const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => ((dv?.layoutDoc || doc)[prop] = !(dv?.layoutDoc || doc)[prop]);
return !targetDoc ? null : (
<Toggle
toggleStatus={BoolCast(targetDoc[property])}
@@ -103,7 +103,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
(dv, doc) => {
const tdoc = dv?.Document || doc;
const newtitle = !tdoc._layout_showTitle ? 'title' : tdoc._layout_showTitle === 'title' ? 'title:hover' : '';
- tdoc._layout_showTitle = newtitle ? newtitle : undefined;
+ tdoc._layout_showTitle = newtitle || undefined;
}
);
}
@@ -181,9 +181,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
on => (on ? 'DISABLE FLASHCARD' : 'ENABLE FLASHCARD'),
'layout_textPainted',
on => `${on ? 'Flashcard enabled' : 'Flashcard disabled'} `,
- on => <MdTouchApp />,
+ () => <MdTouchApp />,
(dv, doc) => {
- const on = doc.onPaint ? true : false;
+ const on = !!doc.onPaint;
doc[DocData].onPaint = on ? undefined : ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, { documentView: 'any' });
doc[DocData].layout_textPainted = on ? undefined : `<ComparisonBox {...props} fieldKey={'${dv?.LayoutFieldKey ?? 'text'}'}/>`;
}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index ae29382c1..77e68866e 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1,3 +1,6 @@
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable prettier/prettier */
import { IconLookup } from '@fortawesome/fontawesome-svg-core';
import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -9,8 +12,9 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorResult, SketchPicker } from 'react-color';
import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils';
-import { Doc, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
+import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
+import { Doc, Field, FieldType, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
import { AclAdmin, DocAcl, DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { InkField } from '../../fields/InkField';
@@ -54,6 +58,7 @@ interface PropertiesViewProps {
export class PropertiesView extends ObservableReactComponent<PropertiesViewProps> {
private _widthUndo?: UndoManager.Batch;
+ // eslint-disable-next-line no-use-before-define
public static Instance: PropertiesView | undefined;
constructor(props: any) {
super(props);
@@ -101,7 +106,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@observable openTransform: boolean = true;
@observable openFilters: boolean = false;
- //Pres Trails booleans:
+ // Pres Trails booleans:
@observable openPresTransitions: boolean = true;
@observable openPresProgressivize: boolean = false;
@observable openPresVisibilityAndDuration: boolean = false;
@@ -183,35 +188,37 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
.forEach(key => doc[key] !== ComputedField.undefined && key && ids.add(key))
);
- // prettier-ignore
- Array.from(ids).sort().map(key => {
- const multiple = Array.from(docs.reduce((set,doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1;
- const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key);
- const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as Field);
- const contentElement = (
- <EditableView
- key="editableView"
- contents={displayContents}
- height={13}
- fontSize={10}
- GetValue={() => editableContents}
- SetValue={(value: string) => {
- value !== '-multiple-' && docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
- return true;
- }}
- />);
- rows.push(
- <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
- <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
- &nbsp;
- {contentElement}
- </div>
- );
- });
+ Array.from(ids)
+ .sort()
+ .forEach(key => {
+ const multiple = Array.from(docs.reduce((set, doc) => set.add(doc[key]), new Set<FieldResult>()).keys()).length > 1;
+ const editableContents = multiple ? '-multiple-' : Field.toKeyValueString(docs[0], key);
+ const displayContents = multiple ? '-multiple-' : Field.toString(docs[0][key] as FieldType);
+ const contentElement = (
+ <EditableView
+ key="editableView"
+ contents={displayContents}
+ height={13}
+ fontSize={10}
+ GetValue={() => editableContents}
+ SetValue={(value: string) => {
+ value !== '-multiple-' && docs.map(doc => KeyValueBox.SetField(doc, key, value, true));
+ return true;
+ }}
+ />
+ );
+ rows.push(
+ <div style={{ display: 'flex', overflowY: 'visible', marginBottom: '-1px' }} key={key}>
+ <span style={{ fontWeight: 'bold', whiteSpace: 'nowrap' }}>{key + ':'}</span>
+ &nbsp;
+ {contentElement}
+ </div>
+ );
+ });
rows.push(
<div className="propertiesView-field" key="newKeyValue" style={{ marginTop: '3px', backgroundColor: SettingsManager.userBackgroundColor, textAlign: 'center' }}>
- <EditableView key="editableView" oneLine contents={'add key:value or #tags'} height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
+ <EditableView key="editableView" oneLine contents="add key:value or #tags" height={13} fontSize={10} GetValue={() => ''} SetValue={this.setKeyValue} />
</div>
);
}
@@ -240,7 +247,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
KeyValueBox.SetField(doc, 'tags', `"${tags.replace(splits[0] + ':', '')}"`, true);
}
return true;
- } else if (value[0] === '#') {
+ }
+ if (value[0] === '#') {
const tags = StrListCast(doc.tags);
if (!tags.includes(value)) {
tags.push(value);
@@ -248,6 +256,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
return true;
}
+ return undefined;
});
return false;
};
@@ -256,7 +265,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
getTransform = () => this.transform;
propertiesDocViewRef = (ref: HTMLDivElement) => {
const observer = new _global.ResizeObserver(
- action((entries: any) => {
+ action(() => {
const cliRect = ref.getBoundingClientRect();
this.transform = new Transform(-cliRect.x, -cliRect.y, 1);
})
@@ -265,28 +274,27 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
};
@computed get contexts() {
- return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle={true} addDocTab={this._props.addDocTab} />;
+ return !this.selectedDoc ? null : <PropertiesDocContextSelector DocView={this.selectedDocumentView} hideTitle addDocTab={this._props.addDocTab} />;
}
@computed get contextCount() {
if (this.selectedDocumentView) {
const target = this.selectedDocumentView.Document;
return Doc.GetEmbeddings(target).length - 1;
- } else {
- return 0;
}
+ return 0;
}
@computed get links() {
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor ?? this.selectedDoc;
- return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle={true} addDocTab={this._props.addDocTab} />;
+ return !selAnchor ? null : <PropertiesDocBacklinksSelector Document={selAnchor} hideTitle addDocTab={this._props.addDocTab} />;
}
@computed get linkCount() {
const selAnchor = this.selectedDocumentView?.anchorViewDoc ?? LinkManager.Instance.currentLinkAnchor ?? this.selectedDoc;
- var counter = 0;
+ let counter = 0;
- LinkManager.Links(selAnchor).forEach((l, i) => counter++);
+ LinkManager.Links(selAnchor).forEach(() => counter++);
return counter;
}
@@ -308,7 +316,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
fitContentsToBox={returnTrue}
styleProvider={DefaultStyleProvider}
containerViewPath={returnEmptyDoclist}
- dontCenter={'y'}
+ dontCenter="y"
isDocumentActive={returnFalse}
isContentActive={emptyFunction}
NativeWidth={layoutDoc.type === DocumentType.RTF ? this.rtfWidth : undefined}
@@ -326,13 +334,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
whenChildContentsActiveChanged={emptyFunction}
addDocTab={returnFalse}
pinToPres={emptyFunction}
- dontRegisterView={true}
+ dontRegisterView
/>
</div>
);
- } else {
- return null;
}
+ return null;
}
/**
@@ -381,7 +388,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return (
<div className="expansion-button">
<IconButton
- icon={<FontAwesomeIcon icon={'ellipsis-h'} />}
+ icon={<FontAwesomeIcon icon="ellipsis-h" />}
size={Size.XSMALL}
color={SettingsManager.userColor}
onClick={action(() => {
@@ -398,7 +405,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
* @returns a row of the permissions panel
*/
sharingItem(name: string, admin: boolean, permission: string, showExpansionIcon?: boolean) {
- if (name == Doc.CurrentUserEmail) {
+ if (name === ClientUtils.CurrentUserEmail) {
name = 'Me';
}
return (
@@ -415,7 +422,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
{/* {name !== "Me" ? this.notifyIcon : null} */}
<div className="propertiesView-sharingTable-item-permission">
{this.colorACLDropDown(name, admin, permission, false)}
- {(permission === 'Owner' && name == 'Me') || showExpansionIcon ? this.expansionIcon : null}
+ {(permission === 'Owner' && name === 'Me') || showExpansionIcon ? this.expansionIcon : null}
</div>
</div>
);
@@ -425,10 +432,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
* @returns a colored dropdown bar reflective of the permission
*/
colorACLDropDown(name: string, admin: boolean, permission: string, showGuestOptions: boolean) {
- var shareImage = ReverseHierarchyMap.get(permission)?.image;
+ const shareImage = ReverseHierarchyMap.get(permission)?.image;
return (
<div>
- <div className={'propertiesView-shareDropDown'}>
+ <div className="propertiesView-shareDropDown">
<div className={`propertiesView-shareDropDown${permission}`}>
<div>{admin && permission !== 'Owner' ? this.getPermissionsSelect(name, permission, showGuestOptions) : concat(shareImage, ' ', permission)}</div>
</div>
@@ -440,9 +447,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
/**
* Sorting algorithm to sort users.
*/
- sortUsers = (u1: String, u2: String) => {
- return u1 > u2 ? -1 : u1 === u2 ? 0 : 1;
- };
+ sortUsers = (u1: String, u2: String) => (u1 > u2 ? -1 : u1 === u2 ? 0 : 1);
/**
* Sorting algorithm to sort groups.
@@ -468,35 +473,35 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const seldoc = this.layoutDocAcls ? this.selectedLayoutDoc : this.selectedDoc?.[DocData];
// adds each user to usersAdded
SharingManager.Instance.users.forEach(eachUser => {
- var userOnDoc = true;
+ let userOnDoc = true;
if (seldoc) {
if (Doc.GetT(seldoc, 'acl-' + normalizeEmail(eachUser.user.email), 'string', true) === '' || Doc.GetT(seldoc, 'acl-' + normalizeEmail(eachUser.user.email), 'string', true) === undefined) {
userOnDoc = false;
}
}
- if (userOnDoc && !usersAdded.includes(eachUser.user.email) && eachUser.user.email !== 'guest' && eachUser.user.email != target.author) {
+ if (userOnDoc && !usersAdded.includes(eachUser.user.email) && eachUser.user.email !== 'guest' && eachUser.user.email !== target.author) {
usersAdded.push(eachUser.user.email);
}
});
// sorts and then adds each user to the table
usersAdded.sort(this.sortUsers);
- usersAdded.map(userEmail => {
+ usersAdded.forEach(userEmail => {
const userKey = `acl-${normalizeEmail(userEmail)}`;
- var aclField = Doc.GetT(this.layoutDocAcls ? target : Doc.GetProto(target), userKey, 'string', true);
- var permission = StrCast(aclField);
+ const aclField = Doc.GetT(this.layoutDocAcls ? target : Doc.GetProto(target), userKey, 'string', true);
+ const permission = StrCast(aclField);
individualTableEntries.unshift(this.sharingItem(userEmail, showAdmin, permission!, false)); // adds each user
});
// adds current user
- var userEmail = Doc.CurrentUserEmail;
- if (userEmail == 'guest') userEmail = 'Guest';
+ let userEmail = ClientUtils.CurrentUserEmail;
+ if (userEmail === 'guest') userEmail = 'Guest';
const userKey = `acl-${normalizeEmail(userEmail)}`;
- if (!usersAdded.includes(userEmail) && userEmail !== 'Guest' && userEmail != target.author) {
- var permission;
+ if (!usersAdded.includes(userEmail) && userEmail !== 'Guest' && userEmail !== target.author) {
+ let permission;
if (this.layoutDocAcls) {
if (target[DocAcl][userKey]) permission = HierarchyMapping.get(target[DocAcl][userKey])?.name;
- else if (target['embedContainer']) permission = StrCast(Doc.GetProto(DocCast(target['embedContainer']))[userKey]);
+ else if (target.embedContainer) permission = StrCast(Doc.GetProto(DocCast(target.embedContainer))[userKey]);
else permission = StrCast(Doc.GetProto(target)?.[userKey]);
} else permission = StrCast(target[userKey]);
individualTableEntries.unshift(this.sharingItem(userEmail, showAdmin, permission!, false)); // adds each user
@@ -509,15 +514,15 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const groupTableEntries: JSX.Element[] = [];
const groupList = GroupManager.Instance?.allGroups || [];
groupList.sort(this.sortGroups);
- groupList.map(group => {
- if (group.title != 'Guest' && this.selectedDoc) {
+ groupList.forEach(group => {
+ if (group.title !== 'Guest' && this.selectedDoc) {
const groupKey = 'acl-' + normalizeEmail(StrCast(group.title));
- if (this.selectedDoc[groupKey] != '' && this.selectedDoc[groupKey] != undefined) {
- var permission;
+ if (this.selectedDoc[groupKey] !== '' && this.selectedDoc[groupKey] !== undefined) {
+ let permission;
if (this.layoutDocAcls) {
if (target[DocAcl][groupKey]) {
permission = HierarchyMapping.get(target[DocAcl][groupKey])?.name;
- } else if (target['embedContainer']) permission = StrCast(Doc.GetProto(DocCast(target['embedContainer']))[groupKey]);
+ } else if (target.embedContainer) permission = StrCast(Doc.GetProto(DocCast(target.embedContainer))[groupKey]);
else permission = StrCast(Doc.GetProto(target)?.[groupKey]);
} else permission = StrCast(target[groupKey]);
groupTableEntries.unshift(this.sharingItem(StrCast(group.title), showAdmin, permission!, false));
@@ -531,22 +536,22 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return (
<div>
<div>
- <br></br> Individuals with Access to this Document
+ <br /> Individuals with Access to this Document
</div>
<div className="propertiesView-sharingTable" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
- {<div> {individualTableEntries}</div>}
+ <div> {individualTableEntries}</div>
</div>
{groupTableEntries.length > 0 ? (
<div>
<div>
- <br></br> Groups with Access to this Document
+ <br /> Groups with Access to this Document
</div>
<div className="propertiesView-sharingTable" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
- {<div> {groupTableEntries}</div>}
+ <div> {groupTableEntries}</div>
</div>
</div>
) : null}
- <br></br> Guest
+ <br /> Guest
<div>{this.colorACLDropDown('Guest', showAdmin, guestPermission!, true)}</div>
</div>
);
@@ -558,7 +563,9 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@action
- toggleCheckbox = () => (this.layoutFields = !this.layoutFields);
+ toggleCheckbox = () => {
+ this.layoutFields = !this.layoutFields;
+ };
@computed get color() {
return SettingsManager.userColor;
@@ -578,21 +585,17 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
return (
<div>
- <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />
+ <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel="Title" fillWidth />
{LinkManager.Instance.currentLinkAnchor ? (
<p className="propertiesView-titleExtender">
- <>
- <b>Anchor:</b>
- {LinkManager.Instance.currentLinkAnchor.title}
- </>
+ <b>Anchor:</b>
+ {StrCast(LinkManager.Instance.currentLinkAnchor.title)}
</p>
) : null}
{this.selectedLink?.title ? (
<p className="propertiesView-titleExtender">
- <>
- <b>Link:</b>
- {this.selectedLink.title}
- </>
+ <b>Link:</b>
+ {StrCast(this.selectedLink.title)}
</p>
) : null}
</div>
@@ -601,8 +604,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get currentType() {
const documentType = StrCast(this.selectedDoc?.type);
- var currentType: string = documentType;
- var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType);
+ const currentType: string = documentType;
+ const capitalizedDocType = ClientUtils.cleanDocumentType(currentType as DocumentType);
return (
<div>
@@ -618,7 +621,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get currentComponent() {
- var iconName = StrCast(this.selectedDoc?.systemIcon);
+ const iconName = StrCast(this.selectedDoc?.systemIcon);
if (iconName) {
const Icon = Icons[iconName as keyof typeof Icons];
@@ -650,13 +653,11 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
const ys = ink.map(p => p.Y);
const left = Math.min(...xs);
const top = Math.min(...ys);
- const right = Math.max(...xs);
- const bottom = Math.max(...ys);
_centerPoints.push({ X: left, Y: top });
}
}
- var index = 0;
+ let index = 0;
if (doc.type === DocumentType.INK && doc.x && doc.y && layout._width && layout._height && doc.data) {
layout.rotation = NumCast(layout.rotation) + angle;
const inks = Cast(doc.stroke, InkField)?.inkData;
@@ -687,11 +688,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
get controlPointsButton() {
return (
<div className="inking-button">
- <Tooltip title={<div className="dash-tooltip">{'Edit points'}</div>}>
+ <Tooltip title={<div className="dash-tooltip">Edit points</div>}>
<div
className="inking-button-points"
style={{ backgroundColor: InkStrokeProperties.Instance._controlButton ? 'black' : '' }}
- onPointerDown={action(() => (InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton))}>
+ onPointerDown={action(() => {
+ InkStrokeProperties.Instance._controlButton = !InkStrokeProperties.Instance._controlButton;
+ })}>
<FontAwesomeIcon icon="bezier-curve" size="lg" />
</div>
</Tooltip>
@@ -699,152 +702,129 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
);
}
- inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => {
- return (
- <div
- className="inputBox"
- style={{
- marginRight: title === 'X:' ? '19px' : '',
- marginLeft: title === '∠:' ? '39px' : '',
- }}>
- <div className="inputBox-title"> {title} </div>
- <input
- className="inputBox-input"
- type="text"
- value={value}
- style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
- onChange={e => setter(e.target.value)}
- onKeyDown={e => e.stopPropagation()}
- />
- <div className="inputBox-button">
- <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
- <FontAwesomeIcon icon="caret-up" size="sm" />
- </div>
- <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
- <FontAwesomeIcon icon="caret-down" size="sm" />
- </div>
+ inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => (
+ <div
+ className="inputBox"
+ style={{
+ marginRight: title === 'X:' ? '19px' : '',
+ marginLeft: title === '∠:' ? '39px' : '',
+ }}>
+ <div className="inputBox-title"> {title} </div>
+ <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} onKeyDown={e => e.stopPropagation()} />
+ <div className="inputBox-button">
+ <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
+ <FontAwesomeIcon icon="caret-up" size="sm" />
+ </div>
+ <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
+ <FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
- );
- };
+ </div>
+ );
- inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
- return (
- <div className="inputBox-duo">
- {this.inputBox(key, value, setter, title1)}
- {title2 === '' ? null : this.inputBox(key2, value2, setter2, title2)}
- </div>
- );
- };
+ inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => (
+ <div className="inputBox-duo">
+ {this.inputBox(key, value, setter, title1)}
+ {title2 === '' ? null : this.inputBox(key2, value2, setter2, title2)}
+ </div>
+ );
@action
upDownButtons = (dirs: string, field: string) => {
const selDoc = this.selectedDoc;
if (!selDoc) return;
- //prettier-ignore
+ // prettier-ignore
switch (field) {
case 'Xps': selDoc.x = NumCast(this.selectedDoc?.x) + (dirs === 'up' ? 10 : -10); break;
case 'Yps': selDoc.y = NumCast(this.selectedDoc?.y) + (dirs === 'up' ? 10 : -10); break;
case 'stk': selDoc.stroke_width = NumCast(this.selectedDoc?.[DocData].stroke_width) + (dirs === 'up' ? 0.1 : -0.1); break;
- case 'wid':
- const oldWidth = NumCast(selDoc._width);
- const oldHeight = NumCast(selDoc._height);
- const oldX = NumCast(selDoc.x);
- const oldY = NumCast(selDoc.y);
- selDoc._width = oldWidth + (dirs === 'up' ? 10 : -10);
- if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
- const ink = Cast(selDoc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number; Y: number }[] = [];
- for (var j = 0; j < ink.length; j++) {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = NumCast(selDoc.x) - oldX + (ink[j].X * NumCast(selDoc._width)) / oldWidth;
- const newY = NumCast(selDoc.y) - oldY + (ink[j].Y * NumCast(selDoc._height)) / oldHeight;
- newPoints.push({ X: newX, Y: newY });
+ case 'wid': {
+ const oldWidth = NumCast(selDoc._width);
+ const oldHeight = NumCast(selDoc._height);
+ const oldX = NumCast(selDoc.x);
+ const oldY = NumCast(selDoc.y);
+ selDoc._width = oldWidth + (dirs === 'up' ? 10 : -10);
+ if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
+ const ink = Cast(selDoc.data, InkField)?.inkData;
+ if (ink) {
+ const newPoints: { X: number; Y: number }[] = [];
+ for (let j = 0; j < ink.length; j++) {
+ // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
+ const newX = NumCast(selDoc.x) - oldX + (ink[j].X * NumCast(selDoc._width)) / oldWidth;
+ const newY = NumCast(selDoc.y) - oldY + (ink[j].Y * NumCast(selDoc._height)) / oldHeight;
+ newPoints.push({ X: newX, Y: newY });
+ }
+ selDoc.data = new InkField(newPoints);
}
- selDoc.data = new InkField(newPoints);
}
}
break;
- case 'hgt':
- const oWidth = NumCast(selDoc._width);
- const oHeight = NumCast(selDoc._height);
- const oX = NumCast(selDoc.x);
- const oY = NumCast(selDoc.y);
- selDoc._height = oHeight + (dirs === 'up' ? 10 : -10);
- if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
- const ink = Cast(selDoc.data, InkField)?.inkData;
- if (ink) {
- const newPoints: { X: number; Y: number }[] = [];
- for (var j = 0; j < ink.length; j++) {
- // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
- const newX = NumCast(selDoc.x) - oX + (ink[j].X * NumCast(selDoc._width)) / oWidth;
- const newY = NumCast(selDoc.y) - oY + (ink[j].Y * NumCast(selDoc._height)) / oHeight;
- newPoints.push({ X: newX, Y: newY });
+ case 'hgt': {
+ const oWidth = NumCast(selDoc._width);
+ const oHeight = NumCast(selDoc._height);
+ const oX = NumCast(selDoc.x);
+ const oY = NumCast(selDoc.y);
+ selDoc._height = oHeight + (dirs === 'up' ? 10 : -10);
+ if (selDoc.type === DocumentType.INK && selDoc.x && selDoc.y && selDoc._height && selDoc._width) {
+ const ink = Cast(selDoc.data, InkField)?.inkData;
+ if (ink) {
+ const newPoints: { X: number; Y: number }[] = [];
+ for (let j = 0; j < ink.length; j++) {
+ // (new x — oldx) + (oldxpoint * newWidt)/oldWidth
+ const newX = NumCast(selDoc.x) - oX + (ink[j].X * NumCast(selDoc._width)) / oWidth;
+ const newY = NumCast(selDoc.y) - oY + (ink[j].Y * NumCast(selDoc._height)) / oHeight;
+ newPoints.push({ X: newX, Y: newY });
+ }
+ selDoc.data = new InkField(newPoints);
}
- selDoc.data = new InkField(newPoints);
}
}
break;
+ default: { /* empty */ }
}
};
getField(key: string) {
- return Field.toString(this.selectedDoc?.[DocData][key] as Field);
+ return Field.toString(this.selectedDoc?.[DocData][key] as FieldType);
}
- @computed get shapeXps() {
- return NumCast(this.selectedDoc?.x);
- }
- @computed get shapeYps() {
- return NumCast(this.selectedDoc?.y);
- }
- @computed get shapeHgt() {
- return NumCast(this.selectedDoc?._height);
- }
- @computed get shapeWid() {
- return NumCast(this.selectedDoc?._width);
- }
- @computed get strokeThk() {
- return NumCast(this.selectedDoc?.[DocData].stroke_width);
- }
- set shapeXps(value) {
- this.selectedDoc && (this.selectedDoc.x = Math.round(value * 100) / 100);
- }
- set shapeYps(value) {
- this.selectedDoc && (this.selectedDoc.y = Math.round(value * 100) / 100);
- }
- set shapeWid(value) {
- this.selectedDoc && (this.selectedDoc._width = Math.round(value * 100) / 100);
- }
- set shapeHgt(value) {
- this.selectedDoc && (this.selectedDoc._height = Math.round(value * 100) / 100);
- }
- set strokeThk(value) {
- this.selectedDoc && (this.selectedDoc[DocData].stroke_width = Math.round(value * 100) / 100);
- }
+ @computed get shapeXps() { return NumCast(this.selectedDoc?.x); } // prettier-ignore
+ set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get shapeYps() { return NumCast(this.selectedDoc?.y); } // prettier-ignore
+ set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get shapeWid() { return NumCast(this.selectedDoc?._width); } // prettier-ignore
+ set shapeWid(value) { this.selectedDoc && (this.selectedDoc._width = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get shapeHgt() { return NumCast(this.selectedDoc?._height); } // prettier-ignore
+ set shapeHgt(value) { this.selectedDoc && (this.selectedDoc._height = Math.round(value * 100) / 100); } // prettier-ignore
+ @computed get strokeThk(){ return NumCast(this.selectedDoc?.[DocData].stroke_width); } // prettier-ignore
+ set strokeThk(value) { this.selectedDoc && (this.selectedDoc[DocData].stroke_width = Math.round(value * 100) / 100); } // prettier-ignore
@computed get hgtInput() {
return this.inputBoxDuo(
'hgt',
this.shapeHgt,
- undoable((val: string) => !isNaN(Number(val)) && (this.shapeHgt = +val), 'set height'),
+ undoable((val: string) => {
+ !Number(val) && (this.shapeHgt = +val);
+ }, 'set height'),
'H:',
'wid',
this.shapeWid,
- undoable((val: string) => !isNaN(Number(val)) && (this.shapeWid = +val), 'set width'),
+ undoable((val: string) => {
+ !isNaN(Number(val)) && (this.shapeWid = +val);
+ }, 'set width'),
'W:'
);
}
@computed get XpsInput() {
+ // prettier-ignore
return this.inputBoxDuo(
'Xps',
this.shapeXps,
- undoable((val: string) => val !== '0' && !isNaN(Number(val)) && (this.shapeXps = +val), 'set x coord'),
+ undoable((val: string) => { val !== '0' && !isNaN(Number(val)) && (this.shapeXps = +val); }, 'set x coord'),
'X:',
'Yps',
this.shapeYps,
- undoable((val: string) => val !== '0' && !isNaN(Number(val)) && (this.shapeYps = +val), 'set y coord'),
+ undoable((val: string) => { val !== '0' && !isNaN(Number(val)) && (this.shapeYps = +val); }, 'set y coord'),
'Y:'
);
}
@@ -854,18 +834,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
private _lastDash: any = '2';
- @computed get colorFil() {
- return StrCast(this.selectedDoc?.[DocData].fillColor);
- }
- @computed get colorStk() {
- return StrCast(this.selectedDoc?.[DocData].color);
- }
- set colorFil(value) {
- this.selectedDoc && (this.selectedDoc[DocData].fillColor = value ? value : undefined);
- }
- set colorStk(value) {
- this.selectedDoc && (this.selectedDoc[DocData].color = value ? value : undefined);
- }
+ @computed get colorFil() { return StrCast(this.selectedDoc?.[DocData].fillColor); } // prettier-ignore
+ set colorFil(value) { this.selectedDoc && (this.selectedDoc[DocData].fillColor = value || undefined); } // prettier-ignore
+ @computed get colorStk() { return StrCast(this.selectedDoc?.[DocData].color); } // prettier-ignore
+ set colorStk(value) { this.selectedDoc && (this.selectedDoc[DocData].color = value || undefined); } // prettier-ignore
colorButton(value: string, type: string, setter: () => void) {
return (
@@ -886,11 +858,9 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
colorPicker(color: string, setter: (color: string) => void) {
return (
+ // prettier-ignore
<SketchPicker
- onChange={undoable(
- action((color: ColorResult) => setter(color.hex)),
- 'set stroke color property'
- )}
+ onChange={undoable( action((color: ColorResult) => setter(color.hex)), 'set stroke color property' )}
presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
color={color}
/>
@@ -911,10 +881,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get fillPicker() {
- return this.colorPicker(this.colorFil, (color: string) => (this.colorFil = color));
+ return this.colorPicker(this.colorFil, (color: string) => { this.colorFil = color; }); // prettier-ignore
}
@computed get linePicker() {
- return this.colorPicker(this.colorStk, (color: string) => (this.colorStk = color));
+ return this.colorPicker(this.colorStk, (color: string) => { this.colorStk = color; }); // prettier-ignore
}
@computed get strokeAndFill() {
@@ -936,60 +906,48 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
);
}
- @computed get dashdStk() {
- return this.selectedDoc?.stroke_dash || '';
- }
- @computed get widthStk() {
- return this.getField('stroke_width') || '1';
- }
- @computed get markScal() {
- return Number(this.getField('stroke_markerScale') || '1');
- }
- @computed get markHead() {
- return this.getField('stroke_startMarker') || '';
- }
- @computed get markTail() {
- return this.getField('stroke_endMarker') || '';
- }
+ @computed get dashdStk() { return this.selectedDoc?.stroke_dash || ''; } // prettier-ignore
set dashdStk(value) {
value && (this._lastDash = value);
this.selectedDoc && (this.selectedDoc[DocData].stroke_dash = value ? this._lastDash : undefined);
}
- set markScal(value) {
- this.selectedDoc && (this.selectedDoc[DocData].stroke_markerScale = Number(value));
- }
+ @computed get widthStk() { return this.getField('stroke_width') || '1'; } // prettier-ignore
set widthStk(value) {
this.selectedDoc && (this.selectedDoc[DocData].stroke_width = Number(value));
}
+ @computed get markScal() { return Number(this.getField('stroke_markerScale') || '1'); } // prettier-ignore
+ set markScal(value) {
+ this.selectedDoc && (this.selectedDoc[DocData].stroke_markerScale = Number(value));
+ }
+ @computed get markHead() { return this.getField('stroke_startMarker') || ''; } // prettier-ignore
set markHead(value) {
this.selectedDoc && (this.selectedDoc[DocData].stroke_startMarker = value);
}
+ @computed get markTail() { return this.getField('stroke_endMarker') || ''; } // prettier-ignore
set markTail(value) {
this.selectedDoc && (this.selectedDoc[DocData].stroke_endMarker = value);
}
@computed get stkInput() {
- return this.regInput('stk', this.widthStk, (val: string) => (this.widthStk = val));
+ return this.regInput('stk', this.widthStk, (val: string) => { this.widthStk = val; }); // prettier-ignore
}
@computed get markScaleInput() {
- return this.regInput('scale', this.markScal.toString(), (val: string) => (this.markScal = Number(val)));
+ return this.regInput('scale', this.markScal.toString(), (val: string) => { this.markScal = Number(val); }); // prettier-ignore
}
- regInput = (key: string, value: any, setter: (val: string) => {}) => {
- return (
- <div className="inputBox">
- <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} />
- <div className="inputBox-button">
- <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
- <FontAwesomeIcon icon="caret-up" size="sm" />
- </div>
- <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
- <FontAwesomeIcon icon="caret-down" size="sm" />
- </div>
+ regInput = (key: string, value: any, setter: (val: string) => {}) => (
+ <div className="inputBox">
+ <input className="inputBox-input" type="text" value={value} style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} onChange={e => setter(e.target.value)} />
+ <div className="inputBox-button">
+ <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
+ <FontAwesomeIcon icon="caret-up" size="sm" />
+ </div>
+ <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
+ <FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
- );
- };
+ </div>
+ );
@action
CloseAll = () => {
@@ -1005,18 +963,55 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get widthAndDash() {
return (
+ // prettier-ignore
<div className="widthAndDash">
- <div className="width">{this.getNumber('Thickness', '', 0, Math.max(50, this.strokeThk), this.strokeThk, (val: number) => !isNaN(val) && (this.strokeThk = val), 50, 1)}</div>
- <div className="width">{this.getNumber('Arrow Scale', '', 0, Math.max(10, this.markScal), this.markScal, (val: number) => !isNaN(val) && (this.markScal = val), 10, 1)}</div>
+ <div className="width">
+ {this.getNumber(
+ 'Thickness',
+ '',
+ 0,
+ Math.max(50, this.strokeThk),
+ this.strokeThk,
+ (val: number) => { !isNaN(val) && (this.strokeThk = val); },
+ 50,
+ 1
+ )}
+ </div>
+ <div className="width">
+ {this.getNumber(
+ 'Arrow Scale',
+ '',
+ 0,
+ Math.max(10, this.markScal),
+ this.markScal,
+ (val: number) => { !isNaN(val) && (this.markScal = val); },
+ 10,
+ 1
+ )}
+ </div>
<div className="arrows">
<div className="arrows-head">
<div className="arrows-head-title">Arrow Head: </div>
- <input key="markHead" className="arrows-head-input" type="checkbox" checked={this.markHead !== ''} onChange={undoBatch(action(() => (this.markHead = this.markHead ? '' : 'arrow')))} />
+ <input
+ key="markHead"
+ className="arrows-head-input"
+ type="checkbox"
+ checked={this.markHead !== ''}
+ onChange={undoBatch(action(() => { this.markHead = this.markHead ? '' : 'arrow'; }))}
+ />
</div>
<div className="arrows-tail">
<div className="arrows-tail-title">Arrow End: </div>
- <input key="markTail" className="arrows-tail-input" type="checkbox" checked={this.markTail !== ''} onChange={undoBatch(action(() => (this.markTail = this.markTail ? '' : 'arrow')))} />
+ <input
+ key="markTail"
+ className="arrows-tail-input"
+ type="checkbox"
+ checked={this.markTail !== ''}
+ onChange={undoBatch(
+ action(() => { this.markTail = this.markTail ? '' : 'arrow'; })
+ )}
+ />
</div>
</div>
<div className="dashed">
@@ -1045,50 +1040,53 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
setFinalNumber = () => {
this._sliderBatch?.end();
};
- getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any, autorange?: number, autorangeMinVal?: number) => {
- return (
- <div key={label + this.selectedDoc?.title}>
- <NumberInput formLabel={label} formLabelPlacement={'left'} type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} />
- <Slider
- key={label}
- onPointerDown={e => (this._sliderBatch = UndoManager.StartBatch('slider ' + label))}
- multithumb={false}
- color={this.color}
- size={Size.XSMALL}
- min={min}
- max={max}
- autorangeMinVal={autorangeMinVal}
- autorange={autorange}
- number={number}
- unit={unit}
- decimals={1}
- setFinalNumber={this.setFinalNumber}
- setNumber={setNumber}
- fillWidth
- />
- </div>
- );
- };
+ getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any, autorange?: number, autorangeMinVal?: number) => (
+ <div key={label + (this.selectedDoc?.title ?? '')}>
+ <NumberInput formLabel={label} formLabelPlacement="left" type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} />
+ <Slider
+ key={label}
+ onPointerDown={() => {
+ this._sliderBatch = UndoManager.StartBatch('slider ' + label);
+ }}
+ multithumb={false}
+ color={this.color}
+ size={Size.XSMALL}
+ min={min}
+ max={max}
+ autorangeMinVal={autorangeMinVal}
+ autorange={autorange}
+ number={number}
+ unit={unit}
+ decimals={1}
+ setFinalNumber={this.setFinalNumber}
+ setNumber={setNumber}
+ fillWidth
+ />
+ </div>
+ );
+ setVal = (func: (doc: Doc, val: number) => void) => (val: number) => this.selectedDoc && !isNaN(val) && func(this.selectedDoc, val);
@computed get transformEditor() {
return (
+ // prettier-ignore
<div className="transform-editor">
- {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), (val: number) => !isNaN(val) && (this.selectedDoc!.gridGap = val))}
- {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.xMargin = val))}
- {!this.isStack ? null : this.getNumber('yMargin', ' px', 0, 500, NumCast(this.selectedDoc!.yMargin), (val: number) => !isNaN(val) && (this.selectedDoc!.yMargin = val))}
- {!this.isGroup ? null : this.getNumber('Padding', ' px', 0, 500, NumCast(this.selectedDoc!.xPadding), (val: number) => !isNaN(val) && (this.selectedDoc!.xPadding = this.selectedDoc!.yPadding = val))}
+ {!this.isStack ? null : this.getNumber('Gap', ' px', 0, 200, NumCast(this.selectedDoc!.gridGap), this.setVal((doc: Doc, val: number) => { doc.gridGap = val; })) }
+ {!this.isStack ? null : this.getNumber('xMargin', ' px', 0, 500, NumCast(this.selectedDoc!.xMargin), this.setVal((doc: Doc, val: number) => { doc.xMargin = val; })) }
+ {!this.isStack ? null : this.getNumber('yMargin', ' px', 0, 500, NumCast(this.selectedDoc!.yMargin), this.setVal((doc: Doc, val: number) => { doc.yMargin = val; })) }
+ {!this.isGroup ? null : this.getNumber('Padding', ' px', 0, 500, NumCast(this.selectedDoc!.xPadding), this.setVal((doc: Doc, val: number) => { doc.xPadding = doc.yPadding = val; })) }
{this.isInk ? this.controlPointsButton : null}
- {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, (val: number) => !isNaN(val) && (this.shapeWid = val), 1000, 1)}
- {this.getNumber('Height', ' px', 0, Math.max(1000, this.shapeHgt), this.shapeHgt, (val: number) => !isNaN(val) && (this.shapeHgt = val), 1000, 1)}
- {this.getNumber('X', ' px', this.shapeXps - 500, this.shapeXps + 500, this.shapeXps, (val: number) => !isNaN(val) && (this.shapeXps = val), 1000)}
- {this.getNumber('Y', ' px', this.shapeYps - 500, this.shapeYps + 500, this.shapeYps, (val: number) => !isNaN(val) && (this.shapeYps = val), 1000)}
+ {this.getNumber('Width', ' px', 0, Math.max(1000, this.shapeWid), this.shapeWid, this.setVal((doc: Doc, val:number) => {this.shapeWid = val}), 1000, 1)}
+ {this.getNumber('Height', ' px', 0, Math.max(1000, this.shapeHgt), this.shapeHgt, this.setVal((doc: Doc, val:number) => {this.shapeHgt = val}), 1000, 1)}
+ {this.getNumber('X', ' px', this.shapeXps - 500, this.shapeXps + 500, this.shapeXps, this.setVal((doc: Doc, val:number) => {this.shapeXps = val}), 1000)}
+ {this.getNumber('Y', ' px', this.shapeYps - 500, this.shapeYps + 500, this.shapeYps, this.setVal((doc: Doc, val:number) => {this.shapeYps = val}), 1000)}
</div>
);
}
@computed get optionsSubMenu() {
return (
- <PropertiesSection title="Options" inSection={this.inOptions} isOpen={this.openOptions} setInSection={bool => (this.inOptions = bool)} setIsOpen={bool => (this.openOptions = bool)} onDoubleClick={this.CloseAll}>
+ // prettier-ignore
+ <PropertiesSection title="Options" inSection={this.inOptions} isOpen={this.openOptions} setInSection={bool => { this.inOptions = bool; }} setIsOpen={bool => { this.openOptions = bool; }} onDoubleClick={this.CloseAll}>
<PropertiesButtons />
</PropertiesSection>
);
@@ -1096,12 +1094,23 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get sharingSubMenu() {
return (
- <PropertiesSection title="Sharing and Permissions" isOpen={this.openSharing} setIsOpen={bool => (this.openSharing = bool)} onDoubleClick={() => this.CloseAll()}>
+ // prettier-ignore
+ <PropertiesSection
+ title="Sharing and Permissions"
+ isOpen={this.openSharing}
+ setIsOpen={bool => { this.openSharing = bool; }}
+ onDoubleClick={this.CloseAll}>
<>
{/* <div className="propertiesView-buttonContainer"> */}
<div className="propertiesView-acls-checkbox">
Layout Permissions
- <Checkbox color="primary" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} />
+ <Checkbox
+ color="primary"
+ onChange={action(() => {
+ this.layoutDocAcls = !this.layoutDocAcls;
+ })}
+ checked={this.layoutDocAcls}
+ />
</div>
{/* <Tooltip title={<><div className="dash-tooltip">{"Re-distribute sharing settings"}</div></>}>
<button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}>
@@ -1141,7 +1150,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get filtersSubMenu() {
return (
- <PropertiesSection title="Filters" isOpen={this.openFilters} setIsOpen={bool => (this.openFilters = bool)} onDoubleClick={() => this.CloseAll()}>
+ // prettier-ignore
+ <PropertiesSection title="Filters" isOpen={this.openFilters} setIsOpen={bool => { this.openFilters = bool; }} onDoubleClick={this.CloseAll}>
<div className="propertiesView-content filters" style={{ position: 'relative', height: 'auto' }}>
<FilterPanel Document={this.selectedDoc ?? Doc.ActiveDashboard!} />
</div>
@@ -1151,11 +1161,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get inkSubMenu() {
return (
+ // prettier-ignore
<>
- <PropertiesSection title="Appearance" isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection title="Appearance" isOpen={this.openAppearance} setIsOpen={bool => { this.openAppearance = bool; }} onDoubleClick={this.CloseAll}>
{this.selectedLayoutDoc?.layout_isSvg ? this.appearanceEditor : null}
</PropertiesSection>
- <PropertiesSection title="Transform" isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection title="Transform" isOpen={this.openTransform} setIsOpen={bool => { this.openTransform = bool; }} onDoubleClick={this.CloseAll}>
{this.transformEditor}
</PropertiesSection>
</>
@@ -1164,7 +1175,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get fieldsSubMenu() {
return (
- <PropertiesSection title="Fields & Tags" isOpen={this.openFields} setIsOpen={bool => (this.openFields = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection
+ title="Fields & Tags"
+ isOpen={this.openFields}
+ setIsOpen={bool => {
+ this.openFields = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>
</PropertiesSection>
);
@@ -1172,7 +1189,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get contextsSubMenu() {
return (
- <PropertiesSection title="Other Contexts" isOpen={this.openContexts} setIsOpen={bool => (this.openContexts = bool)} onDoubleClick={() => this.CloseAll()}>
+ <PropertiesSection
+ title="Other Contexts"
+ isOpen={this.openContexts}
+ setIsOpen={bool => {
+ this.openContexts = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
{this.contextCount > 0 ? this.contexts : 'There are no other contexts.'}
</PropertiesSection>
);
@@ -1180,7 +1203,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get linksSubMenu() {
return (
- <PropertiesSection title="Linked To" isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.CloseAll}>
+ <PropertiesSection
+ title="Linked To"
+ isOpen={this.openLinks}
+ setIsOpen={bool => {
+ this.openLinks = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
{this.linkCount > 0 ? this.links : 'There are no current links.'}
</PropertiesSection>
);
@@ -1188,14 +1217,20 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@computed get layoutSubMenu() {
return (
- <PropertiesSection title="Layout" isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.CloseAll}>
+ <PropertiesSection
+ title="Layout"
+ isOpen={this.openLayout}
+ setIsOpen={bool => {
+ this.openLayout = bool;
+ }}
+ onDoubleClick={this.CloseAll}>
{this.layoutPreview}
</PropertiesSection>
);
}
@computed get description() {
- return Field.toString(this.selectedLink?.link_description as any as Field);
+ return Field.toString(this.selectedLink?.link_description as any as FieldType);
}
@computed get relationship() {
return StrCast(this.selectedLink?.link_relationship);
@@ -1250,12 +1285,12 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
// if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes
} else if (linkRelationshipList && value !== prevRelationship) {
const index = linkRelationshipList.indexOf(value);
- //increment size of new relationship size
+ // increment size of new relationship size
if (index !== -1 && index < linkRelationshipSizes.length) {
const pvalue = linkRelationshipSizes[index];
linkRelationshipSizes[index] = pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1;
}
- //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation)
+ // decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation)
if (linkRelationshipList.includes(prevRelationship)) {
const pindex = linkRelationshipList.indexOf(prevRelationship);
if (pindex !== -1 && pindex < linkRelationshipSizes.length) {
@@ -1265,21 +1300,25 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
}
this.relationshipButtonColor = 'rgb(62, 133, 55)';
- setTimeout(
- action(() => (this.relationshipButtonColor = '')),
- 750
- );
+ setTimeout(action(() => { this.relationshipButtonColor = ''; }), 750); // prettier-ignore
return true;
}
+ return undefined;
});
- changeFollowBehavior = undoable((loc: Opt<string>) => this.sourceAnchor && (this.sourceAnchor.followLinkLocation = loc), 'change follow behavior');
+ changeFollowBehavior = undoable((loc: Opt<string>) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkLocation = loc);
+ }, 'change follow behavior');
@undoBatch
- changeAnimationBehavior = action((behavior: string) => this.sourceAnchor && (this.sourceAnchor.followLinkAnimEffect = behavior));
+ changeAnimationBehavior = action((behavior: string) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkAnimEffect = behavior);
+ });
@undoBatch
- changeEffectDirection = action((effect: PresEffectDirection) => this.sourceAnchor && (this.sourceAnchor.followLinkAnimDirection = effect));
+ changeEffectDirection = action((effect: PresEffectDirection) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkAnimDirection = effect);
+ });
animationDirection = (direction: PresEffectDirection, icon: string, gridColumn: number, gridRow: number, opts: object) => {
const lanch = this.sourceAnchor;
@@ -1300,7 +1339,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
document.getElementById('link_description_input')?.blur();
};
- onDescriptionKey = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
+ onDescriptionKey = () => {
// if (e.key === 'Enter') {
// this.setDescripValue(this.description);
// document.getElementById('link_description_input')?.blur();
@@ -1320,7 +1359,13 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
};
toggleLinkProp = (e: React.PointerEvent, prop: string) => {
- setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.selectedLink && (this.selectedLink[prop] = !this.selectedLink[prop]))));
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ undoBatch(action(() => { this.selectedLink && (this.selectedLink[prop] = !this.selectedLink[prop]); })) // prettier-ignore
+ );
};
@computed get destinationAnchor() {
@@ -1343,12 +1388,10 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
e,
returnFalse,
emptyFunction,
- undoBatch(
- action(() => {
- anchor[prop] = anchor[prop] === value ? ovalue : value;
- this.selectedDoc && cb(anchor[prop]);
- })
- )
+ undoBatch(action(() => {
+ anchor[prop] = anchor[prop] === value ? ovalue : value;
+ this.selectedDoc && cb(anchor[prop]);
+ })) // prettier-ignore
);
};
@@ -1357,7 +1400,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return (
<input
style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}
- autoComplete={'off'}
+ autoComplete="off"
id="link_relationship_input"
value={StrCast(this.selectedLink?.link_relationship)}
onKeyDown={this.onRelationshipKey}
@@ -1459,11 +1502,14 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
'10',
NumCast(this.sourceAnchor?.followLinkTransitionTime) / 1000,
true,
- (val: string) => PresBox.SetTransitionTime(val, (timeInMS: number) => this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS)),
+ (val: string) =>
+ PresBox.SetTransitionTime(val, (timeInMS: number) => {
+ this.sourceAnchor && (this.sourceAnchor.followLinkTransitionTime = timeInMS);
+ }),
indent
)}{' '}
<div
- className={'slider-headers'}
+ className="slider-headers"
style={{
display: 'grid',
justifyContent: 'space-between',
@@ -1478,86 +1524,118 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
</div>{' '}
<div className="propertiesView-input inline">
<p>Play Target Audio</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkAudio', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Play Target Video</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Zoom Text Selections</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoomText', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Toggle Follow to Outer Context</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToOuterContext', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faWindowMaximize as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Toggle Target (Show/Hide)</p>
- <button
- style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkToggle', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Ease Transitions</p>
- <button
- style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkEase', this.sourceAnchor, 'ease', 'linear')}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Capture Offset to Target</p>
- <button
- style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => {
- this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined);
- this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined);
- }}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => {
+ this.toggleAnchorProp(e, 'followLinkXoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.x) - NumCast(this.sourceAnchor?.x), undefined);
+ this.toggleAnchorProp(e, 'followLinkYoffset', this.sourceAnchor, NumCast(this.destinationAnchor?.y) - NumCast(this.sourceAnchor?.y), undefined);
+ }}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline">
<p>Center Target (no zoom)</p>
- <button
- style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+ </button>
+ }
</div>
<div className="propertiesView-input inline" style={{ display: 'grid', gridTemplateColumns: '78px calc(100% - 108px) 50px' }}>
<p>Zoom %</p>
@@ -1565,24 +1643,28 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<input className="presBox-input" style={{ width: '100%', color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }} readOnly={true} type="number" value={zoom} />
<div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}>
<div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}>
- <FontAwesomeIcon icon={'caret-up'} />
+ <FontAwesomeIcon icon="caret-up" />
</div>
<div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}>
- <FontAwesomeIcon icon={'caret-down'} />
+ <FontAwesomeIcon icon="caret-down" />
</div>
</div>
</div>
- <button
- style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }}
- onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
- onClick={e => e.stopPropagation()}
- className="propertiesButton">
- <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
- </button>
+ {
+ // eslint-disable-next-line jsx-a11y/control-has-associated-label
+ <button
+ type="button"
+ style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }}
+ onPointerDown={e => this.toggleAnchorProp(e, 'followLinkZoom', this.sourceAnchor)}
+ onClick={e => e.stopPropagation()}
+ className="propertiesButton">
+ <FontAwesomeIcon className="fa-icon" icon={faArrowRight as IconLookup} size="lg" />
+ </button>
+ }
</div>
{!targZoom ? null : PresBox.inputter('0', '1', '100', zoom, true, this.setZoom, 30)}
<div
- className={'slider-headers'}
+ className="slider-headers"
style={{
display: !targZoom ? 'none' : 'grid',
justifyContent: 'space-between',
@@ -1594,7 +1676,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}}>
<div className="slider-text">0%</div>
<div className="slider-text">100%</div>
- </div>{' '}
+ </div>
</div>
)}
</>
@@ -1622,128 +1704,136 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
</div>
</div>
);
- } else {
- if (this.selectedDoc && !this.isPres) {
- return (
- <div
- className="propertiesView"
- style={{
- background: SettingsManager.userBackgroundColor,
- color: SettingsManager.userColor,
- width: this._props.width,
- minWidth: this._props.width,
- }}>
- <div className="propertiesView-propAndInfoGrouping">
- <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
- Properties
- <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
- <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} />
- </div>
+ }
+ if (this.selectedDoc && !this.isPres) {
+ return (
+ <div
+ className="propertiesView"
+ style={{
+ background: SettingsManager.userBackgroundColor,
+ color: SettingsManager.userColor,
+ width: this._props.width,
+ minWidth: this._props.width,
+ }}>
+ <div className="propertiesView-propAndInfoGrouping">
+ <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
+ Properties
+ <div className="propertiesView-info" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/properties')}>
+ <IconButton icon={<FontAwesomeIcon icon="info-circle" />} color={SettingsManager.userColor} />
</div>
</div>
+ </div>
- <div className="propertiesView-name">{this.editableTitle}</div>
- <div className="propertiesView-type"> {this.currentType} </div>
- {this.fieldsSubMenu}
- {this.optionsSubMenu}
- {this.linksSubMenu}
- {!this.selectedLink || !this.openLinks ? null : this.linkProperties}
- {this.inkSubMenu}
- {this.contextsSubMenu}
- {isNovice ? null : this.sharingSubMenu}
- {this.filtersSubMenu}
- {isNovice ? null : this.layoutSubMenu}
+ <div className="propertiesView-name">{this.editableTitle}</div>
+ <div className="propertiesView-type"> {this.currentType} </div>
+ {this.fieldsSubMenu}
+ {this.optionsSubMenu}
+ {this.linksSubMenu}
+ {!this.selectedLink || !this.openLinks ? null : this.linkProperties}
+ {this.inkSubMenu}
+ {this.contextsSubMenu}
+ {isNovice ? null : this.sharingSubMenu}
+ {this.filtersSubMenu}
+ {isNovice ? null : this.layoutSubMenu}
+ </div>
+ );
+ }
+ if (this.isPres && PresBox.Instance) {
+ const selectedItem: boolean = PresBox.Instance.selectedArray.size > 0;
+ const type = [DocumentType.AUDIO, DocumentType.VID].includes(DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
+ ? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
+ : PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type;
+ return (
+ <div className="propertiesView" style={{ width: this._props.width }}>
+ <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
+ Presentation
</div>
- );
- }
- if (this.isPres && PresBox.Instance) {
- const selectedItem: boolean = PresBox.Instance.selectedArray.size > 0;
- const type = [DocumentType.AUDIO, DocumentType.VID].includes(DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
- ? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
- : PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type;
- return (
- <div className="propertiesView" style={{ width: this._props.width }}>
- <div className="propertiesView-sectionTitle" style={{ width: this._props.width }}>
- Presentation
- </div>
- <div className="propertiesView-name" style={{ borderBottom: 0 }}>
- {this.editableTitle}
- <div className="propertiesView-presSelected">
- <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div>
- <div className="propertiesView-selectedList">{PresBox.Instance.listOfSelected}</div>
- </div>
+ <div className="propertiesView-name" style={{ borderBottom: 0 }}>
+ {this.editableTitle}
+ <div className="propertiesView-presSelected">
+ <div className="propertiesView-selectedCount">{PresBox.Instance.selectedArray.size} selected</div>
+ <div className="propertiesView-selectedList">{PresBox.Instance.listOfSelected}</div>
</div>
- {!selectedItem ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openPresTransitions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Transitions
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ </div>
+ {!selectedItem ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openPresTransitions = !this.openPresTransitions;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openPresTransitions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Transitions
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openPresTransitions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.transitionDropdown}</div> : null}
</div>
- )}
- {!selectedItem ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibility
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ {this.openPresTransitions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.transitionDropdown}</div> : null}
+ </div>
+ )}
+ {!selectedItem ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon="rocket" /> &nbsp; Visibility
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
</div>
- )}
- {!selectedItem ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openPresProgressivize ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Progressivize
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
+ </div>
+ )}
+ {!selectedItem ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openPresProgressivize = !this.openPresProgressivize;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openPresProgressivize ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon="rocket" /> &nbsp; Progressivize
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openPresProgressivize ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null}
</div>
- )}
- {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : (
- <div className="propertiesView-presentationTrails">
- <div
- className="propertiesView-presentationTrails-title"
- onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))}
- style={{
- color: SettingsManager.userColor,
- backgroundColor: this.openSlideOptions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
- }}>
- &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> &nbsp; {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
- <div className="propertiesView-presentationTrails-title-icon">
- <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" />
- </div>
+ {this.openPresProgressivize ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.progressivizeDropdown}</div> : null}
+ </div>
+ )}
+ {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : (
+ <div className="propertiesView-presentationTrails">
+ <div
+ className="propertiesView-presentationTrails-title"
+ onPointerDown={action(() => {
+ this.openSlideOptions = !this.openSlideOptions;
+ })}
+ style={{
+ color: SettingsManager.userColor,
+ backgroundColor: this.openSlideOptions ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ }}>
+ &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> &nbsp; {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'}
+ <div className="propertiesView-presentationTrails-title-icon">
+ <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" />
</div>
- {this.openSlideOptions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null}
</div>
- )}
- </div>
- );
- }
+ {this.openSlideOptions ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.mediaOptionsDropdown}</div> : null}
+ </div>
+ )}
+ </div>
+ );
}
+ return null;
}
}
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx
index 623201ed1..365980f33 100644
--- a/src/client/views/ScriptBox.tsx
+++ b/src/client/views/ScriptBox.tsx
@@ -4,7 +4,7 @@ import * as React from 'react';
import { Doc, Opt } from '../../fields/Doc';
import { ScriptField } from '../../fields/ScriptField';
import { ScriptCast } from '../../fields/Types';
-import { emptyFunction } from '../../Utils';
+import { emptyFunction } from '../../ClientUtils';
import { DragManager } from '../util/DragManager';
import { CompileScript } from '../util/Scripting';
import { EditableView } from './EditableView';
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 3ad3c92da..bcd82887c 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -1,8 +1,10 @@
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnAll, returnFalse, returnOne, returnZero } from '../../Utils';
-import { Doc, DocListCast, Field, FieldResult, StrListCast } from '../../fields/Doc';
+import { ClientUtils, returnAll, returnFalse, returnOne, returnZero } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
+import { Doc, DocListCast, Field, FieldType, FieldResult, StrListCast } from '../../fields/Doc';
+import { DocData } from '../../fields/DocSymbols';
import { Id } from '../../fields/FieldSymbols';
import { List } from '../../fields/List';
import { RichTextField } from '../../fields/RichTextField';
@@ -18,7 +20,6 @@ import { StyleProp } from './StyleProvider';
import { CollectionStackingView } from './collections/CollectionStackingView';
import { FieldViewProps } from './nodes/FieldView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import { DocData } from '../../fields/DocSymbols';
interface ExtraProps {
fieldKey: string;
@@ -44,7 +45,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
_stackRef = React.createRef<CollectionStackingView>();
@computed get allMetadata() {
- const keys = new Map<string, FieldResult<Field>>();
+ const keys = new Map<string, FieldResult<FieldType>>();
DocListCast(this._props.Document[this.sidebarKey]).forEach(doc =>
SearchUtil.documentKeys(doc)
.filter(key => key[0] && key[0] !== '_' && key[0] === key[0].toUpperCase())
@@ -95,7 +96,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
return {
type: 'dashField',
attrs: { fieldKey: key, docId: '', hideKey: false, hideValue: false, editable: true },
- marks: [{ type: 'pFontSize', attrs: { fontSize: '12px' } }, { type: 'strong' }, { type: 'user_mark', attrs: { userid: Doc.CurrentUserEmail, modified: 0 } }],
+ marks: [{ type: 'pFontSize', attrs: { fontSize: '12px' } }, { type: 'strong' }, { type: 'user_mark', attrs: { userid: ClientUtils.CurrentUserEmail, modified: 0 } }],
};
});
@@ -196,7 +197,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
</div>
);
};
- const renderMeta = (tag: string, dflt: FieldResult<Field>) => {
+ const renderMeta = (tag: string, dflt: FieldResult<FieldType>) => {
const active = this.childFilters().includes(`${tag}${Doc.FilterSep}${Doc.FilterAny}${Doc.FilterSep}exists`);
return (
<div key={tag} className={`sidebarAnnos-filterTag${active ? '-active' : ''}`} onClick={e => Doc.setDocFilter(this._props.Document, tag, Doc.FilterAny, 'exists', true, undefined, e.shiftKey)}>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index dcec2fe3d..15e309ca0 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -7,10 +7,10 @@ import { extname } from 'path';
import * as React from 'react';
import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs';
import { FaFilter } from 'react-icons/fa';
+import { ClientUtils, DashColor, lightOrDark } from '../../ClientUtils';
import { Doc, Opt, StrListCast } from '../../fields/Doc';
import { DocViews } from '../../fields/DocSymbols';
import { BoolCast, Cast, DocCast, ImageCast, NumCast, ScriptCast, StrCast } from '../../fields/Types';
-import { DashColor, lightOrDark, Utils } from '../../Utils';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
import { DocFocusOrOpen, DocumentManager } from '../util/DocumentManager';
import { IsFollowLinkScript } from '../util/LinkFollower';
@@ -26,6 +26,7 @@ import { FieldViewProps } from './nodes/FieldView';
import { KeyValueBox } from './nodes/KeyValueBox';
import { PropertiesView } from './PropertiesView';
import './StyleProvider.scss';
+import { ScriptField } from '../../fields/ScriptField';
export enum StyleProp {
TreeViewIcon = 'treeView_Icon',
@@ -70,6 +71,20 @@ function togglePaintView(e: React.MouseEvent, doc: Opt<Doc>, props: Opt<FieldVie
ScriptCast(doc?.onPaint)?.script.run(scriptProps);
}
+export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: number) {
+ const style: { [key: string]: any } = {};
+ const divKeys = ['width', 'height', 'fontSize', 'transform', 'left', 'backgroundColor', 'left', 'right', 'top', 'bottom', 'pointerEvents', 'position'];
+ const replacer = (match: any, expr: string, offset: any, string: any) => {
+ // bcz: this executes a script to convert a property expression string: { script } into a value
+ return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ this: doc, self: doc, scale }).result?.toString() ?? '';
+ };
+ divKeys.map((prop: string) => {
+ const p = (props as any)[prop];
+ typeof p === 'string' && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer));
+ });
+ return style;
+}
+
export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
return `M ${pw * 0.5} ${ph * inset} C ${pw * 0.6} ${ph * inset} ${pw * (1 - 2 * inset)} 0 ${pw * (1 - inset)} ${ph * inset} C ${pw} ${ph * (2 * inset)} ${pw * (1 - inset)} ${ph * 0.25} ${pw * (1 - inset)} ${ph * 0.3} C ${
pw * (1 - inset)
@@ -156,7 +171,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
doc._layout_showTitle,
props?.layout_showTitle?.() ||
(!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.FUNCPLOT, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any)
- ? doc.author === Doc.CurrentUserEmail
+ ? doc.author === ClientUtils.CurrentUserEmail
? StrCast(Doc.UserDoc().layout_showTitle)
: remoteDocHeader
: '')
@@ -300,7 +315,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
const showFilterIcon =
StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length
? 'green' // #18c718bd' //'hasFilter'
- : props?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragDocsFilter).length || props?.childFiltersByRanges().length
+ : props?.childFilters?.().filter(f => ClientUtils.IsRecursiveFilter(f) && f !== ClientUtils.noDragDocsFilter).length || props?.childFiltersByRanges().length
? 'orange' //'inheritsFilter'
: undefined;
return !showFilterIcon ? null : (
@@ -308,7 +323,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
<Dropdown
type={Type.TERT}
dropdownType={DropdownType.CLICK}
- fillWidth
+ fillWidth
iconProvider={(active:boolean) => <div className='styleProvider-filterShift'><FaFilter/></div>}
closeOnSelect={true}
setSelectedVal={
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 5df0bea1a..1d02568dd 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -1,12 +1,13 @@
-import { computed, observable, ObservableSet, runInAction } from 'mobx';
+import { computed, ObservableSet, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../ClientUtils';
import { Doc, DocListCast } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { ScriptField } from '../../fields/ScriptField';
import { Cast, DocCast, StrCast } from '../../fields/Types';
import { TraceMobx } from '../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../Utils';
+import { emptyFunction } from '../../Utils';
import { Docs, DocUtils } from '../documents/Documents';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { Transform } from '../util/Transform';
@@ -16,21 +17,6 @@ import { DefaultStyleProvider } from './StyleProvider';
import './TemplateMenu.scss';
@observer
-class TemplateToggle extends React.Component<{ template: string; checked: boolean; toggle: (event: React.ChangeEvent<HTMLInputElement>, template: string) => void }> {
- render() {
- if (this.props.template) {
- return (
- <li className="templateToggle">
- <input type="checkbox" checked={this.props.checked} onChange={event => this.props.toggle(event, this.props.template)} />
- {this.props.template}
- </li>
- );
- } else {
- return null;
- }
- }
-}
-@observer
class OtherToggle extends React.Component<{ checked: boolean; name: string; toggle: (event: React.ChangeEvent<HTMLInputElement>) => void }> {
render() {
return (
@@ -50,12 +36,25 @@ export interface TemplateMenuProps {
export class TemplateMenu extends React.Component<TemplateMenuProps> {
_addedKeys = new ObservableSet();
_customRef = React.createRef<HTMLInputElement>();
- @observable private _hidden: boolean = true;
+
+ componentDidMount() {
+ !this._addedKeys && (this._addedKeys = new ObservableSet());
+ [...Array.from(Object.keys(this.props.docViews[0].Document[DocData])), ...Array.from(Object.keys(this.props.docViews[0].Document))]
+ .filter(key => key.startsWith('layout_') && (
+ StrCast(this.props.docViews[0].Document[key]).startsWith("<") ||
+ DocCast(this.props.docViews[0].Document[key])?.isTemplateDoc
+ ))
+ .forEach(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); // prettier-ignore
+ }
+ @computed get scriptField() {
+ const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.Document) as any });
+ return script ? () => script : undefined;
+ }
toggleLayout = (e: React.ChangeEvent<HTMLInputElement>, layout: string): void => {
this.props.docViews.map(dv => dv.switchViews(e.target.checked, layout, undefined, true));
};
- toggleDefault = (e: React.ChangeEvent<HTMLInputElement>): void => {
+ toggleDefault = (): void => {
this.props.docViews.map(dv => dv.switchViews(false, 'layout'));
};
@@ -65,21 +64,8 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
runInAction(() => this._addedKeys.add(this._customRef.current!.value));
}
};
- componentDidMount() {
- !this._addedKeys && (this._addedKeys = new ObservableSet());
- [...Array.from(Object.keys(this.props.docViews[0].Document[DocData])), ...Array.from(Object.keys(this.props.docViews[0].Document))]
- .filter(key => key.startsWith('layout_') && (
- StrCast(this.props.docViews[0].Document[key]).startsWith("<") ||
- DocCast(this.props.docViews[0].Document[key])?.isTemplateDoc
- ))
- .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); // prettier-ignore
- }
return100 = () => 300;
- @computed get scriptField() {
- const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.Document) as any });
- return script ? () => script : undefined;
- }
templateIsUsed = (selDoc: Doc, templateDoc: Doc) => {
const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title);
return StrCast(selDoc.layout_fieldKey) === 'layout_' + template ? 'check' : 'unchecked';
@@ -88,10 +74,11 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
TraceMobx();
const firstDoc = this.props.docViews[0].Document;
const templateName = StrCast(firstDoc.layout_fieldKey, 'layout').replace('layout_', '');
- const noteTypes = DocListCast(Cast(Doc.UserDoc()['template_notes'], Doc, null)?.data);
- const addedTypes = DocListCast(Cast(Doc.UserDoc()['template_clickFuncs'], Doc, null)?.data);
+ const noteTypes = DocListCast(Cast(Doc.UserDoc().template_notes, Doc, null)?.data);
+ const addedTypes = DocListCast(Cast(Doc.UserDoc().template_clickFuncs, Doc, null)?.data);
const templateMenu: Array<JSX.Element> = [];
templateMenu.push(<OtherToggle key="default" name={firstDoc.layout instanceof Doc ? StrCast(firstDoc.layout.title) : 'Default'} checked={templateName === 'layout'} toggle={this.toggleDefault} />);
+ // eslint-disable-next-line no-return-assign
addedTypes.concat(noteTypes).map(template => (template.treeView_Checked = this.templateIsUsed(firstDoc, template)));
this._addedKeys &&
Array.from(this._addedKeys)
@@ -122,10 +109,10 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
addDocTab={returnFalse}
PanelWidth={this.return100}
PanelHeight={this.return100}
- treeViewHideHeaderFields={true}
- treeViewHideTitle={true}
- dontRegisterView={true}
- fieldKey={'data'}
+ treeViewHideHeaderFields
+ treeViewHideTitle
+ dontRegisterView
+ fieldKey="data"
moveDocument={returnFalse}
removeDocument={returnFalse}
addDocument={returnFalse}
@@ -135,10 +122,9 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
}
}
-ScriptingGlobals.add(function switchView(doc: Doc, template: Doc | undefined) {
- if (template?.dragFactory) {
- template = Cast(template.dragFactory, Doc, null);
- }
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(function switchView(doc: Doc, templateIn: Doc | undefined) {
+ const template = templateIn?.dragFactory ? Cast(templateIn.dragFactory, Doc, null) : templateIn;
const templateTitle = StrCast(template?.title);
return templateTitle && DocUtils.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template);
});
diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx
deleted file mode 100644
index 436cb688f..000000000
--- a/src/client/views/Touchable.tsx
+++ /dev/null
@@ -1,213 +0,0 @@
-import * as React from 'react';
-import { action } from 'mobx';
-import { InteractionUtils } from '../util/InteractionUtils';
-
-const HOLD_DURATION = 1000;
-
-export abstract class Touchable<T = {}> extends React.Component<React.PropsWithChildren<T>> {
- //private holdTimer: NodeJS.Timeout | undefined;
- private moveDisposer?: InteractionUtils.MultiTouchEventDisposer;
- private endDisposer?: InteractionUtils.MultiTouchEventDisposer;
- private holdMoveDisposer?: InteractionUtils.MultiTouchEventDisposer;
- private holdEndDisposer?: InteractionUtils.MultiTouchEventDisposer;
-
- protected abstract _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
- protected _touchDrag: boolean = false;
- protected prevPoints: Map<number, React.Touch> = new Map<number, React.Touch>();
-
- public FirstX: number = 0;
- public FirstY: number = 0;
- public SecondX: number = 0;
- public SecondY: number = 0;
-
- /**
- * When a touch even starts, we keep track of each touch that is associated with that event
- */
- @action
- protected onTouchStart = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): void => {
- const actualPts: React.Touch[] = [];
- const te = me.touchEvent;
- // loop through all touches on screen
- for (const pt of me.touches) {
- actualPts.push(pt);
- if (this.prevPoints.has(pt.identifier)) {
- this.prevPoints.set(pt.identifier, pt);
- }
- // only add the ones that are targeted on "this" element, but with the identifier that the screen touch gives
- for (const tPt of me.changedTouches) {
- if (pt.clientX === tPt.clientX && pt.clientY === tPt.clientY) {
- // pen is also a touch, but with a radius of 0.5 (at least with the surface pens)
- // and this seems to be the only way of differentiating pen and touch on touch events
- if ((pt as any).radiusX > 1 && (pt as any).radiusY > 1) {
- this.prevPoints.set(pt.identifier, pt);
- }
- }
- }
- }
-
- const ptsToDelete: number[] = [];
- this.prevPoints.forEach(pt => {
- if (!actualPts.includes(pt)) {
- ptsToDelete.push(pt.identifier);
- }
- });
-
- ptsToDelete.forEach(pt => this.prevPoints.delete(pt));
-
- if (this.prevPoints.size) {
- switch (this.prevPoints.size) {
- case 1:
- this.handle1PointerDown(te, me);
- te.persist();
- // -- code for radial menu --
- // if (this.holdTimer) {
- // clearTimeout(this.holdTimer)
- // this.holdTimer = undefined;
- // }
- break;
- case 2:
- this.handle2PointersDown(te, me);
- break;
- }
- }
- };
-
- /**
- * Handle touch move event
- */
- @action
- protected onTouch = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
- const te = me.touchEvent;
- const myTouches = InteractionUtils.GetMyTargetTouches(me, this.prevPoints, true);
-
- // if we're not actually moving a lot, don't consider it as dragging yet
- if (!InteractionUtils.IsDragging(this.prevPoints, myTouches, 5) && !this._touchDrag) return;
- this._touchDrag = true;
- switch (myTouches.length) {
- case 1:
- this.handle1PointerMove(te, me);
- break;
- case 2:
- this.handle2PointersMove(te, me);
- break;
- }
-
- for (const pt of me.touches) {
- if (pt && this.prevPoints.has(pt.identifier)) {
- this.prevPoints.set(pt.identifier, pt);
- }
- }
- };
-
- @action
- protected onTouchEnd = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
- // remove all the touches associated with the event
- const te = me.touchEvent;
- for (const pt of me.changedTouches) {
- if (pt) {
- if (this.prevPoints.has(pt.identifier)) {
- this.prevPoints.delete(pt.identifier);
- }
- }
- }
- this._touchDrag = false;
- te.stopPropagation();
-
- // if (e.targetTouches.length === 0) {
- // this.prevPoints.clear();
- // }
-
- if (this.prevPoints.size === 0) {
- this.cleanUpInteractions();
- }
- e.stopPropagation();
- };
-
- cleanUpInteractions = (): void => {
- this.removeMoveListeners();
- this.removeEndListeners();
- };
-
- handle1PointerMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>): any => {
- e.stopPropagation();
- e.preventDefault();
- };
-
- handle2PointersMove = (e: TouchEvent, me: InteractionUtils.MultiTouchEvent<TouchEvent>): any => {
- e.stopPropagation();
- e.preventDefault();
- };
-
- handle1PointerDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
- this.removeMoveListeners();
- this.addMoveListeners();
- this.removeEndListeners();
- this.addEndListeners();
- };
-
- handle2PointersDown = (e: React.TouchEvent, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
- this.removeMoveListeners();
- this.addMoveListeners();
- this.removeEndListeners();
- this.addEndListeners();
- };
-
- handle1PointerHoldStart = (e: Event, me: InteractionUtils.MultiTouchEvent<React.TouchEvent>): any => {
- e.stopPropagation();
- me.touchEvent.stopPropagation();
- this.removeMoveListeners();
- this.removeEndListeners();
- this.removeHoldMoveListeners();
- this.removeHoldEndListeners();
- this.addHoldMoveListeners();
- this.addHoldEndListeners();
- };
-
- addMoveListeners = () => {
- const handler = (e: Event) => this.onTouch(e, (e as CustomEvent<InteractionUtils.MultiTouchEvent<TouchEvent>>).detail);
- document.addEventListener('dashOnTouchMove', handler);
- this.moveDisposer = () => document.removeEventListener('dashOnTouchMove', handler);
- };
- addEndListeners = () => {
- const handler = (e: Event) => this.onTouchEnd(e, (e as CustomEvent<InteractionUtils.MultiTouchEvent<TouchEvent>>).detail);
- document.addEventListener('dashOnTouchEnd', handler);
- this.endDisposer = () => document.removeEventListener('dashOnTouchEnd', handler);
- };
-
- addHoldMoveListeners = () => {
- const handler = (e: Event) => this.handle1PointerHoldMove(e, (e as CustomEvent<InteractionUtils.MultiTouchEvent<TouchEvent>>).detail);
- document.addEventListener('dashOnTouchHoldMove', handler);
- this.holdMoveDisposer = () => document.removeEventListener('dashOnTouchHoldMove', handler);
- };
-
- addHoldEndListeners = () => {
- const handler = (e: Event) => this.handle1PointerHoldEnd(e, (e as CustomEvent<InteractionUtils.MultiTouchEvent<TouchEvent>>).detail);
- document.addEventListener('dashOnTouchHoldEnd', handler);
- this.holdEndDisposer = () => document.removeEventListener('dashOnTouchHoldEnd', handler);
- };
-
- removeMoveListeners = () => this.moveDisposer?.();
- removeEndListeners = () => this.endDisposer?.();
- removeHoldMoveListeners = () => this.holdMoveDisposer?.();
- removeHoldEndListeners = () => this.holdEndDisposer?.();
-
- handle1PointerHoldMove = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
- // e.stopPropagation();
- // me.touchEvent.stopPropagation();
- };
-
- handle1PointerHoldEnd = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
- e.stopPropagation();
- me.touchEvent.stopPropagation();
- this.removeHoldMoveListeners();
- this.removeHoldEndListeners();
-
- me.touchEvent.stopPropagation();
- me.touchEvent.preventDefault();
- };
-
- handleHandDown = (e: React.TouchEvent) => {
- // e.stopPropagation();
- // e.preventDefault();
- };
-}
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index cc4da1694..c3e513154 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -4,7 +4,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, setupMoveUpEvents } from '../../../Utils';
+import { setupMoveUpEvents } from '../../../ClientUtils';
+import { Utils, emptyFunction } from '../../../Utils';
import { Doc, DocListCast } from '../../../fields/Doc';
import { BoolCast, NumCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
diff --git a/src/client/views/animationtimeline/TimelineMenu.tsx b/src/client/views/animationtimeline/TimelineMenu.tsx
index 97a571dc4..20da21cb9 100644
--- a/src/client/views/animationtimeline/TimelineMenu.tsx
+++ b/src/client/views/animationtimeline/TimelineMenu.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconLookup } from '@fortawesome/fontawesome-svg-core';
import { faChartLine, faClipboard } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -9,6 +10,7 @@ import './TimelineMenu.scss';
@observer
export class TimelineMenu extends React.Component {
+ // eslint-disable-next-line no-use-before-define
public static Instance: TimelineMenu;
@observable private _opacity = 0;
@@ -67,16 +69,19 @@ export class TimelineMenu extends React.Component {
this._currentMenu.push(
<div key={Utils.GenerateGuid()} className="timeline-menu-item">
<FontAwesomeIcon icon={faChartLine as IconLookup} size="lg" />
- <p
- className="timeline-menu-desc"
- onClick={e => {
- e.preventDefault();
- e.stopPropagation();
- event(e);
- this.closeMenu();
- }}>
- {title}
- </p>
+ {
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
+ <p
+ className="timeline-menu-desc"
+ onClick={e => {
+ e.preventDefault();
+ e.stopPropagation();
+ event(e);
+ this.closeMenu();
+ }}>
+ {title}
+ </p>
+ }
</div>
);
}
diff --git a/src/client/views/collections/CollectionCalendarView.tsx b/src/client/views/collections/CollectionCalendarView.tsx
index cbcc980a9..578ce77a5 100644
--- a/src/client/views/collections/CollectionCalendarView.tsx
+++ b/src/client/views/collections/CollectionCalendarView.tsx
@@ -1,7 +1,8 @@
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { dateRangeStrToDates, emptyFunction, returnTrue } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
+import { dateRangeStrToDates, returnTrue } from '../../../ClientUtils';
import { Doc, DocListCast } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
import { CollectionStackingView } from './CollectionStackingView';
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 4e4bd43bf..8d8f41126 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -1,9 +1,12 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, returnFalse, returnZero } from '../../../Utils';
-import { Doc, DocListCast } from '../../../fields/Doc';
+import { returnZero } from '../../../ClientUtils';
+import { Utils } from '../../../Utils';
+import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -14,12 +17,13 @@ import { DocumentView } from '../nodes/DocumentView';
import { FocusViewOptions } from '../nodes/FieldView';
import './CollectionCarousel3DView.scss';
import { CollectionSubView } from './CollectionSubView';
+
const { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } = require('../global/globalCssVariables.module.scss');
@observer
export class CollectionCarousel3DView extends CollectionSubView() {
@computed get scrollSpeed() {
- return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed
+ return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; // default scroll speed
}
constructor(props: any) {
super(props);
@@ -48,16 +52,16 @@ export class CollectionCarousel3DView extends CollectionSubView() {
panelHeight = () => this._props.PanelHeight() * Number(CAROUSEL3D_SIDE_SCALE);
onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick);
isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive();
- isChildContentActive = () => (this.isContentActive() ? true : false);
+ isChildContentActive = () => !!this.isContentActive();
childScreenToLocal = () =>
this._props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1)
.ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor.
.translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2, -((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2)
.scale(1 / this.centerScale);
- focus = (anchor: Doc, options: FocusViewOptions) => {
+ focus = (anchor: Doc, options: FocusViewOptions): Opt<number> => {
const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]);
- if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return;
+ if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return undefined;
options.didMove = true;
const target = DocCast(anchor.annotationOn) ?? anchor;
const index = docs.indexOf(target);
@@ -66,37 +70,34 @@ export class CollectionCarousel3DView extends CollectionSubView() {
};
@computed get content() {
const currentIndex = NumCast(this.layoutDoc._carousel_index);
- const displayDoc = (childPair: { layout: Doc; data: Doc }) => {
- return (
- <DocumentView
- {...this._props}
- Document={childPair.layout}
- TemplateDataDocument={childPair.data}
- //suppressSetHeight={true}
- NativeWidth={returnZero}
- NativeHeight={returnZero}
- layout_fitWidth={undefined}
- onDoubleClickScript={this.onChildDoubleClick}
- renderDepth={this._props.renderDepth + 1}
- LayoutTemplate={this._props.childLayoutTemplate}
- LayoutTemplateString={this._props.childLayoutString}
- focus={this.focus}
- ScreenToLocalTransform={this.childScreenToLocal}
- isContentActive={this.isChildContentActive}
- isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
- />
- );
- };
-
- return this.carouselItems.map((childPair, index) => {
- return (
- <div key={childPair.layout[Id]} className={`collectionCarousel3DView-item${index === currentIndex ? '-active' : ''} ${index}`} style={{ width: this.panelWidth() }}>
- {displayDoc(childPair)}
- </div>
- );
- });
+ const displayDoc = (childPair: { layout: Doc; data: Doc }) => (
+ <DocumentView
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ {...this._props}
+ Document={childPair.layout}
+ TemplateDataDocument={childPair.data}
+ // suppressSetHeight={true}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
+ layout_fitWidth={undefined}
+ onDoubleClickScript={this.onChildDoubleClick}
+ renderDepth={this._props.renderDepth + 1}
+ LayoutTemplate={this._props.childLayoutTemplate}
+ LayoutTemplateString={this._props.childLayoutString}
+ focus={this.focus}
+ ScreenToLocalTransform={this.childScreenToLocal}
+ isContentActive={this.isChildContentActive}
+ isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive}
+ PanelWidth={this.panelWidth}
+ PanelHeight={this.panelHeight}
+ />
+ );
+
+ return this.carouselItems.map((childPair, index) => (
+ <div key={childPair.layout[Id]} className={`collectionCarousel3DView-item${index === currentIndex ? '-active' : ''} ${index}`} style={{ width: this.panelWidth() }}>
+ {displayDoc(childPair)}
+ </div>
+ ));
}
changeSlide = (direction: number) => {
@@ -124,21 +125,21 @@ export class CollectionCarousel3DView extends CollectionSubView() {
};
toggleAutoScroll = (direction: number) => {
- this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true;
+ this.layoutDoc.autoScrollOn = !this.layoutDoc.autoScrollOn;
this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll();
};
fadeScrollButton = () => {
window.setTimeout(() => {
- !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = 'none'); //fade away after 1.5s if it's not clicked.
+ !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = 'none'); // fade away after 1.5s if it's not clicked.
}, 1500);
};
@computed get buttons() {
return (
<div className="arrow-buttons">
- <div title="click to go back" key="back" className="carousel3DView-back" onClick={e => this.onArrowClick(-1)} />
- <div title="click to advance" key="fwd" className="carousel3DView-fwd" onClick={e => this.onArrowClick(1)} />
+ <div title="click to go back" key="back" className="carousel3DView-back" onClick={() => this.onArrowClick(-1)} />
+ <div title="click to advance" key="fwd" className="carousel3DView-fwd" onClick={() => this.onArrowClick(1)} />
{/* {this.autoScrollButton} */}
</div>
);
@@ -149,17 +150,25 @@ export class CollectionCarousel3DView extends CollectionSubView() {
return (
<>
<div className={`carousel3DView-back-scroll${whichButton === 'back' ? '' : '-hidden'}`} style={{ background: `${StrCast(this.Document.backgroundColor)}` }} onClick={() => this.toggleAutoScroll(-1)}>
- {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={'pause'} size={'1x'} /> : <FontAwesomeIcon icon={'angle-double-left'} size={'1x'} />}
+ {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon="pause" size="1x" /> : <FontAwesomeIcon icon="angle-double-left" size="1x" />}
</div>
<div className={`carousel3DView-fwd-scroll${whichButton === 'fwd' ? '' : '-hidden'}`} style={{ background: `${StrCast(this.Document.backgroundColor)}` }} onClick={() => this.toggleAutoScroll(1)}>
- {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon={'pause'} size={'1x'} /> : <FontAwesomeIcon icon={'angle-double-right'} size={'1x'} />}
+ {this.layoutDoc.autoScrollOn ? <FontAwesomeIcon icon="pause" size="1x" /> : <FontAwesomeIcon icon="angle-double-right" size="1x" />}
</div>
</>
);
}
@computed get dots() {
- return this.carouselItems.map((_child, index) => <div key={Utils.GenerateGuid()} className={`dot${index === NumCast(this.layoutDoc._carousel_index) ? '-active' : ''}`} onClick={() => (this.layoutDoc._carousel_index = index)} />);
+ return this.carouselItems.map((_child, index) => (
+ <div
+ key={Utils.GenerateGuid()}
+ className={`dot${index === NumCast(this.layoutDoc._carousel_index) ? '-active' : ''}`}
+ onClick={() => {
+ this.layoutDoc._carousel_index = index;
+ }}
+ />
+ ));
}
@computed get translateX() {
const index = NumCast(this.layoutDoc._carousel_index);
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 9c370bfbb..6dda6e545 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -2,9 +2,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { StopEvent, emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
+import { StopEvent, returnFalse, returnOne, returnZero } from '../../../ClientUtils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { StyleProp } from '../StyleProvider';
import { DocumentView } from '../nodes/DocumentView';
@@ -12,7 +14,6 @@ import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import './CollectionCarouselView.scss';
import { CollectionSubView } from './CollectionSubView';
-import { DocumentType } from '../../documents/DocumentTypes';
@observer
export class CollectionCarouselView extends CollectionSubView() {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index b2897a9b7..9a1781b93 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -2,25 +2,26 @@ import { action, IReactionDisposer, makeObservable, observable, reaction } from
import { observer } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
-import * as GoldenLayout from '../../../client/goldenLayout';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, incrementTitleCopy } from '../../../ClientUtils';
import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
import { AclAdmin, AclEdit, DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
-import { FieldValue, ImageCast, NumCast, StrCast } from '../../../fields/Types';
+import { ImageCast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { GetEffectiveAcl, inheritParentAcls, SetPropSetterCb } from '../../../fields/util';
-import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, emptyFunction, incrementTitleCopy } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { DocServer } from '../../DocServer';
import { Docs } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import * as GoldenLayout from '../../goldenLayout';
import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
import { InteractionUtils } from '../../util/InteractionUtils';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { undoable, undoBatch, UndoManager } from '../../util/UndoManager';
import { DashboardView } from '../DashboardView';
import { LightboxView } from '../LightboxView';
@@ -32,11 +33,12 @@ import './CollectionDockingView.scss';
import { CollectionFreeFormView } from './collectionFreeForm';
import { CollectionSubView } from './CollectionSubView';
import { TabDocView } from './TabDocView';
-import { ComputedField } from '../../../fields/ScriptField';
+
const _global = (window /* browser */ || global) /* node */ as any;
@observer
export class CollectionDockingView extends CollectionSubView() {
+ // eslint-disable-next-line no-use-before-define
@observable public static Instance: CollectionDockingView | undefined = undefined;
public static makeDocumentConfig(document: Doc, panelName?: string, width?: number, keyValue?: boolean) {
return {
@@ -68,7 +70,7 @@ export class CollectionDockingView extends CollectionSubView() {
super(props);
makeObservable(this);
if (this._props.renderDepth < 0) CollectionDockingView.Instance = this;
- //Why is this here?
+ // Why is this here?
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
DragManager.StartWindowDrag = this.StartOtherDrag;
@@ -201,6 +203,7 @@ export class CollectionDockingView extends CollectionSubView() {
} else if (instance._goldenLayout.root.contentItems[0].isRow) {
// if row
switch (pullSide) {
+ // eslint-disable-next-line default-case-last
default:
case OpenWhereMod.none:
case OpenWhereMod.right:
@@ -210,7 +213,7 @@ export class CollectionDockingView extends CollectionSubView() {
glayRoot.contentItems[0].addChild(newContentItem(), 0);
break;
case OpenWhereMod.top:
- case OpenWhereMod.bottom:
+ case OpenWhereMod.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);
@@ -229,6 +232,7 @@ export class CollectionDockingView extends CollectionSubView() {
rowlayout.config.height = 50;
newItem.config.height = 50;
+ }
}
} else {
// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
@@ -241,7 +245,7 @@ export class CollectionDockingView extends CollectionSubView() {
break;
case 'left':
case 'right':
- default:
+ 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);
@@ -260,6 +264,7 @@ export class CollectionDockingView extends CollectionSubView() {
collayout.config.width = 50;
newItem.config.width = 50;
+ }
}
}
instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig());
@@ -278,10 +283,10 @@ export class CollectionDockingView extends CollectionSubView() {
}
setupGoldenLayout = async () => {
if (this._unmounting) return;
- //const config = StrCast(this.Document.dockingConfig, JSON.stringify(DashboardView.resetDashboard(this.Document)));
+ // const config = StrCast(this.Document.dockingConfig, JSON.stringify(DashboardView.resetDashboard(this.Document)));
const config = StrCast(this.Document.dockingConfig);
if (config) {
- const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g);
+ const matches = config.match(/"documentId":"[a-z0-9-]+"/g);
const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')) ?? [];
await Promise.all(docids.map(id => DocServer.GetRefField(id)));
@@ -289,12 +294,13 @@ export class CollectionDockingView extends CollectionSubView() {
if (this._goldenLayout) {
if (config === JSON.stringify(this._goldenLayout.toConfig())) {
return;
- } else {
- try {
- this._goldenLayout.unbind('tabCreated', this.tabCreated);
- this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- this._goldenLayout.unbind('stackCreated', this.stackCreated);
- } catch (e) {}
+ }
+ try {
+ this._goldenLayout.unbind('tabCreated', this.tabCreated);
+ this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
+ this._goldenLayout.unbind('stackCreated', this.stackCreated);
+ } catch (e) {
+ /* empty */
}
this.tabMap.clear();
this._goldenLayout.destroy();
@@ -323,7 +329,7 @@ export class CollectionDockingView extends CollectionSubView() {
*/
titleChanged = (target: any, value: any) => {
const title = Field.toString(value);
- if (title.startsWith('@') && !title.substring(1).match(/[\(\)\[\]@]/) && title.length > 1) {
+ if (title.startsWith('@') && !title.substring(1).match(/[()[\]@]/) && title.length > 1) {
const embedding = DocListCast(target.proto_embeddings).lastElement();
embedding && Doc.AddToMyPublished(embedding);
} else if (!title.startsWith('@')) {
@@ -337,7 +343,7 @@ export class CollectionDockingView extends CollectionSubView() {
if (this._containerRef.current) {
this._lightboxReactionDisposer = reaction(
() => LightboxView.LightboxDoc,
- doc => setTimeout(() => !doc && this.onResize(undefined))
+ doc => setTimeout(() => !doc && this.onResize())
);
new _global.ResizeObserver(this.onResize).observe(this._containerRef.current);
this._reactionDisposer = reaction(
@@ -356,12 +362,12 @@ export class CollectionDockingView extends CollectionSubView() {
{ fireImmediately: true }
);
reaction(
- () => [SettingsManager.userBackgroundColor, SettingsManager.userBackgroundColor],
+ () => [SnappingManager.userBackgroundColor, SnappingManager.userBackgroundColor],
() => {
clearStyleSheetRules(CollectionDockingView._highlightStyleSheet);
- addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { background: `${SettingsManager.userBackgroundColor} !important` });
- addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { color: `${SettingsManager.userColor} !important` });
- addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${SettingsManager.userBackgroundColor} !important` });
+ addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { background: `${SnappingManager.userBackgroundColor} !important` });
+ addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { color: `${SnappingManager.userColor} !important` });
+ addStyleSheetRule(SnappingManager.SettingsStyle, 'lm_header', { background: `${SnappingManager.userBackgroundColor} !important` });
},
{ fireImmediately: true }
);
@@ -374,7 +380,9 @@ export class CollectionDockingView extends CollectionSubView() {
try {
this._goldenLayout.unbind('stackCreated', this.stackCreated);
this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- } catch (e) {}
+ } catch (e) {
+ /* empty */
+ }
this._goldenLayout?.destroy();
window.removeEventListener('resize', this.onResize);
window.removeEventListener('mouseup', this.onPointerUp);
@@ -384,7 +392,7 @@ export class CollectionDockingView extends CollectionSubView() {
};
@action
- onResize = (event: any) => {
+ onResize = () => {
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);
@@ -392,7 +400,7 @@ export class CollectionDockingView extends CollectionSubView() {
endUndoBatch = () => {
const json = JSON.stringify(this._goldenLayout.toConfig());
- const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
+ const matches = json.match(/"documentId":"[a-z0-9-]+"/g);
const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', ''));
const docs = !docids
? []
@@ -415,7 +423,7 @@ export class CollectionDockingView extends CollectionSubView() {
};
@action
- onPointerUp = (e: MouseEvent): void => {
+ onPointerUp = (): void => {
window.removeEventListener('pointerup', this.onPointerUp);
DragManager.CompleteWindowDrag = undefined;
setTimeout(this.endUndoBatch, 100);
@@ -453,24 +461,27 @@ export class CollectionDockingView extends CollectionSubView() {
if (content) {
const _width = DivWidth(content);
const _height = DivHeight(content);
- 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) => {
+ return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', iconFile => {
const proto = this.dataDoc; // Cast(img.proto, Doc, null)!;
- proto['thumb_nativeWidth'] = _width;
- proto['thumb_nativeHeight'] = _height;
+ proto.thumb_nativeWidth = _width;
+ proto.thumb_nativeHeight = _height;
proto.thumb = new ImageField(iconFile);
});
}
+ return undefined;
}
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()).forEach(entry => {
+ json = json.replace(entry[0], entry[1][Id]);
+ });
cloned.clone[DocData].dockingConfig = json;
return DashboardView.openDashboard(cloned.clone);
}
- const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
+ 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))
@@ -508,19 +519,20 @@ export class CollectionDockingView extends CollectionSubView() {
tabDestroyed = (tab: any) => {
this._flush = this._flush ?? UndoManager.StartBatch('tab movement');
- if (tab.DashDoc && ![DocumentType.PRES].includes(tab.DashDoc?.type) && !tab.contentItem.config.props.keyValue) {
- Doc.AddDocToList(Doc.MyHeaderBar, 'data', tab.DashDoc, undefined, undefined, true);
+ const dashDoc = tab.DashDoc;
+ if (dashDoc && ![DocumentType.PRES].includes(dashDoc.type) && !tab.contentItem.config.props.keyValue) {
+ Doc.AddDocToList(Doc.MyHeaderBar, 'data', dashDoc, undefined, undefined, true);
// if you close a tab that is not embedded somewhere else (an embedded Doc can be opened simultaneously in a tab), then add the tab to recently closed
- if (tab.DashDoc.embedContainer === this.Document) tab.DashDoc.embedContainer = undefined;
- if (!tab.DashDoc.embedContainer) {
- Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true);
- Doc.RemoveEmbedding(tab.DashDoc, tab.DashDoc);
+ if (dashDoc.embedContainer === this.Document) dashDoc.embedContainer = undefined;
+ if (!dashDoc.embedContainer) {
+ Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', dashDoc, undefined, true, true);
+ Doc.RemoveEmbedding(dashDoc, dashDoc);
}
}
if (CollectionDockingView.Instance) {
const dview = CollectionDockingView.Instance.Document;
- const fieldKey = CollectionDockingView.Instance.props.fieldKey;
- Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc);
+ const { fieldKey } = CollectionDockingView.Instance.props;
+ Doc.RemoveDocFromList(dview, fieldKey, dashDoc);
this.tabMap.delete(tab);
tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
this.stateChanged();
@@ -531,8 +543,8 @@ export class CollectionDockingView extends CollectionSubView() {
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 = stack.header ? stack : stack.origin;
+ stackCreated = (stackIn: any) => {
+ const stack = stackIn.header ? stackIn : stackIn.origin;
stack.header?.element.on('mousedown', (e: any) => {
const dashboard = Doc.ActiveDashboard;
if (dashboard && e.target === stack.header?.element[0] && e.button === 2) {
@@ -550,32 +562,29 @@ export class CollectionDockingView extends CollectionSubView() {
}
});
- let addNewDoc = undoable(
- action(() => {
- const dashboard = Doc.ActiveDashboard;
- if (dashboard) {
- dashboard.pane_count = NumCast(dashboard.pane_count) + 1;
- const docToAdd = Docs.Create.FreeformDocument([], {
- _width: this._props.PanelWidth(),
- _height: this._props.PanelHeight(),
- _layout_fitWidth: true,
- _freeform_backgroundGrid: true,
- title: `Untitled Tab ${NumCast(dashboard.pane_count)}`,
- });
- Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd, undefined, undefined, true);
- inheritParentAcls(this.dataDoc, docToAdd, false);
- CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
- }
- }),
- 'add new tab'
- );
+ const addNewDoc = undoable(() => {
+ const dashboard = Doc.ActiveDashboard;
+ if (dashboard) {
+ dashboard.pane_count = NumCast(dashboard.pane_count) + 1;
+ const docToAdd = Docs.Create.FreeformDocument([], {
+ _width: this._props.PanelWidth(),
+ _height: this._props.PanelHeight(),
+ _layout_fitWidth: true,
+ _freeform_backgroundGrid: true,
+ title: `Untitled Tab ${NumCast(dashboard.pane_count)}`,
+ });
+ Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd, undefined, undefined, true);
+ inheritParentAcls(this.dataDoc, docToAdd, false);
+ CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
+ }
+ }, 'add new tab');
stack.header?.controlsContainer
- .find('.lm_close') //get the close icon
- .off('click') //unbind the current click handler
+ .find('.lm_close') // get the close icon
+ .off('click') // unbind the current click handler
.click(
action(() => {
- //if (confirm('really close this?')) {
+ // if (confirm('really close this?')) {
if ((!stack.parent.isRoot && !stack.parent.parent.isRoot) || stack.parent.contentItems.length > 1) {
const batch = UndoManager.StartBatch('close stack');
stack.remove();
@@ -595,11 +604,11 @@ export class CollectionDockingView extends CollectionSubView() {
}
});
stack.header?.controlsContainer
- .find('.lm_maximise') //get the close icon
+ .find('.lm_maximise') // get the close icon
.click(() => setTimeout(this.stateChanged));
stack.header?.controlsContainer
- .find('.lm_popout') //get the popout icon
- .off('click') //unbind the current click handler
+ .find('.lm_popout') // get the popout icon
+ .off('click') // unbind the current click handler
.click(addNewDoc);
};
@@ -609,13 +618,14 @@ export class CollectionDockingView extends CollectionSubView() {
<div>
{href ? (
<img
+ alt="thumbnail of nested dashboard"
style={{ background: 'white', top: 0, position: 'absolute' }}
src={href} // + '?d=' + (new Date()).getTime()}
width={this._props.PanelWidth()}
height={this._props.PanelHeight()}
/>
) : (
- <p>nested dashboards has no thumbnail</p>
+ <p>nested dashboard has no thumbnail</p>
)}
</div>
) : (
@@ -625,6 +635,7 @@ export class CollectionDockingView extends CollectionSubView() {
}
ScriptingGlobals.add(
+ // eslint-disable-next-line prefer-arrow-callback
function openInLightbox(doc: any) {
LightboxView.Instance.AddDocTab(doc, OpenWhere.lightbox);
},
@@ -632,26 +643,37 @@ ScriptingGlobals.add(
'(doc: any)'
);
ScriptingGlobals.add(
+ // eslint-disable-next-line prefer-arrow-callback
function openDoc(doc: any, where: OpenWhere) {
switch (where) {
case OpenWhere.addRight:
return CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
case OpenWhere.overlay:
+ default:
// prettier-ignore
switch (doc) {
case '<ScriptingRepl />': return OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
case "<UndoStack />": return OverlayView.Instance.addWindow(<UndoStack />, { x: 300, y: 100, width: 200, height: 200, title: 'Undo stack' });
+ default:
}
Doc.AddToMyOverlay(doc);
+ return true;
}
},
'opens up document in location specified',
'(doc: any)'
);
ScriptingGlobals.add(
+ // eslint-disable-next-line prefer-arrow-callback
function openRepl() {
return 'openRepl';
},
'opens up document in screen overlay layer',
'(doc: any)'
);
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(async function snapshotDashboard() {
+ const batch = UndoManager.StartBatch('snapshot');
+ await CollectionDockingView.TakeSnapshot(Doc.ActiveDashboard);
+ batch.end();
+}, 'creates a snapshot copy of a dashboard');
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 7dcfd32bd..2d906dfe7 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -2,7 +2,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, numberRange, returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../Utils';
+import { returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction, numberRange } from '../../../Utils';
import { Doc, DocListCast } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 4f25f69ef..a23725348 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -4,7 +4,8 @@ import { Toggle, ToggleType, Type } from 'browndash-components';
import { Lambda, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils';
+import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { List } from '../../../fields/List';
@@ -12,7 +13,8 @@ import { ObjectField } from '../../../fields/ObjectField';
import { RichTextField } from '../../../fields/RichTextField';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { SelectionManager } from '../../util/SelectionManager';
import { SettingsManager } from '../../util/SettingsManager';
import { Transform } from '../../util/Transform';
@@ -79,7 +81,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
buttonBarXf = () => {
if (!this._docBtnRef.current) return Transform.Identity();
- const { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current);
+ const { scale, translateX, translateY } = ClientUtils.GetScreenTransform(this._docBtnRef.current);
return new Transform(-translateX, -translateY, 1 / scale);
};
@@ -123,7 +125,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
const propTitle = SettingsManager.Instance.propertiesWidth > 0 ? 'Close Properties' : 'Open Properties';
const hardCodedButtons = (
- <div className={`hardCodedButtons`}>
+ <div className="hardCodedButtons">
<Toggle
toggleType={ToggleType.BUTTON}
type={Type.PRIM}
@@ -145,7 +147,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
</div>
);
- //dash col linear view buttons
+ // dash col linear view buttons
const contMenuButtons = (
<div
className="collectionMenu-container"
@@ -172,7 +174,7 @@ const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
@observer
export class CollectionViewBaseChrome extends React.Component<CollectionViewMenuProps> {
- //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
+ // (!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
get document() {
return this.props.docView?.Document;
@@ -206,14 +208,18 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
params: ['target', 'source'],
title: 'child click view',
script: 'this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])',
- immediate: undoBatch((source: Doc[]) => source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]))),
+ immediate: undoBatch((source: Doc[]) => {
+ source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]));
+ }),
initialize: emptyFunction,
};
_contentCommand = {
params: ['target', 'source'],
title: 'set content',
script: 'getProto(this.target).data = copyField(this.source);',
- immediate: undoBatch((source: Doc[]) => (this.target[DocData].data = new List<Doc>(source))),
+ immediate: undoBatch((source: Doc[]) => {
+ this.target[DocData].data = new List<Doc>(source);
+ }),
initialize: emptyFunction,
};
_onClickCommand = {
@@ -224,14 +230,14 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
getProto(this.proxy[0]).target = this.target.target;
getProto(this.proxy[0]).source = copyField(this.target.source);
}}`,
- immediate: undoBatch((source: Doc[]) => {}),
+ immediate: undoBatch(() => {}),
initialize: emptyFunction,
};
_viewCommand = {
params: ['target'],
title: 'bookmark view',
script: "this.target._freeform_panX = self['target-freeform_panX']; this.target._freeform_panY = this['target-freeform_panY']; this.target._freeform_scale = this['target_freeform_scale']; gotoFrame(this.target, this['target-currentFrame']);",
- immediate: undoBatch((source: Doc[]) => {
+ immediate: undoBatch(() => {
this.target._freeform_panX = 0;
this.target._freeform_panY = 0;
this.target._freeform_scale = 1;
@@ -248,14 +254,18 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
params: ['target'],
title: 'fit content',
script: 'this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox;',
- immediate: undoBatch((source: Doc[]) => (this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox)),
+ immediate: undoBatch(() => {
+ this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox;
+ }),
initialize: emptyFunction,
};
_fitContentCommand = {
params: ['target'],
title: 'toggle clusters',
script: 'this.target._freeform_useClusters = !this.target._freeform_useClusters;',
- immediate: undoBatch((source: Doc[]) => (this.target._freeform_useClusters = !this.target._freeform_useClusters)),
+ immediate: undoBatch(() => {
+ this.target._freeform_useClusters = !this.target._freeform_useClusters;
+ }),
initialize: emptyFunction,
};
_saveFilterCommand = {
@@ -263,7 +273,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
title: 'save filter',
script: `this.target._childFilters = compareLists(this['target-childFilters'],this.target._childFilters) ? undefined : copyField(this['target-childFilters']);
this.target._searchFilterDocs = compareLists(this['target-searchFilterDocs'],this.target._searchFilterDocs) ? undefined: copyField(this['target-searchFilterDocs']);`,
- immediate: undoBatch((source: Doc[]) => {
+ immediate: undoBatch(() => {
this.target._childFilters = undefined;
this.target._searchFilterDocs = undefined;
}),
@@ -332,12 +342,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
@undoBatch
viewChanged = (e: React.ChangeEvent) => {
const target = this.document !== Doc.MyLeftSidebarPanel ? this.document : DocCast(this.document.proto);
- //@ts-ignore
target._type_collection = e.target.selectedOptions[0].value;
};
commandChanged = (e: React.ChangeEvent) => {
- //@ts-ignore
runInAction(() => (this._currentKey = e.target.selectedOptions[0].value));
};
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index d8a0aebb1..4ceeb631d 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -1,7 +1,8 @@
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, Field, Opt } from '../../../fields/Doc';
+import { ClientUtils, DivHeight, lightOrDark, returnZero, smoothScroll } from '../../../ClientUtils';
+import { Doc, Field, FieldType, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Copy, Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
@@ -9,14 +10,16 @@ import { listSpec } from '../../../fields/Schema';
import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DivHeight, emptyFunction, lightOrDark, returnZero, smoothScroll, Utils } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoable, undoBatch } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
+import { FieldsDropdown } from '../FieldsDropdown';
import { Colors } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { DocumentView } from '../nodes/DocumentView';
@@ -27,7 +30,7 @@ import './CollectionNoteTakingView.scss';
import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn';
import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';
import { CollectionSubView } from './CollectionSubView';
-import { FieldsDropdown } from '../FieldsDropdown';
+
const _global = (window /* browser */ || global) /* node */ as any;
/**
@@ -300,7 +303,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// getDocTransform is used to get the coordinates of a document when we go from a view like freeform to columns
getDocTransform(doc: Doc, dref?: DocumentView) {
const y = this._scroll; // required for document decorations to update when the text box container is scrolled
- const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined);
+ const { translateX, translateY } = ClientUtils.GetScreenTransform(dref?.ContentDiv || undefined);
// the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off
return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(this.ScreenToLocalBoxXf().Scale);
}
@@ -308,7 +311,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// how to get the width of a document. Currently returns the width of the column (minus margins)
// if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
getDocWidth(d: Doc) {
- const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field);
+ const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as FieldType);
const existingHeader = this.colHeaderData.find(sh => sh.heading === heading);
const existingWidth = this.layoutDoc._notetaking_columns_autoSize ? 1 / (this.colHeaderData.length ?? 1) : existingHeader?.width ? existingHeader.width : 0;
const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth;
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 448b11b05..e00fdb50c 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { lightOrDark, returnEmptyString } from '../../../Utils';
+import { lightOrDark, returnEmptyString } from '../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { RichTextField } from '../../../fields/RichTextField';
import { listSpec } from '../../../fields/Schema';
diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
index 50a97b978..67070b24d 100644
--- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
@@ -1,7 +1,8 @@
import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
+import { setupMoveUpEvents } from '../../../ClientUtils';
import { UndoManager } from '../../util/UndoManager';
import { ObservableReactComponent } from '../ObservableReactComponent';
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index 9d68c621b..e39f1c700 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -1,12 +1,13 @@
import { action, computed, IReactionDisposer, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, DocListCast } from '../../../fields/Doc';
import { ScriptField } from '../../../fields/ScriptField';
import { NumCast, StrCast } from '../../../fields/Types';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { DocUtils } from '../../documents/Documents';
-import { dropActionType } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { SelectionManager } from '../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
import { OpenWhere } from '../nodes/DocumentView';
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 656f850b3..3f6638b25 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -2,6 +2,7 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import * as React from 'react';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../ClientUtils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -10,7 +11,7 @@ import { listSpec } from '../../../fields/Schema';
import { ComputedField, ScriptField } from '../../../fields/ScriptField';
import { Cast, NumCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
-import { emptyFunction, formatTime, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents, smoothScrollHorizontal, StopEvent } from '../../../Utils';
+import { emptyFunction, formatTime } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index bf0393883..b79d660c6 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,8 +1,10 @@
+/* eslint-disable react/jsx-props-no-spreading */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import * as CSS from 'csstype';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { ClientUtils, DivHeight, returnEmptyDoclist, returnNone, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -11,10 +13,11 @@ import { listSpec } from '../../../fields/Schema';
import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DivHeight, emptyFunction, returnEmptyDoclist, returnNone, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { CollectionViewType } from '../../documents/DocumentTypes';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { SettingsManager } from '../../util/SettingsManager';
import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from '../../util/UndoManager';
@@ -31,6 +34,7 @@ import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow';
import './CollectionStackingView.scss';
import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn';
import { CollectionSubView } from './CollectionSubView';
+
const _global = (window /* browser */ || global) /* node */ as any;
export type collectionStackingViewProps = {
@@ -125,11 +129,16 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// TODO: plj - these are the children
children = (docs: Doc[]) => {
- //TODO: can somebody explain me to what exactly TraceMobX is?
+ // TODO: can somebody explain me to what exactly TraceMobX is?
TraceMobx();
// appears that we are going to reset the _docXfs. TODO: what is Xfs?
this._docXfs.length = 0;
- this._renderCount < docs.length && setTimeout(action(() => (this._renderCount = Math.min(docs.length, this._renderCount + 5))));
+ this._renderCount < docs.length &&
+ setTimeout(
+ action(() => {
+ this._renderCount = Math.min(docs.length, this._renderCount + 5);
+ })
+ );
return docs.map((d, i) => {
const height = () => this.getDocHeight(d);
const width = () => this.getDocWidth(d);
@@ -152,19 +161,21 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
};
// is sections that all collections inherit? I think this is how we show the masonry/columns
- //TODO: this seems important
+ // TODO: this seems important
get Sections() {
// appears that pivot field IS actually for sorting
if (!this.pivotField || this.colHeaderData instanceof Promise) return new Map<SchemaHeaderField, Doc[]>();
if (this.colHeaderData === undefined) {
- setTimeout(() => (this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>()), 0);
+ setTimeout(() => {
+ this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>();
+ });
return new Map<SchemaHeaderField, Doc[]>();
}
const colHeaderData = Array.from(this.colHeaderData);
const fields = new Map<SchemaHeaderField, Doc[]>(colHeaderData.map(sh => [sh, []] as [SchemaHeaderField, []]));
let changed = false;
- this.filteredChildren.map(d => {
+ this.filteredChildren.forEach(d => {
const sectionValue = (d[this.pivotField] ? d[this.pivotField] : `NO ${this.pivotField.toUpperCase()} VALUE`) as object;
// the next five lines ensures that floating point rounding errors don't create more than one section -syip
const parsed = parseInt(sectionValue.toString());
@@ -186,7 +197,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
if (this.layoutDoc._columnsHideIfEmpty) {
Array.from(fields.keys())
.filter(key => !fields.get(key)!.length)
- .map(header => {
+ .forEach(header => {
fields.delete(header);
colHeaderData.splice(colHeaderData.indexOf(header), 1);
changed = true;
@@ -207,11 +218,13 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// reset section headers when a new filter is inputted
this._disposers.pivotField = reaction(
() => this.pivotField,
- () => (this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List())
+ () => {
+ this.dataDoc['_' + this.fieldKey + '_columnHeaders'] = new List();
+ }
);
this._disposers.autoHeight = reaction(
() => this.layoutDoc._layout_autoHeight,
- layout_autoHeight => layout_autoHeight && this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0)))
+ layoutAutoHeight => layoutAutoHeight && this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0)))
);
this._disposers.refList = reaction(
() => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }),
@@ -231,9 +244,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
isAnyChildContentActive = () => this._props.isAnyChildContentActive();
- moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => {
- return this._props.removeDocument?.(doc) && addDocument?.(doc) ? true : false;
- };
+ moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => !!(this._props.removeDocument?.(doc) && addDocument?.(doc));
onChildClickHandler = () => this._props.childClickScript || ScriptCast(this.Document.onChildClick);
@computed get onChildDoubleClickHandler() {
@@ -250,10 +261,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
if (found) {
- const top = found.getBoundingClientRect().top;
+ const { top } = found.getBoundingClientRect();
const localTop = this.ScreenToLocalBoxXf().transformPoint(0, top);
if (Math.floor(localTop[1]) !== 0) {
- let focusSpeed = options.zoomTime ?? 500;
+ const focusSpeed = options.zoomTime ?? 500;
smoothScroll(focusSpeed, this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
return focusSpeed;
}
@@ -276,18 +287,18 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
if (['Enter'].includes(e.key) && e.ctrlKey) {
e.stopPropagation?.();
- const below = !e.altKey && e.key !== 'Tab';
- const layout_fieldKey = StrCast(fieldProps.fieldKey);
+ const layoutFieldKey = StrCast(fieldProps.fieldKey);
const newDoc = Doc.MakeCopy(fieldProps.Document, true);
const dataField = fieldProps.Document[Doc.LayoutFieldKey(newDoc)];
newDoc[DocData][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined;
- if (layout_fieldKey !== 'layout' && fieldProps.Document[layout_fieldKey] instanceof Doc) {
- newDoc[layout_fieldKey] = fieldProps.Document[layout_fieldKey];
+ if (layoutFieldKey !== 'layout' && fieldProps.Document[layoutFieldKey] instanceof Doc) {
+ newDoc[layoutFieldKey] = fieldProps.Document[layoutFieldKey];
}
newDoc[DocData].text = undefined;
FormattedTextBox.SetSelectOnLoad(newDoc);
return this.addDocument?.(newDoc);
}
+ return false;
};
isContentActive = () => (this._props.isContentActive() ? true : this._props.isSelected() === false || this._props.isContentActive() === false ? false : undefined);
@@ -363,7 +374,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
getDocTransform(doc: Doc) {
const dref = this.docRefs.get(doc);
this._scroll; // must be referenced for document decorations to update when the text box container is scrolled
- const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv);
+ const { translateX, translateY } = ClientUtils.GetScreenTransform(dref?.ContentDiv);
// the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off
return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(this.ScreenToLocalBoxXf().Scale);
}
@@ -399,7 +410,9 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// This following three functions must be from the view Mehek showed
columnDividerDown = (e: React.PointerEvent) => {
- runInAction(() => (this._cursor = 'grabbing'));
+ runInAction(() => {
+ this._cursor = 'grabbing';
+ });
const batch = UndoManager.StartBatch('stacking width');
setupMoveUpEvents(
this,
@@ -425,7 +438,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
onPointerDown={this.columnDividerDown}
ref={this._draggerRef}
style={{ cursor: this._cursor, color: SettingsManager.userColor, left: `${this.columnWidth + this.xMargin}px`, top: `${Math.max(0, this.yMargin - 9)}px` }}>
- <FontAwesomeIcon icon={'arrows-alt-h'} />
+ <FontAwesomeIcon icon="arrows-alt-h" />
</div>
);
}
@@ -439,7 +452,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
let dropAfter = 0;
if (de.complete.docDragData) {
// going to re-add the docs to the _docXFs based on position of where we just dropped
- this._docXfs.map((cd, i) => {
+ this._docXfs.forEach((cd, i) => {
const pos = cd
.stackedDocTransform()
.inverse()
@@ -496,7 +509,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
onExternalDrop = async (e: React.DragEvent): Promise<void> => {
const where = [e.clientX, e.clientY];
let targInd = -1;
- this._docXfs.map((cd, i) => {
+ this._docXfs.forEach((cd, i) => {
const pos = cd
.stackedDocTransform()
.inverse()
@@ -521,10 +534,11 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// what a section looks like if we're in stacking view
sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
const key = this.pivotField;
- let type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined = undefined;
+ let type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined;
if (this.pivotField) {
const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]);
if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) {
+ // eslint-disable-next-line prefer-destructuring
type = types[0];
}
}
@@ -557,9 +571,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
// what a section looks like if we're in masonry. Shouldn't actually need to use this.
sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => {
const key = this.pivotField;
- let type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined = undefined;
+ let type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined;
const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]);
if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) {
+ // eslint-disable-next-line prefer-destructuring
type = types[0];
}
const rows = () => (!this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this._props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))));
@@ -609,9 +624,9 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
const cm = ContextMenu.Instance;
const options = cm.findByDescription('Options...');
const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
- optionItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' });
- optionItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' });
- optionItems.push({ description: 'Clear All', event: () => (this.dataDoc[this.fieldKey ?? 'data'] = new List([])), icon: 'times' });
+ optionItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => { this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill; }, icon: 'plus' }); // prettier-ignore
+ optionItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => { this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight; }, icon: 'plus' }); // prettier-ignore
+ optionItems.push({ description: 'Clear All', event: () => { this.dataDoc[this.fieldKey ?? 'data'] = new List([]); } , icon: 'times' }); // prettier-ignore
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
}
};
@@ -700,7 +715,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
className={this.isStackingView ? 'collectionStackingView' : 'collectionMasonryView'}
ref={ele => {
this._masonryGridRef = ele;
- this.createDashEventsTarget(ele); //so the whole grid is the drop target?
+ this.createDashEventsTarget(ele); // so the whole grid is the drop target?
this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
this._oldWheel = ele;
// prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling
@@ -711,7 +726,9 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
background: this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor),
pointerEvents: (this._props.pointerEvents?.() as any) ?? this.backgroundEvents,
}}
- onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
+ onScroll={action(e => {
+ this._scroll = e.currentTarget.scrollTop;
+ })}
onDrop={this.onExternalDrop.bind(this)}
onContextMenu={this.onContextMenu}
onWheel={e => this.isContentActive() && e.stopPropagation()}>
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index c5292f880..35f330b44 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -1,7 +1,11 @@
+/* eslint-disable jsx-a11y/control-has-associated-label */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { DivHeight, DivWidth, returnEmptyString, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { RichTextField } from '../../../fields/RichTextField';
import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
@@ -9,10 +13,11 @@ import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, NumCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
-import { DivHeight, DivWidth, emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch } from '../../util/UndoManager';
@@ -95,7 +100,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
this._ele && this.props.refList.push(this._ele);
this._disposers.collapser = reaction(
() => this._props.headingObject?.collapsed,
- collapsed => (this.collapsed = collapsed !== undefined ? BoolCast(collapsed) : false),
+ collapsed => { this.collapsed = collapsed !== undefined ? BoolCast(collapsed) : false; }, // prettier-ignore
{ fireImmediately: true }
);
}
@@ -105,7 +110,6 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
this._ele = null;
}
- //TODO: what is scripting? I found it in SetInPlace def but don't know what that is
@undoBatch
columnDrop = action((e: Event, de: DragManager.DropEvent) => {
const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) };
@@ -121,13 +125,13 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
};
@action
- headingChanged = (value: string, shiftDown?: boolean) => {
+ headingChanged = (value: string /* , shiftDown?: boolean */) => {
const castedValue = this.getValue(value);
if (castedValue) {
if (this._props.colHeaderData?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
return false;
}
- this._props.pivotField && this._props.docList.forEach(d => (d[this._props.pivotField] = castedValue));
+ this._props.pivotField && this._props.docList.forEach(d => { d[this._props.pivotField] = castedValue; }) // prettier-ignore
if (this._props.headingObject) {
this._props.headingObject.setHeading(castedValue.toString());
this._heading = this._props.headingObject.heading;
@@ -143,9 +147,9 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
this._color = color;
};
- @action pointerEntered = () => SnappingManager.IsDragging && (this._background = '#b4b4b4');
- @action pointerLeave = () => (this._background = 'inherit');
- @undoBatch typedNote = (char: string) => this.addNewTextDoc('-typed text-', false, true);
+ @action pointerEntered = () => { SnappingManager.IsDragging && (this._background = '#b4b4b4'); } // prettier-ignore
+ @action pointerLeave = () => { this._background = 'inherit'}; // prettier-ignore
+ @undoBatch typedNote = () => this.addNewTextDoc('-typed text-', false, true);
@action
addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
@@ -163,7 +167,10 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
@action
deleteColumn = () => {
- this._props.pivotField && this._props.docList.forEach(d => (d[this._props.pivotField] = undefined));
+ this._props.pivotField &&
+ this._props.docList.forEach(d => {
+ d[this._props.pivotField] = undefined;
+ });
if (this._props.colHeaderData && this._props.headingObject) {
const index = this._props.colHeaderData.indexOf(this._props.headingObject);
this._props.colHeaderData.splice(index, 1);
@@ -178,8 +185,8 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
- //TODO: I think this is where I'm supposed to edit stuff
- startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
+ // TODO: I think this is where I'm supposed to edit stuff
+ startDrag = (e: PointerEvent) => {
// is MakeEmbedding a way to make a copy of a doc without rendering it?
const embedding = Doc.MakeEmbedding(this._props.Document);
embedding._width = this._props.columnWidth / (this._props.colHeaderData?.length || 1);
@@ -210,23 +217,23 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
);
};
- renderMenu = () => {
- return (
- <div className="collectionStackingView-optionPicker">
- <div className="optionOptions">
- <div className={'optionPicker' + (true ? ' active' : '')} onClick={action(() => {})}>
- Add options here
- </div>
+ renderMenu = () => (
+ <div className="collectionStackingView-optionPicker">
+ <div className="optionOptions">
+ <div className={'optionPicker' + (true ? ' active' : '')} onClick={action(() => {})}>
+ Add options here
</div>
</div>
- );
- };
+ </div>
+ );
@observable private collapsed: boolean = false;
- private toggleVisibility = action(() => (this.collapsed = !this.collapsed));
+ private toggleVisibility = action(() => {
+ this.collapsed = !this.collapsed;
+ });
- menuCallback = (x: number, y: number) => {
+ menuCallback = () => {
ContextMenu.Instance.clearItems();
const layoutItems: ContextMenuProps[] = [];
const docItems: ContextMenuProps[] = [];
@@ -257,6 +264,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
}
return this._props.addDocument?.(created);
}
+ return false;
},
icon: 'compress-arrows-alt',
})
@@ -276,6 +284,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
}
return this._props.addDocument?.(created) || false;
}
+ return false;
},
icon: 'compress-arrows-alt',
})
@@ -307,7 +316,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
const columnYMargin = this._props.headingObject ? 0 : this._props.yMargin;
const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
const noValueHeader = `NO ${key.toUpperCase()} VALUE`;
- const evContents = heading ? heading : this._props?.type === 'number' ? '0' : noValueHeader;
+ const evContents = heading || (this._props?.type === 'number' ? '0' : noValueHeader);
const headingView = this._props.headingObject ? (
<div
key={heading}
@@ -324,14 +333,19 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
onPointerDown={this.headerDown}
title={evContents === noValueHeader ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''}
style={{ background: evContents !== noValueHeader ? this._color : 'inherit' }}>
- <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
+ <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine />
<div className="collectionStackingView-sectionColor" style={{ display: evContents === noValueHeader ? 'none' : undefined }}>
- <button className="collectionStackingView-sectionColorButton" onClick={action(e => (this._paletteOn = !this._paletteOn))}>
+ <button
+ type="button"
+ className="collectionStackingView-sectionColorButton"
+ onClick={action(() => {
+ this._paletteOn = !this._paletteOn;
+ })}>
<FontAwesomeIcon icon="palette" size="lg" />
</button>
{this._paletteOn ? this.renderColorPicker() : null}
</div>
- <button className="collectionStackingView-sectionDelete" onClick={this.deleteColumn}>
+ <button type="button" className="collectionStackingView-sectionDelete" onClick={this.deleteColumn}>
<FontAwesomeIcon icon="trash" size="lg" />
</button>
{/* {evContents === noValueHeader ? null : (
@@ -352,7 +366,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
</div>
) : null;
const templatecols = `${this._props.columnWidth / this._props.numGroupColumns}px `;
- const type = this._props.Document.type;
+ const { type } = this._props.Document;
return (
<>
{this._props.Document._columnsHideIfEmpty ? null : headingView}
@@ -364,7 +378,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
style={{
padding: `${columnYMargin}px ${0}px ${this._props.yMargin}px ${0}px`,
margin: 'auto',
- width: 'max-content', //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
+ width: 'max-content', // singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
height: 'max-content',
position: 'relative',
gridGap: this._props.gridGap,
@@ -376,10 +390,10 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
{!this._props.chromeHidden && type !== DocumentType.PRES ? (
// TODO: this is the "new" button: see what you can work with here
// change cursor to pointer for this, and update dragging cursor
- //TODO: there is a bug that occurs when adding a freeform document and trying to move it around
- //TODO: would be great if there was additional space beyond the frame, so that you can actually see your
+ // TODO: there is a bug that occurs when adding a freeform document and trying to move it around
+ // TODO: would be great if there was additional space beyond the frame, so that you can actually see your
// bottom note
- //TODO: ok, so we are using a single column, and this is it!
+ // TODO: ok, so we are using a single column, and this is it!
<div
key={`${heading}-add-document`}
onKeyDown={e => e.stopPropagation()}
@@ -390,7 +404,7 @@ export class CollectionStackingViewFieldColumn extends ObservableReactComponent<
SetValue={this.addNewTextDoc}
textCallback={this.typedNote}
placeholder={"Type ':' for commands"}
- contents={<FontAwesomeIcon icon={'plus'} />}
+ contents={<FontAwesomeIcon icon="plus" />}
menuCallback={this.menuCallback}
/>
</div>
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 32198e3a2..cd401058f 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,10 +1,10 @@
import { action, computed, makeObservable, observable } from 'mobx';
import * as React from 'react';
import * as rp from 'request-promise';
-import { Utils, returnFalse } from '../../../Utils';
+import { ClientUtils, returnFalse } from '../../../ClientUtils';
import CursorField from '../../../fields/CursorField';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
-import { AclPrivate, DocData } from '../../../fields/DocSymbols';
+import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
+import { AclPrivate } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
@@ -15,16 +15,47 @@ import { GestureUtils } from '../../../pen-gestures/GestureUtils';
import { DocServer } from '../../DocServer';
import { Networking } from '../../Network';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
-import { ViewBoxBaseComponent } from '../DocComponent';
import { DocUtils, Docs, DocumentOptions } from '../../documents/Documents';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { ImageUtils } from '../../util/Import & Export/ImageUtils';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { UndoManager, undoBatch } from '../../util/UndoManager';
+import { ViewBoxBaseComponent } from '../DocComponent';
+import { FieldViewProps } from '../nodes/FieldView';
import { LoadingBox } from '../nodes/LoadingBox';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
-import { CollectionView, CollectionViewProps } from './CollectionView';
+
+export interface CollectionViewProps extends React.PropsWithChildren<FieldViewProps> {
+ isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
+ isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
+ layoutEngine?: () => string;
+ setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => void;
+ ignoreUnrendered?: boolean;
+
+ // property overrides for child documents
+ childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
+ childDocumentsActive?: () => boolean | undefined; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode)
+ childContentsActive?: () => boolean | undefined;
+ childLayoutFitWidth?: (child: Doc) => boolean;
+ childlayout_showTitle?: () => string;
+ childOpacity?: () => number;
+ childContextMenuItems?: () => { script: ScriptField; label: string }[];
+ childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection
+ childHideDecorationTitle?: boolean;
+ childHideResizeHandles?: boolean;
+ childDragAction?: dropActionType;
+ childXPadding?: number;
+ childYPadding?: number;
+ childLayoutString?: string;
+ childIgnoreNativeSize?: boolean;
+ childClickScript?: ScriptField;
+ childDoubleClickScript?: ScriptField;
+ AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
+ RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
+ hierarchyIndex?: number[]; // hierarchical index of a document up to the rendering root (primarily used for tree views)
+}
export interface SubCollectionViewProps extends CollectionViewProps {
isAnyChildContentActive: () => boolean;
@@ -53,7 +84,7 @@ export function CollectionSubView<X>(moreProps?: X) {
}
};
protected CreateDropTarget(ele: HTMLDivElement) {
- //used in schema view
+ // used in schema view
this.createDashEventsTarget(ele);
}
@@ -83,10 +114,11 @@ export function CollectionSubView<X>(moreProps?: X) {
const { Document, TemplateDataDocument } = this._props;
const validPairs = this.childDocs
.map(doc => Doc.GetLayoutDataDocPair(Document, !this._props.isAnnotationOverlay ? TemplateDataDocument : undefined, doc))
- .filter(pair => {
- // filter out any documents that have a proto that we don't have permissions to
- return !pair.layout?.hidden && pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate));
- });
+ .filter(
+ pair =>
+ // filter out any documents that have a proto that we don't have permissions to
+ !pair.layout?.hidden && pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate))
+ );
return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
@computed get childDocList() {
@@ -95,9 +127,9 @@ export function CollectionSubView<X>(moreProps?: X) {
collectionFilters = () => this._focusFilters ?? StrListCast(this.Document._childFilters);
collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.Document._childFiltersByRanges, listSpec('string'), []);
// child filters apply to the descendants of the documents in this collection
- childDocFilters = () => [...(this._props.childFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
+ childDocFilters = () => [...(this._props.childFilters?.().filter(f => ClientUtils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
// unrecursive filters apply to the documents in the collection, but no their children. See Utils.noRecursionHack
- unrecursiveDocFilters = () => [...(this._props.childFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])];
+ unrecursiveDocFilters = () => [...(this._props.childFilters?.().filter(f => !ClientUtils.IsRecursiveFilter(f)) || [])];
childDocRangeFilters = () => [...(this._props.childFiltersByRanges?.() || []), ...this.collectionRangeDocFilters()];
searchFilterDocs = () => this._props.searchFilterDocs?.() ?? DocListCast(this.Document._searchFilterDocs);
@computed.struct get childDocs() {
@@ -129,13 +161,13 @@ export function CollectionSubView<X>(moreProps?: X) {
const docsforFilter: Doc[] = [];
childDocs.forEach(d => {
// dragging facets
- const dragged = this._props.childFilters?.().some(f => f.includes(Utils.noDragDocsFilter));
- if (dragged && SnappingManager.CanEmbed && DragManager.docsBeingDragged.includes(d)) return false;
+ const dragged = this._props.childFilters?.().some(f => f.includes(ClientUtils.noDragDocsFilter));
+ if (dragged && SnappingManager.CanEmbed && DragManager.docsBeingDragged.includes(d)) return;
let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), childFiltersByRanges, this.Document).length > 0;
if (notFiltered) {
notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, childFiltersByRanges, this.Document).length > 0;
const fieldKey = Doc.LayoutFieldKey(d);
- const annos = !Field.toString(Doc.LayoutField(d) as Field).includes(CollectionView.name);
+ const annos = !Field.toString(Doc.LayoutField(d) as FieldType).includes(CollectionView.name);
const data = d[annos ? fieldKey + '_annotations' : fieldKey];
const side = annos && d[fieldKey + '_sidebar'];
if (data !== undefined || side !== undefined) {
@@ -147,7 +179,7 @@ export function CollectionSubView<X>(moreProps?: X) {
newarray = [];
subDocs.forEach(t => {
const fieldKey = Doc.LayoutFieldKey(t);
- const annos = !Field.toString(Doc.LayoutField(t) as Field).includes(CollectionView.name);
+ const annos = !Field.toString(Doc.LayoutField(t) as FieldType).includes(CollectionView.name);
notFiltered =
notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length));
DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
@@ -168,7 +200,7 @@ export function CollectionSubView<X>(moreProps?: X) {
let ind;
const doc = this.Document;
const id = Doc.UserDoc()[Id];
- const email = Doc.CurrentUserEmail;
+ const email = ClientUtils.CurrentUserEmail;
const pos = { x: position[0], y: position[1] };
if (id && email) {
const proto = Doc.GetProto(doc);
@@ -184,6 +216,7 @@ export function CollectionSubView<X>(moreProps?: X) {
if (!cursors) {
proto.cursors = cursors = new List<CursorField>();
}
+ // eslint-disable-next-line no-cond-assign
if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.data.metadata.id === id)) > -1) {
cursors[ind].setPosition(pos);
} else {
@@ -215,9 +248,9 @@ export function CollectionSubView<X>(moreProps?: X) {
moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string) => this._props.moveDocument?.(doc, targetCollection, addDocument) || false;
protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
- const docDragData = de.complete.docDragData;
+ const { docDragData } = de.complete;
if (docDragData) {
- let added = undefined;
+ let added;
const dropAction = docDragData.dropAction || docDragData.userDropAction;
const targetDocments = DocListCast(this.dataDoc[this._props.fieldKey]);
const someMoved = !dropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag));
@@ -245,8 +278,9 @@ export function CollectionSubView<X>(moreProps?: X) {
}
added === false && !this._props.isAnnotationOverlay && e.preventDefault();
added === true && e.stopPropagation();
- return added ? true : false;
- } else if (de.complete.annoDragData) {
+ return !!added;
+ }
+ if (de.complete.annoDragData) {
const dropCreator = de.complete.annoDragData.dropDocCreator;
de.complete.annoDragData.dropDocCreator = () => {
const dropped = dropCreator(this._props.isAnnotationOverlay ? this.Document : undefined);
@@ -316,7 +350,7 @@ export function CollectionSubView<X>(moreProps?: X) {
const result = (await Networking.PostToServer('/uploadRemoteImage', { sources: [imgSrc] })).lastElement();
const newImgSrc =
result.accessPaths.agnostic.client.indexOf('dashblobstore') === -1 //
- ? Utils.prepend(result.accessPaths.agnostic.client)
+ ? ClientUtils.prepend(result.accessPaths.agnostic.client)
: result.accessPaths.agnostic.client;
addDocument(ImageUtils.AssignImgInfo(Docs.Create.ImageDocument(newImgSrc, imgOpts), result));
@@ -325,39 +359,39 @@ export function CollectionSubView<X>(moreProps?: X) {
addDocument(ImageUtils.AssignImgInfo(doc, await ImageUtils.ExtractImgInfo(doc)));
}
return;
+ }
+ const path = window.location.origin + '/doc/';
+ if (text.startsWith(path)) {
+ const docId = text.replace(Doc.globalServerPath(), '').split('?')[0];
+ DocServer.GetRefField(docId).then(f => {
+ const fDoc = f;
+ if (fDoc instanceof Doc) {
+ if (options.x || options.y) {
+ fDoc.x = options.x as number;
+ fDoc.y = options.y as number;
+ } // should be in CollectionFreeFormView
+ addDocument(fDoc);
+ }
+ });
} else {
- const path = window.location.origin + '/doc/';
- if (text.startsWith(path)) {
- const docId = text.replace(Doc.globalServerPath(), '').split('?')[0];
- DocServer.GetRefField(docId).then(f => {
- if (f instanceof Doc) {
- if (options.x || options.y) {
- f.x = options.x as number;
- f.y = options.y as number;
- } // should be in CollectionFreeFormView
- f instanceof Doc && addDocument(f);
- }
- });
- } else {
- const srcWeb = SelectionManager.Views.lastElement();
- const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
- const reg = new RegExp(Utils.prepend(''), 'g');
- const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
- const backgroundColor = tags.map(tag => tag.match(/.*(background-color: ?[^;]*)/)?.[1]?.replace(/background-color: ?(.*)/, '$1')).filter(t => t)?.[0];
- const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: srcUrl ? 'from:' + srcUrl : '-web clip-', _width: 300, _height: 300, backgroundColor });
- Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
- addDocument(htmlDoc);
- if (srcWeb) {
- const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
- const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
- if (focusNode) {
- const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
- anchor && DocUtils.MakeLink(htmlDoc, anchor, {});
- }
+ const srcWeb = SelectionManager.Views.lastElement();
+ const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
+ const reg = new RegExp(ClientUtils.prepend(''), 'g');
+ const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
+ const backgroundColor = tags.map(tag => tag.match(/.*(background-color: ?[^;]*)/)?.[1]?.replace(/background-color: ?(.*)/, '$1')).filter(t => t)?.[0];
+ const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: srcUrl ? 'from:' + srcUrl : '-web clip-', _width: 300, _height: 300, backgroundColor });
+ Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
+ addDocument(htmlDoc);
+ if (srcWeb) {
+ const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
+ const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
+ if (focusNode) {
+ const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
+ anchor && DocUtils.MakeLink(htmlDoc, anchor, {});
}
}
- return;
}
+ return;
}
}
@@ -414,10 +448,15 @@ export function CollectionSubView<X>(moreProps?: X) {
for (let i = 0; i < length; i++) {
const item = e.dataTransfer.items[i];
if (item.kind === 'string' && item.type.includes('uri')) {
- const stringContents = await new Promise<string>(resolve => item.getAsString(resolve));
- const type = (await rp.head(Utils.CorsProxy(stringContents)))['content-type'];
+ // eslint-disable-next-line no-await-in-loop
+ const stringContents = await new Promise<string>(resolve => {
+ item.getAsString(resolve);
+ });
+ // eslint-disable-next-line no-await-in-loop
+ const type = (await rp.head(ClientUtils.CorsProxy(stringContents)))['content-type'];
if (type) {
- const doc = await DocUtils.DocumentFromType(type, Utils.CorsProxy(stringContents), options);
+ // eslint-disable-next-line no-await-in-loop
+ const doc = await DocUtils.DocumentFromType(type, ClientUtils.CorsProxy(stringContents), options);
doc && generatedDocuments.push(doc);
}
}
@@ -426,7 +465,7 @@ export function CollectionSubView<X>(moreProps?: X) {
file?.type && files.push(file);
file?.type === 'application/json' &&
- Utils.readUploadedFileAsText(file).then(result => {
+ ClientUtils.readUploadedFileAsText(file).then(result => {
const json = JSON.parse(result as string);
addDocument(
Docs.Create.TreeDocument(
@@ -450,7 +489,7 @@ export function CollectionSubView<X>(moreProps?: X) {
// create placeholder docs
// inside placeholder docs have some func that
- let pileUpDoc = undefined;
+ let pileUpDoc;
if (typeof files === 'string') {
const loading = Docs.Create.LoadingDocument(files, options);
generatedDocuments.push(loading);
@@ -478,20 +517,16 @@ export function CollectionSubView<X>(moreProps?: X) {
})
: [];
if (completed) completed(set);
- else {
- if (isFreeformView && generatedDocuments.length > 1) {
- pileUpDoc = DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!;
- addDocument(pileUpDoc);
- } else {
- generatedDocuments.forEach(addDocument);
- }
- }
- } else {
- if (text && !text.includes('https://')) {
- addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 }));
+ else if (isFreeformView && generatedDocuments.length > 1) {
+ pileUpDoc = DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!;
+ addDocument(pileUpDoc);
} else {
- alert('Document upload failed - possibly an unsupported file type.');
+ generatedDocuments.forEach(addDocument);
}
+ } else if (text && !text.includes('https://')) {
+ addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 }));
+ } else {
+ alert('Document upload failed - possibly an unsupported file type.');
}
};
}
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 37452ddfb..7f234ffe9 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -1,7 +1,8 @@
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
+import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, Opt, StrListCast } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { ObjectField } from '../../../fields/ObjectField';
@@ -195,7 +196,7 @@ export class CollectionTimeView extends CollectionSubView() {
let nonNumbers = 0;
this.childDocs.map(doc => {
const num = NumCast(doc[this.pivotField], Number(StrCast(doc[this.pivotField])));
- if (Number.isNaN(num)) {
+ if (isNaN(num)) {
nonNumbers++;
}
});
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 5741fc29b..32473f20b 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,6 +1,7 @@
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { DivHeight, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -8,10 +9,11 @@ import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DivHeight, emptyFunction, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero, Utils } from '../../../Utils';
+import { emptyFunction, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 18eb4dd1f..a0d84ab28 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,21 +1,20 @@
+/* eslint-disable react/jsx-props-no-spreading */
import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnEmptyString } from '../../../Utils';
-import { Doc, DocListCast, Opt } from '../../../fields/Doc';
+import { returnEmptyString } from '../../../ClientUtils';
+import { Doc, DocListCast } from '../../../fields/Doc';
import { ObjectField } from '../../../fields/ObjectField';
-import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { CollectionViewType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/Documents';
-import { dropActionType } from '../../util/DragManager';
import { ImageUtils } from '../../util/Import & Export/ImageUtils';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { OpenWhere } from '../nodes/DocumentView';
-import { FieldView, FieldViewProps } from '../nodes/FieldView';
+import { FieldView } from '../nodes/FieldView';
import { CollectionCalendarView } from './CollectionCalendarView';
import { CollectionCarousel3DView } from './CollectionCarousel3DView';
import { CollectionCarouselView } from './CollectionCarouselView';
@@ -23,7 +22,7 @@ import { CollectionDockingView } from './CollectionDockingView';
import { CollectionNoteTakingView } from './CollectionNoteTakingView';
import { CollectionPileView } from './CollectionPileView';
import { CollectionStackingView } from './CollectionStackingView';
-import { SubCollectionViewProps } from './CollectionSubView';
+import { CollectionViewProps, SubCollectionViewProps } from './CollectionSubView';
import { CollectionTimeView } from './CollectionTimeView';
import { CollectionTreeView } from './CollectionTreeView';
import './CollectionView.scss';
@@ -33,36 +32,7 @@ import { CollectionLinearView } from './collectionLinear';
import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView';
import { CollectionMultirowView } from './collectionMulticolumn/CollectionMultirowView';
import { CollectionSchemaView } from './collectionSchema/CollectionSchemaView';
-export interface CollectionViewProps extends React.PropsWithChildren<FieldViewProps> {
- isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
- isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
- layoutEngine?: () => string;
- setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => void;
- ignoreUnrendered?: boolean;
- // property overrides for child documents
- childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
- childDocumentsActive?: () => boolean | undefined; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode)
- childContentsActive?: () => boolean | undefined;
- childLayoutFitWidth?: (child: Doc) => boolean;
- childlayout_showTitle?: () => string;
- childOpacity?: () => number;
- childContextMenuItems?: () => { script: ScriptField; label: string }[];
- childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection
- childHideDecorationTitle?: boolean;
- childHideResizeHandles?: boolean;
- childDragAction?: dropActionType;
- childXPadding?: number;
- childYPadding?: number;
- childLayoutString?: string;
- childIgnoreNativeSize?: boolean;
- childClickScript?: ScriptField;
- childDoubleClickScript?: ScriptField;
- //TODO: [AL] add these fields
- AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
- RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
- hierarchyIndex?: number[]; // hierarchical index of a document up to the rendering root (primarily used for tree views)
-}
@observer
export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewProps>() implements ViewBoxInterface {
public static LayoutString(fieldStr: string) {
@@ -89,7 +59,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
// this a reaction, downstream invalidations only occur when the reaction value actually changes.
this.reactionDisposer = reaction(
() => (this.isAnyChildContentActive() ? true : this._props.isContentActive()),
- active => (this._isContentActive = active),
+ active => {
+ this._isContentActive = active;
+ },
{ fireImmediately: true }
);
}
@@ -100,13 +72,12 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
get collectionViewType(): CollectionViewType | undefined {
const viewField = StrCast(this.layoutDoc._type_collection);
if (CollectionView._safeMode) {
- switch (viewField) {
+ switch (viewField) {
case CollectionViewType.Freeform:
- case CollectionViewType.Schema:
- return CollectionViewType.Tree;
- case CollectionViewType.Invalid:
- return CollectionViewType.Freeform;
- }
+ case CollectionViewType.Schema: return CollectionViewType.Tree;
+ case CollectionViewType.Invalid: return CollectionViewType.Freeform;
+ default:
+ } // prettier-ignore
}
return viewField as any as CollectionViewType;
}
@@ -117,8 +88,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
TraceMobx();
if (type === undefined) return null;
switch (type) {
- default:
- case CollectionViewType.Freeform: return <CollectionFreeFormView key="collview" {...props} />;
case CollectionViewType.Schema: return <CollectionSchemaView key="collview" {...props} />;
case CollectionViewType.Calendar: return <CollectionCalendarView key="collview" {...props} />;
case CollectionViewType.Docking: return <CollectionDockingView key="collview" {...props} />;
@@ -134,6 +103,8 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
case CollectionViewType.Masonry: return <CollectionStackingView key="collview" {...props} />;
case CollectionViewType.Time: return <CollectionTimeView key="collview" {...props} />;
case CollectionViewType.Grid: return <CollectionGridView key="collview" {...props} />;
+ case CollectionViewType.Freeform:
+ default: return <CollectionFreeFormView key="collview" {...props} />;
}
};
@@ -144,9 +115,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
{ description: 'Freeform', event: () => func(CollectionViewType.Freeform), icon: 'signature' },
{ description: 'Schema', event: () => func(CollectionViewType.Schema), icon: 'th-list' },
{ description: 'Tree', event: () => func(CollectionViewType.Tree), icon: 'tree' },
- { description: 'Stacking', event: () => (func(CollectionViewType.Stacking)._layout_autoHeight = true), icon: 'ellipsis-v' },
+ { description: 'Stacking', event: () => {func(CollectionViewType.Stacking)._layout_autoHeight = true}, icon: 'ellipsis-v' },
{ description: 'Calendar', event: () => func(CollectionViewType.Calendar), icon: 'columns'},
- { description: 'Notetaking', event: () => (func(CollectionViewType.NoteTaking)._layout_autoHeight = true), icon: 'ellipsis-v' },
+ { description: 'Notetaking', event: () => {func(CollectionViewType.NoteTaking)._layout_autoHeight = true}, icon: 'ellipsis-v' },
{ description: 'Multicolumn', event: () => func(CollectionViewType.Multicolumn), icon: 'columns' },
{ description: 'Multirow', event: () => func(CollectionViewType.Multirow), icon: 'columns' },
{ description: 'Masonry', event: () => func(CollectionViewType.Masonry), icon: 'columns' },
@@ -178,14 +149,14 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
const options = cm.findByDescription('Options...');
const optionItems = options && 'subitems' in options ? options.subitems : [];
- !Doc.noviceMode ? optionItems.splice(0, 0, { description: `${this.Document.forceActive ? 'Select' : 'Force'} Contents Active`, event: () => (this.Document.forceActive = !this.Document.forceActive), icon: 'project-diagram' }) : null;
+ !Doc.noviceMode ? optionItems.splice(0, 0, { description: `${this.Document.forceActive ? 'Select' : 'Force'} Contents Active`, event: () => {this.Document.forceActive = !this.Document.forceActive}, icon: 'project-diagram' }) : null; // prettier-ignore
if (this.Document.childLayout instanceof Doc) {
optionItems.push({ description: 'View Child Layout', event: () => this._props.addDocTab(this.Document.childLayout as Doc, OpenWhere.addRight), icon: 'project-diagram' });
}
if (this.Document.childClickedOpenTemplateView instanceof Doc) {
optionItems.push({ description: 'View Child Detailed Layout', event: () => this._props.addDocTab(this.Document.childClickedOpenTemplateView as Doc, OpenWhere.addRight), icon: 'project-diagram' });
}
- !Doc.noviceMode && optionItems.push({ description: `${this.layoutDoc._isLightbox ? 'Unset' : 'Set'} is Lightbox`, event: () => (this.layoutDoc._isLightbox = !this.layoutDoc._isLightbox), icon: 'project-diagram' });
+ !Doc.noviceMode && optionItems.push({ description: `${this.layoutDoc._isLightbox ? 'Unset' : 'Set'} is Lightbox`, event: () => { this.layoutDoc._isLightbox = !this.layoutDoc._isLightbox; }, icon: 'project-diagram' }); // prettier-ignore
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'hand-point-right' });
@@ -200,7 +171,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
onClicks.push({
description: `Edit ${func.name} script`,
icon: 'edit',
- event: (obj: any) => {
+ event: () => {
const embedding = Doc.MakeEmbedding(this.Document);
DocUtils.makeCustomViewClicked(embedding, undefined, func.key);
this._props.addDocTab(embedding, OpenWhere.addRight);
@@ -211,7 +182,9 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
onClicks.push({
description: `Set child ${childClick.title}`,
icon: 'edit',
- event: () => (this.dataDoc[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data))),
+ event: () => {
+ this.dataDoc[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data));
+ },
})
);
!Doc.IsSystem(this.Document) && !existingOnClick && cm.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
@@ -229,7 +202,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
bodyPanelWidth = () => this._props.PanelWidth();
childLayoutTemplate = () => this._props.childLayoutTemplate?.() || Cast(this.Document.childLayoutTemplate, Doc, null);
- isContentActive = (outsideReaction?: boolean) => this._isContentActive;
+ isContentActive = () => this._isContentActive;
pointerEvents = () =>
this.layoutDoc._lockedPosition && //
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 5cb7b149b..8a2e83ed9 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -6,7 +6,8 @@ import { IReactionDisposer, ObservableSet, action, computed, makeObservable, obs
import { observer } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
-import { DashColor, Utils, emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../Utils';
+import { ClientUtils, DashColor, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -18,13 +19,14 @@ import { DocServer } from '../../DocServer';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { SelectionManager } from '../../util/SelectionManager';
-import { SettingsManager } from '../../util/SettingsManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { UndoManager, undoable } from '../../util/UndoManager';
import { DashboardView } from '../DashboardView';
+import { PinProps } from '../DocComponent';
import { LightboxView } from '../LightboxView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
@@ -32,12 +34,12 @@ import { Colors } from '../global/globalEnums';
import { DocumentView, OpenWhere, OpenWhereMod, returnEmptyDocViewList } from '../nodes/DocumentView';
import { FieldViewProps, FocusViewOptions } from '../nodes/FieldView';
import { KeyValueBox } from '../nodes/KeyValueBox';
-import { DashFieldView } from '../nodes/formattedText/DashFieldView';
-import { PinProps, PresBox, PresMovement } from '../nodes/trails';
+import { PresBox, PresMovement } from '../nodes/trails';
import { CollectionDockingView } from './CollectionDockingView';
import { CollectionView } from './CollectionView';
import './TabDocView.scss';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
+
const _global = (window /* browser */ || global) /* node */ as any;
interface TabDocViewProps {
@@ -105,7 +107,6 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
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;
}
@@ -149,17 +150,17 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />;
- const closeIcon = <FontAwesomeIcon icon={'eye'} />;
+ const closeIcon = <FontAwesomeIcon icon="eye" />;
ReactDOM.createRoot(iconWrap).render(docIcon);
ReactDOM.createRoot(closeWrap).render(closeIcon);
tab.reactComponents = [iconWrap, closeWrap];
tab.element[0].prepend(iconWrap);
tab._disposers.color = reaction(
- () => ({ variant: SettingsManager.userVariantColor, degree: Doc.GetBrushStatus(doc), highlight: DefaultStyleProvider(this._document, undefined, StyleProp.Highlighting) }),
+ () => ({ variant: SnappingManager.userVariantColor, degree: Doc.GetBrushStatus(doc), highlight: DefaultStyleProvider(this._document, undefined, StyleProp.Highlighting) }),
({ variant, degree, highlight }) => {
const color = highlight?.highlightIndex === Doc.DocBrushStatus.highlighted ? highlight.highlightColor : degree ? ['transparent', variant, variant, 'orange'][degree] : variant;
- const textColor = color === variant ? SettingsManager.userColor : lightOrDark(color);
+ const textColor = color === variant ? SnappingManager.userColor : lightOrDark(color);
titleEle.style.color = textColor;
iconWrap.style.color = textColor;
closeWrap.style.color = textColor;
@@ -407,9 +408,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
return false;
};
- getCurrentFrame = () => {
- return NumCast(Cast(PresBox.Instance.activeItem.presentation_targetDoc, Doc, null)._currentFrame);
- };
+ getCurrentFrame = () => NumCast(Cast(PresBox.Instance.activeItem.presentation_targetDoc, Doc, null)._currentFrame);
static Activate = (tabDoc: Doc) => {
const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(tab => tab.DashDoc === tabDoc && !tab.contentItem.config.props.keyValue);
tab?.header.parent.setActiveContentItem(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)
@@ -426,7 +425,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
@observable _forceInvalidateScreenToLocal = 0;
ScreenToLocalTransform = () => {
this._forceInvalidateScreenToLocal;
- const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont?.children?.[0] as HTMLElement);
+ const { translateX, translateY } = ClientUtils.GetScreenTransform(this._mainCont?.children?.[0] as HTMLElement);
return CollectionDockingView.Instance?.ScreenToLocalBoxXf().translate(-translateX, -translateY) ?? Transform.Identity();
};
PanelWidth = () => this._panelWidth;
@@ -434,7 +433,9 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
miniMapColor = () => Colors.MEDIUM_GRAY;
tabView = () => this._view;
disableMinimap = () => !this._document;
- whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive);
+ whenChildContentActiveChanges = (isActive: boolean) => {
+ this._isAnyChildContentActive = isActive;
+ };
isContentActive = () => this._isContentActive;
waitForDoubleClick = () => (SnappingManager.ExploreMode ? 'never' : undefined);
@computed get docView() {
@@ -465,9 +466,9 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
addDocument={undefined}
removeDocument={this.remDocTab}
addDocTab={this.addDocTab}
- suppressSetHeight={this._document._layout_fitWidth ? true : false}
+ suppressSetHeight={!!this._document._layout_fitWidth}
ScreenToLocalTransform={this.ScreenToLocalTransform}
- dontCenter={'y'}
+ dontCenter="y"
whenChildContentsActiveChanged={this.whenChildContentActiveChanges}
focus={this.focusFunc}
containerViewPath={returnEmptyDoclist}
@@ -485,12 +486,13 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
style={{
fontFamily: Doc.UserDoc().renderStyle === 'comic' ? 'Comic Sans MS' : undefined,
}}
- onPointerOver={action(() => (this._hovering = true))}
- onPointerLeave={action(() => (this._hovering = false))}
- onDragOver={action(() => (this._hovering = true))}
- onDragLeave={action(() => (this._hovering = false))}
+ onPointerOver={action(() => { this._hovering = true; })} // prettier-ignore
+ onPointerLeave={action(() => { this._hovering = false; })} // prettier-ignore
+ onDragOver={action(() => { this._hovering = true; })} // prettier-ignore
+ onDragLeave={action(() => { this._hovering = false; })} // prettier-ignore
ref={ref => {
- if ((this._mainCont = ref)) {
+ this._mainCont = ref;
+ if (this._mainCont) {
if (this._lastTab) {
this._view && DocumentManager.Instance.RemoveView(this._view);
}
@@ -524,7 +526,8 @@ interface TabMiniThumbProps {
@observer
class TabMiniThumb extends React.Component<TabMiniThumbProps> {
render() {
- return <div className="miniThumb" style={{ width: `${this.props.miniWidth()}% `, height: `${this.props.miniHeight()}% `, left: `${this.props.miniLeft()}% `, top: `${this.props.miniTop()}% ` }} />;
+ const { miniWidth, miniHeight, miniLeft, miniTop } = this.props;
+ return <div className="miniThumb" style={{ width: `${miniWidth()}%`, height: `${miniHeight()}%`, left: `${miniLeft()}%`, top: `${miniTop()}%` }} />;
}
}
@observer
@@ -532,14 +535,10 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps
static miniStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string): any => {
if (doc) {
switch (property.split(':')[0]) {
- default:
- return DefaultStyleProvider(doc, props, property);
- case StyleProp.PointerEvents:
- return 'none';
- case StyleProp.DocContents:
- const background = ((type: DocumentType) => {
- // prettier-ignore
- switch (type) {
+ case StyleProp.PointerEvents: return 'none';
+ case StyleProp.DocContents: {
+ const background = (() => {
+ switch (doc.type as DocumentType) {
case DocumentType.PDF: return 'pink';
case DocumentType.AUDIO: return 'lightgreen';
case DocumentType.WEB: return 'brown';
@@ -549,10 +548,12 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps
case DocumentType.RTF: return 'yellow';
case DocumentType.COL: return undefined;
default: return 'gray';
- }
- })(doc.type as DocumentType);
+ } // prettier-ignore
+ })();
return !background ? undefined : <div style={{ width: NumCast(doc._width), height: NumCast(doc._height), position: 'absolute', display: 'block', background }} />;
- }
+ }
+ default: return DefaultStyleProvider(doc, props, property);
+ } // prettier-ignore
}
};
@@ -639,7 +640,7 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps
render() {
return this._props.document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._props.document)) || this._props.document?._type_collection !== CollectionViewType.Freeform ? null : (
<div className="miniMap-hidden">
- <Popup icon={<FontAwesomeIcon icon="globe-asia" size="lg" />} color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement="top-end" popup={this.popup} />
+ <Popup icon={<FontAwesomeIcon icon="globe-asia" size="lg" />} color={SnappingManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement="top-end" popup={this.popup} />
</div>
);
}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 4fd49f8fe..e266ccd14 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,11 +1,15 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IconButton, Size } from 'browndash-components';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../Utils';
-import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../fields/Doc';
+import { ClientUtils, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
+import { Doc, DocListCast, Field, FieldType, FieldResult, Opt, StrListCast } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
@@ -17,7 +21,8 @@ import { TraceMobx } from '../../../fields/util';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DocUtils, Docs } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { LinkManager } from '../../util/LinkManager';
import { SettingsManager } from '../../util/SettingsManager';
import { SnappingManager } from '../../util/SnappingManager';
@@ -35,10 +40,12 @@ import { CollectionTreeView, TreeViewType } from './CollectionTreeView';
import { CollectionView } from './CollectionView';
import { TreeSort } from './TreeSort';
import './TreeView.scss';
+
const { TREE_BULLET_WIDTH } = require('../global/globalCssVariables.module.scss'); // prettier-ignore
export interface TreeViewProps {
treeView: CollectionTreeView;
+ // eslint-disable-next-line no-use-before-define
parentTreeView: TreeView | CollectionTreeView | undefined;
observeHeight: (ref: any) => void;
unobserveHeight: (ref: any) => void;
@@ -87,6 +94,7 @@ const treeBulletWidth = function () {
*/
@observer
export class TreeView extends ObservableReactComponent<TreeViewProps> {
+ // eslint-disable-next-line no-use-before-define
static _editTitleOnLoad: Opt<{ id: string; parent: TreeView | CollectionTreeView | undefined }>;
static _openTitleScript: Opt<ScriptField | undefined>;
static _openLevelScript: Opt<ScriptField | undefined>;
@@ -101,6 +109,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
get treeViewOpenIsTransient() {
return this.treeView.Document.treeView_OpenIsTransient || Doc.IsDataProto(this.Document);
}
+ @computed get treeViewOpen() {
+ return (!this.treeViewOpenIsTransient && Doc.GetT(this.Document, 'treeView_Open', 'boolean', true)) || this._transientOpenState;
+ }
set treeViewOpen(c: boolean) {
if (this.treeViewOpenIsTransient) this._transientOpenState = c;
else {
@@ -137,9 +148,6 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@computed get Document() {
return this._props.Document;
}
- @computed get treeViewOpen() {
- return (!this.treeViewOpenIsTransient && Doc.GetT(this.Document, 'treeView_Open', 'boolean', true)) || this._transientOpenState;
- }
@computed get treeViewExpandedView() {
return this.validExpandViewTypes.includes(StrCast(this.Document.treeView_ExpandedView)) ? StrCast(this.Document.treeView_ExpandedView) : this.defaultExpandedView;
}
@@ -221,7 +229,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this.treeViewOpen = !this.treeViewOpen;
} else {
// choose an appropriate embedding or make one. --- choose the first embedding that (1) user owns, (2) has no context field ... otherwise make a new embedding
- const bestEmbedding = docView.Document.author === Doc.CurrentUserEmail && !Doc.IsDataProto(docView.Document) ? docView.Document : Doc.BestEmbedding(docView.Document);
+ const bestEmbedding = docView.Document.author === ClientUtils.CurrentUserEmail && !Doc.IsDataProto(docView.Document) ? docView.Document : Doc.BestEmbedding(docView.Document);
this._props.addDocTab(bestEmbedding, OpenWhere.lightbox);
}
};
@@ -230,7 +238,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
recurToggle = (childList: Doc[]) => {
if (childList.length > 0) {
childList.forEach(child => {
- child.runProcess = !!!child.runProcess;
+ child.runProcess = !child.runProcess;
TreeView.ToggleChildrenRun.get(child)?.();
});
}
@@ -273,9 +281,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this.recurToggle(this.childDocs);
});
- TreeView.GetRunningChildren.set(this.Document, () => {
- return this.getRunningChildren(this.childDocs);
- });
+ TreeView.GetRunningChildren.set(this.Document, () => this.getRunningChildren(this.childDocs));
}
_treeEle: any;
@@ -301,7 +307,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
super.componentDidUpdate(prevProps);
this._disposers.opening = reaction(
() => this.treeViewOpen,
- open => !open && (this._renderCount = 20)
+ open => {
+ !open && (this._renderCount = 20);
+ }
);
this._props.hierarchyIndex !== undefined && this._props.AddToMap?.(this.Document, this._props.hierarchyIndex);
}
@@ -324,7 +332,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
document.addEventListener('pointerup', this.onDragUp, true);
}
};
- onPointerLeave = (e: React.PointerEvent): void => {
+ onPointerLeave = (): void => {
Doc.UnBrushDoc(this.dataDoc);
if (this._header.current?.className !== 'treeView-header-editing') {
this._header.current!.className = 'treeView-header';
@@ -385,7 +393,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return this.localAdd(folder);
};
- preTreeDrop = (e: Event, de: DragManager.DropEvent, docDropAction: dropActionType) => {
+ preTreeDrop = () => {
// fall through and let the CollectionTreeView handle this since treeView items have no special properties of their own
};
@@ -403,7 +411,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
e.stopPropagation();
return true;
}
- const docDragData = de.complete.docDragData;
+ const { docDragData } = de.complete;
if (docDragData && pt[0] < rect.left + rect.width) {
if (docDragData.draggedDocuments[0] === this.Document) return true;
const added = this.dropDocuments(
@@ -462,8 +470,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
refTransform = (ref: HTMLDivElement | undefined | null) => {
if (!ref) return this.ScreenToLocalTransform();
- const { scale, translateX, translateY } = Utils.GetScreenTransform(ref);
- const outerXf = Utils.GetScreenTransform(this.treeView.MainEle());
+ const { translateX, translateY } = ClientUtils.GetScreenTransform(ref);
+ const outerXf = ClientUtils.GetScreenTransform(this.treeView.MainEle());
const offset = this.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY);
return this.ScreenToLocalTransform().translate(offset[0], offset[1]);
};
@@ -490,14 +498,19 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const ids: { [key: string]: string } = {};
const rows: JSX.Element[] = [];
const doc = this.Document;
- doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
+ doc &&
+ Object.keys(doc).forEach(key => {
+ !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key);
+ });
+ // eslint-disable-next-line no-restricted-syntax
for (const key of Object.keys(ids).slice().sort()) {
+ // eslint-disable-next-line no-continue
if (this._props.skipFields?.includes(key) || key === 'title' || key === 'treeView_Open') continue;
const contents = doc[key];
let contentElement: (JSX.Element | null)[] | JSX.Element = [];
- let leftOffset = observable({ width: 0 });
+ const leftOffset = observable({ width: 0 });
const expandedWidth = () => this._props.panelWidth() - leftOffset.width;
if (contents instanceof Doc || (Cast(contents, listSpec(Doc)) && Cast(contents, listSpec(Doc))!.length && Cast(contents, listSpec(Doc))![0] instanceof Doc)) {
const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
@@ -549,7 +562,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
contentElement = (
<EditableView
key="editableView"
- contents={contents !== undefined ? Field.toString(contents as Field) : 'null'}
+ contents={contents !== undefined ? Field.toString(contents as FieldType) : 'null'}
height={13}
fontSize={12}
GetValue={() => Field.toKeyValueString(doc, key)}
@@ -572,15 +585,15 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
);
}
rows.push(
- <div style={{ display: 'flex', overflow: 'auto' }} key={'newKeyValue'}>
+ <div style={{ display: 'flex', overflow: 'auto' }} key="newKeyValue">
<EditableView
key="editableView"
- contents={'+key=value'}
+ contents="+key=value"
height={13}
fontSize={12}
GetValue={returnEmptyString}
SetValue={input => {
- const match = input.match(/([a-zA-Z0-9_-]+)(=|=:=)([a-zA-Z,_@\?\+\-\*\/\ 0-9\(\)]+)/);
+ const match = input.match(/([a-zA-Z0-9_-]+)(=|=:=)([a-zA-Z,_@?+\-*/ 0-9()]+)/);
if (match) {
const key = match[1];
const assign = match[2];
@@ -620,7 +633,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
doc.zIndex = addBefore ? NumCast(addBefore.zIndex) + (before ? -0.5 : 0.5) : 1000;
docs.push(doc);
- docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => (d.zIndex = i));
+ docs.sort((a, b) => (NumCast(a.zIndex) > NumCast(b.zIndex) ? 1 : -1)).forEach((d, i) => {
+ d.zIndex = i;
+ });
}
const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField;
const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false);
@@ -630,8 +645,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
};
const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
const docs = expandKey === 'embeddings' ? this.childEmbeddings : expandKey === 'links' ? this.childLinks : expandKey === 'annotations' ? this.childAnnos : this.childDocs;
- let downX = 0,
- downY = 0;
+ let downX = 0;
+ let downY = 0;
if (docs?.length && this._renderCount < docs?.length) {
this._renderTimer && clearTimeout(this._renderTimer);
this._renderTimer = setTimeout(
@@ -667,7 +682,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
style={{ cursor: 'inherit' }}
key={expandKey + 'more'}
title={`Sorted by : ${this.Document.treeView_SortCriterion}. click to cycle`}
- className="" //this.doc.treeView_HideTitle ? 'no-indent' : ''}
+ className="" // this.doc.treeView_HideTitle ? 'no-indent' : ''}
onPointerDown={e => {
downX = e.clientX;
downY = e.clientY;
@@ -719,7 +734,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
</ul>
</div>
);
- } else if (this.treeViewExpandedView === 'fields') {
+ }
+ if (this.treeViewExpandedView === 'fields') {
return (
<ul key={this.Document[Id] + this.Document.title} style={{ cursor: 'inherit' }}>
<div>{this.expandedField}</div>
@@ -891,14 +907,15 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
titleStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
if (!doc || doc !== this.Document) return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
- const treeView = this.treeView;
+ const { treeView } = this;
// prettier-ignore
switch (property.split(':')[0]) {
case StyleProp.Opacity: return this.treeView.outlineMode ? undefined : 1;
case StyleProp.BackgroundColor: return this.selected ? '#7089bb' : undefined;//StrCast(doc._backgroundColor, StrCast(doc.backgroundColor));
case StyleProp.Highlighting: if (this.treeView.outlineMode) return undefined;
+ break;
case StyleProp.BoxShadow: return undefined;
- case StyleProp.DocContents:
+ case StyleProp.DocContents: {
const highlightIndex = this.treeView.outlineMode ? Doc.DocBrushStatus.unbrushed : Doc.GetBrushHighlightStatus(doc);
const highlightColor = ['transparent', 'rgb(68, 118, 247)', 'rgb(68, 118, 247)', 'orange', 'lightBlue'][highlightIndex];
return treeView.outlineMode ? null : (
@@ -917,6 +934,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
{StrCast(doc?.title)}
</div>
);
+ }
+ default:
}
return treeView._props.styleProvider?.(doc, props, property);
};
@@ -924,7 +943,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
if (property.startsWith(StyleProp.Decorations)) return null;
return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
};
- onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
+ onKeyDown = (e: React.KeyboardEvent) => {
if (this.Document.treeView_HideHeader || (this.Document.treeView_HideHeaderIfTemplate && this.treeView._props.childLayoutTemplate?.()) || this.treeView.outlineMode) {
switch (e.key) {
case 'Tab':
@@ -944,6 +963,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
e.stopPropagation?.();
e.preventDefault?.();
return UndoManager.RunInBatch(this.makeTextCollection, 'bullet');
+ default:
}
}
return false;
@@ -959,22 +979,24 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const view = this._editTitle ? (
<EditableView
key="_editTitle"
- oneLine={true}
- display={'inline-block'}
+ oneLine
+ display="inline-block"
editing={this._editTitle}
- background={'#7089bb'}
+ background="#7089bb"
contents={StrCast(this.Document.title)}
height={12}
- sizeToContent={true}
+ sizeToContent
fontSize={12}
- isEditingCallback={action(e => (this._editTitle = e))}
+ isEditingCallback={action(e => {
+ this._editTitle = e;
+ })}
GetValue={() => StrCast(this.Document.title)}
OnTab={undoBatch((shift?: boolean) => {
if (!shift) this._props.indentDocument?.(true);
else this._props.outdentDocument?.(true);
})}
OnEmpty={undoBatch(() => this.treeView.outlineMode && this._props.removeDoc?.(this.Document))}
- OnFillDown={val => this.treeView.fileSysMode && this.makeFolder()}
+ OnFillDown={() => this.treeView.fileSysMode && this.makeFolder()}
SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => {
Doc.SetInPlace(this.Document, 'title', value, false);
this.treeView.outlineMode && enterKey && this.makeTextCollection();
@@ -984,7 +1006,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
<DocumentView
key="title"
ref={action((r: any) => {
- this._docRef = r ? r : undefined;
+ this._docRef = r || undefined;
if (this._docRef && TreeView._editTitleOnLoad?.id === this.Document[Id] && TreeView._editTitleOnLoad.parent === this._props.parentTreeView) {
this._docRef.select(false);
this.setEditTitle(this._docRef);
@@ -994,8 +1016,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
Document={this.Document}
layout_fitWidth={returnTrue}
scriptContext={this}
- hideDecorations={true}
- hideClickBehaviors={true}
+ hideDecorations
+ hideClickBehaviors
styleProvider={this.titleStyleProvider}
onClickScriptDisable="never" // tree docViews have a script to show fields, etc.
containerViewPath={this.treeView.childContainerViewPath}
@@ -1015,7 +1037,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
PanelHeight={return18}
contextMenuItems={this.contextMenuItems}
renderDepth={1}
- isContentActive={emptyFunction} //this._props.isContentActive}
+ isContentActive={emptyFunction} // this._props.isContentActive}
isDocumentActive={this._props.isContentActive}
focus={this.refocus}
whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
@@ -1045,99 +1067,101 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}}>
{view}
</div>
- <div className="treeView-rightButtons" ref={action((r: any) => r && (this.headerEleWidth = r.getBoundingClientRect().width))}>
+ <div
+ className="treeView-rightButtons"
+ ref={action((r: any) => {
+ r && (this.headerEleWidth = r.getBoundingClientRect().width);
+ })}>
{this.titleButtons}
</div>
</>
);
}
- renderBulletHeader = (contents: JSX.Element, editing: boolean) => {
- return (
- <>
+ renderBulletHeader = (contents: JSX.Element, editing: boolean) => (
+ <>
+ <div
+ className={`treeView-header` + (editing ? '-editing' : '')}
+ key="titleheader"
+ ref={this._header}
+ onClick={this.ignoreEvent}
+ onPointerDown={e => {
+ this.treeView.isContentActive() &&
+ setupMoveUpEvents(
+ this,
+ e,
+ () => {
+ (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any);
+ return true;
+ },
+ returnFalse,
+ emptyFunction
+ );
+ }}
+ onPointerEnter={this.onPointerEnter}
+ onPointerLeave={this.onPointerLeave}>
<div
- className={`treeView-header` + (editing ? '-editing' : '')}
- key="titleheader"
- ref={this._header}
- onClick={this.ignoreEvent}
- onPointerDown={e => {
- this.treeView.isContentActive() &&
- setupMoveUpEvents(
- this,
- e,
- () => {
- (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any);
- return true;
- },
- returnFalse,
- emptyFunction
- );
+ className="treeView-background"
+ style={{
+ background: SettingsManager.userColor,
}}
- onPointerEnter={this.onPointerEnter}
- onPointerLeave={this.onPointerLeave}>
- <div
- className="treeView-background"
- style={{
- background: SettingsManager.userColor,
- }}
- />
- {contents}
- </div>
- {this.renderBorder}
- </>
- );
- };
-
- fitWidthFilter = (doc: Doc) => (doc.type === DocumentType.IMG ? false : undefined);
- renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => {
- return (
- <div style={{ height: this.embeddedPanelHeight(), width: this.embeddedPanelWidth() }}>
- <DocumentView
- key={this.Document[Id]}
- ref={action((r: DocumentView | null) => (this._dref = r))}
- Document={this.Document}
- layout_fitWidth={this.fitWidthFilter}
- PanelWidth={this.embeddedPanelWidth}
- PanelHeight={this.embeddedPanelHeight}
- LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
- LayoutTemplate={this.treeView._props.childLayoutTemplate}
- isContentActive={isActive}
- isDocumentActive={isActive}
- styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
- fitContentsToBox={returnTrue}
- hideTitle={asText}
- hideDecorations={true}
- hideClickBehaviors={true}
- hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)}
- dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)}
- ScreenToLocalTransform={this.docTransform}
- renderDepth={this._props.renderDepth + 1}
- onClickScript={this.onChildClick}
- onKey={this.onKeyDown}
- containerViewPath={this.treeView.childContainerViewPath}
- childFilters={returnEmptyFilter}
- childFiltersByRanges={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- focus={this.refocus}
- addDocument={this._props.addDocument}
- moveDocument={this.move}
- removeDocument={this._props.removeDoc}
- whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
- xPadding={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)}
- yPadding={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)}
- addDocTab={this._props.addDocTab}
- pinToPres={this.treeView._props.pinToPres}
- disableBrushing={this.treeView._props.disableBrushing}
- scriptContext={this}
/>
+ {contents}
</div>
- );
- };
+ {this.renderBorder}
+ </>
+ );
+
+ fitWidthFilter = (doc: Doc) => (doc.type === DocumentType.IMG ? false : undefined);
+ renderEmbeddedDocument = (asText: boolean, isActive: () => boolean | undefined) => (
+ <div style={{ height: this.embeddedPanelHeight(), width: this.embeddedPanelWidth() }}>
+ <DocumentView
+ key={this.Document[Id]}
+ ref={action((r: DocumentView | null) => {
+ this._dref = r;
+ })}
+ Document={this.Document}
+ layout_fitWidth={this.fitWidthFilter}
+ PanelWidth={this.embeddedPanelWidth}
+ PanelHeight={this.embeddedPanelHeight}
+ LayoutTemplateString={asText ? FormattedTextBox.LayoutString('text') : undefined}
+ LayoutTemplate={this.treeView._props.childLayoutTemplate}
+ isContentActive={isActive}
+ isDocumentActive={isActive}
+ styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
+ fitContentsToBox={returnTrue}
+ hideTitle={asText}
+ hideDecorations
+ hideClickBehaviors
+ hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)}
+ dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)}
+ ScreenToLocalTransform={this.docTransform}
+ renderDepth={this._props.renderDepth + 1}
+ onClickScript={this.onChildClick}
+ onKey={this.onKeyDown}
+ containerViewPath={this.treeView.childContainerViewPath}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ focus={this.refocus}
+ addDocument={this._props.addDocument}
+ moveDocument={this.move}
+ removeDocument={this._props.removeDoc}
+ whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
+ xPadding={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)}
+ yPadding={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)}
+ addDocTab={this._props.addDocTab}
+ pinToPres={this.treeView._props.pinToPres}
+ disableBrushing={this.treeView._props.disableBrushing}
+ scriptContext={this}
+ />
+ </div>
+ );
// renders the text version of a document as the header. This is used in the file system mode and in other vanilla tree views.
@computed get renderTitleAsHeader() {
return this.treeView.Document.treeView_HideUnrendered && this.Document.layout_unrendered && !this.Document.treeView_FieldKey ? (
- <div></div>
+ <div />
) : (
<>
{this.renderBullet}
@@ -1147,14 +1171,12 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}
// renders the document in the header field instead of a text proxy.
- renderDocumentAsHeader = (asText: boolean) => {
- return (
- <>
- {this.renderBullet}
- {this.renderEmbeddedDocument(asText, this._props.isContentActive)}
- </>
- );
- };
+ renderDocumentAsHeader = (asText: boolean) => (
+ <>
+ {this.renderBullet}
+ {this.renderEmbeddedDocument(asText, this._props.isContentActive)}
+ </>
+ );
@computed get renderBorder() {
const sorting = StrCast(this.Document.treeView_SortCriterion, TreeSort.WhenAdded);
@@ -1185,7 +1207,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
className={`treeView-container${this._props.isContentActive() ? '-active' : ''}`}
ref={this.createTreeDropTarget}
onDrop={this.onTreeDrop}
- //onPointerDown={e => this._props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
+ // onPointerDown={e => this._props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
// onKeyDown={this.onKeyDown}
>
<li className="collection-child">
@@ -1209,11 +1231,10 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const aN = parseInt(a.match(reN)![0], 10);
const bN = parseInt(b.match(reN)![0], 10);
return aN === bN ? 0 : aN > bN ? 1 : -1;
- } else {
- return aA > bA ? 1 : -1;
}
+ return aA > bA ? 1 : -1;
};
- docs.sort(function (d1, d2): 0 | 1 | -1 {
+ docs.sort((d1, d2): 0 | 1 | -1 => {
const a = criterion === TreeSort.AlphaUp ? d2 : d1;
const b = criterion === TreeSort.AlphaUp ? d1 : d2;
const first = a[criterion === TreeSort.Zindex ? 'zIndex' : 'title'];
@@ -1230,7 +1251,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
childDocs: Doc[],
treeView: CollectionTreeView,
parentTreeView: CollectionTreeView | TreeView | undefined,
- treeView_Parent: Doc,
+ treeViewParent: Doc,
dataDoc: Doc | undefined,
parentCollectionDoc: Doc | undefined,
containerPrevSibling: Doc | undefined,
@@ -1244,7 +1265,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
isContentActive: (outsideReaction?: boolean) => boolean,
panelWidth: () => number,
renderDepth: number,
- treeView_HideHeaderFields: () => boolean,
+ treeViewHideHeaderFields: () => boolean,
renderedIds: string[],
onCheckedClick: undefined | (() => ScriptField),
onChildClick: undefined | (() => ScriptField),
@@ -1261,19 +1282,19 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
hierarchyIndex?: number[],
renderCount?: number
) {
- const viewSpecScript = Cast(treeView_Parent.viewSpecScript, ScriptField);
+ const viewSpecScript = Cast(treeViewParent.viewSpecScript, ScriptField);
if (viewSpecScript) {
childDocs = childDocs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result);
}
- const docs = TreeView.sortDocs(childDocs, StrCast(treeView_Parent.treeView_SortCriterion, TreeSort.WhenAdded));
+ const docs = TreeView.sortDocs(childDocs, StrCast(treeViewParent.treeView_SortCriterion, TreeSort.WhenAdded));
const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView._props.NativeDimScaling?.() || 1);
- const treeView_Refs = new Map<Doc, TreeView | undefined>();
+ const treeViewRefs = new Map<Doc, TreeView | undefined>();
return docs
.filter(child => child instanceof Doc)
.map((child, i) => {
if (renderCount && i > renderCount) return null;
- const pair = Doc.GetLayoutDataDocPair(treeView_Parent, dataDoc, child);
+ const pair = Doc.GetLayoutDataDocPair(treeViewParent, dataDoc, child);
if (!pair.layout || pair.data instanceof Promise) {
return null;
}
@@ -1290,7 +1311,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
Doc.SetContainer(child, treeView.Document);
}
};
- const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeView_Refs.get(docs[i - 1]));
+ const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
const outdent = !parentCollectionDoc ? undefined : (editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, containerPrevSibling, parentTreeView instanceof TreeView ? parentTreeView._props.parentTreeView : undefined);
const addDocument = (doc: Doc | Doc[], annotationKey?: string, relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false);
const childLayout = Doc.Layout(pair.layout);
@@ -1301,10 +1322,10 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return (
<TreeView
key={child[Id]}
- ref={r => treeView_Refs.set(child, r ? r : undefined)}
+ ref={r => treeViewRefs.set(child, r || undefined)}
Document={pair.layout}
dataDoc={pair.data}
- treeViewParent={treeView_Parent}
+ treeViewParent={treeViewParent}
prevSibling={docs[i]}
// TODO: [AL] add these
hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
@@ -1316,7 +1337,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
onCheckedClick={onCheckedClick}
onChildClick={onChildClick}
renderDepth={renderDepth}
- removeDoc={StrCast(treeView_Parent.treeView_FreezeChildren).includes('remove') ? undefined : remove}
+ removeDoc={StrCast(treeViewParent.treeView_FreezeChildren).includes('remove') ? undefined : remove}
addDocument={addDocument}
styleProvider={styleProvider}
panelWidth={rowWidth}
@@ -1327,7 +1348,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
addDocTab={addDocTab}
ScreenToLocalTransform={screenToLocalXf}
isContentActive={isContentActive}
- treeViewHideHeaderFields={treeView_HideHeaderFields}
+ treeViewHideHeaderFields={treeViewHideHeaderFields}
renderedIds={renderedIds}
skipFields={skipFields}
firstLevel={firstLevel}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
index cc729decc..29d835b28 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
@@ -1,7 +1,7 @@
import { makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCast, Field, FieldResult } from '../../../../fields/Doc';
+import { Doc, DocListCast, FieldType, FieldResult } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
import { StrCast } from '../../../../fields/Types';
import { DocumentManager } from '../../../util/DocumentManager';
@@ -10,13 +10,14 @@ import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { TopBar } from '../../topbar/TopBar';
import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState';
-import { CollectionFreeFormView } from './CollectionFreeFormView';
import './CollectionFreeFormView.scss';
+import { DocData } from '../../../../fields/DocSymbols';
export interface CollectionFreeFormInfoUIProps {
Document: Doc;
- Freeform: CollectionFreeFormView;
- close: () => boolean;
+ LayoutDoc: Doc;
+ childDocs: () => Doc[];
+ close: () => void;
}
@observer
@@ -32,10 +33,10 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
@observable _currState: infoState | undefined = undefined;
get currState() { return this._currState; } // prettier-ignore
- set currState(val) { runInAction(() => (this._currState = val)); } // prettier-ignore
+ set currState(val) { runInAction(() => {this._currState = val;}); } // prettier-ignore
componentWillUnmount(): void {
- this._props.Freeform.dataDoc.backgroundColor = this._originalbackground;
+ this._props.Document[DocData].backgroundColor = this._originalbackground;
}
setCurrState = (state: infoState) => {
@@ -46,16 +47,16 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
};
setupStates = () => {
- this._originalbackground = StrCast(this._props.Freeform.dataDoc.backgroundColor);
+ this._originalbackground = StrCast(this._props.Document[DocData].backgroundColor);
// state entry functions
- const setBackground = (colour: string) => () => (this._props.Freeform.dataDoc.backgroundColor = colour);
- const setOpacity = (opacity: number) => () => (this._props.Freeform.layoutDoc.opacity = opacity);
+ const setBackground = (colour: string) => () => {this._props.Document[DocData].backgroundColor = colour;} // prettier-ignore
+ const setOpacity = (opacity: number) => () => {this._props.LayoutDoc.opacity = opacity;} // prettier-ignore
// arc transition trigger conditions
- const firstDoc = () => (this._props.Freeform.childDocs.length ? this._props.Freeform.childDocs[0] : undefined);
- const numDocs = () => this._props.Freeform.childDocs.length;
+ const firstDoc = () => (this._props.childDocs().length ? this._props.childDocs()[0] : undefined);
+ const numDocs = () => this._props.childDocs().length;
- let docX: FieldResult<Field>;
- let docY: FieldResult<Field>;
+ let docX: FieldResult<FieldType>;
+ let docY: FieldResult<FieldType>;
const docNewX = () => firstDoc()?.x;
const docNewY = () => firstDoc()?.y;
@@ -244,12 +245,12 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
// editPresentation: [() => presentationMode() === 'edit', () => editPresentationMode],
manualPresentation: [() => presentationMode() === 'manual', () => manualPresentationMode],
docRemoved: [() => numDocs() < 3, () => viewedLink],
- docCreated: [() => numDocs() == 4, () => completed],
+ docCreated: [() => numDocs() === 4, () => completed],
});
const completed = InfoState(
'Eager to learn more? Click the ? icon in the top right corner to read our full documentation.',
- { docRemoved: [() => numDocs() == 1, () => oneDoc] },
+ { docRemoved: [() => numDocs() === 1, () => oneDoc] },
'documentation.png',
() => TopBar.Instance.FlipDocumentationIcon()
); // prettier-ignore
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index c83c26509..a0b96c75a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -1,4 +1,4 @@
-import { Doc, Field, FieldResult } from '../../../../fields/Doc';
+import { Doc, Field, FieldType, FieldResult } from '../../../../fields/Doc';
import { Id, ToString } from '../../../../fields/FieldSymbols';
import { ObjectField } from '../../../../fields/ObjectField';
import { RefField } from '../../../../fields/RefField';
@@ -50,7 +50,7 @@ export interface ViewDefResult {
bounds?: ViewDefBounds;
inkMask?: number; //sort elements into either the mask layer (which has a mixedBlendMode appropriate for transparent masks), or the regular documents layer; -1 = no mask, 0 = mask layer but stroke is transparent (hidden, as in during a presentation when you want to smoothly animate it into being a mask), >0 = mask layer and not hidden
}
-function toLabel(target: FieldResult<Field>) {
+function toLabel(target: FieldResult<FieldType>) {
if (typeof target === 'number' || Number(target)) {
const truncated = Number(Number(target).toFixed(0));
const precise = Number(Number(target).toFixed(2));
@@ -128,7 +128,7 @@ export function computeStarburstLayout(poolData: Map<string, PoolData>, pivotDoc
export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) {
const docMap = new Map<string, PoolData>();
const fieldKey = 'data';
- const pivotColumnGroups = new Map<FieldResult<Field>, PivotColumn>();
+ const pivotColumnGroups = new Map<FieldResult<FieldType>, PivotColumn>();
let nonNumbers = 0;
const pivotFieldKey = toLabel(engineProps?.pivotField ?? pivotDoc._pivotField) || 'author';
@@ -136,10 +136,10 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
const listValue = Cast(pair.layout[pivotFieldKey], listSpec('string'), null);
const num = toNumber(pair.layout[pivotFieldKey]);
- if (num === undefined || Number.isNaN(num)) {
+ if (num === undefined || isNaN(num)) {
nonNumbers++;
}
- const val = Field.toString(pair.layout[pivotFieldKey] as Field);
+ const val = Field.toString(pair.layout[pivotFieldKey] as FieldType);
if (listValue) {
listValue.forEach((val, i) => {
!pivotColumnGroups.get(val) && pivotColumnGroups.set(val, { docs: [], filters: [val], replicas: [] });
@@ -265,7 +265,7 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
return normalizeResults(panelDim, max_text, docMap, poolData, viewDefsToJSX, groupNames, 0, []);
}
-function toNumber(val: FieldResult<Field>) {
+function toNumber(val: FieldResult<FieldType>) {
return val === undefined ? undefined : NumCast(val, Number(StrCast(val)));
}
@@ -274,7 +274,7 @@ export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc:
const pivotDateGroups = new Map<number, Doc[]>();
const docMap = new Map<string, PoolData>();
const groupNames: ViewDefBounds[] = [];
- const timelineFieldKey = Field.toString(pivotDoc._pivotField as Field);
+ const timelineFieldKey = Field.toString(pivotDoc._pivotField as FieldType);
const curTime = toNumber(pivotDoc[fieldKey + '-timelineCur']);
const curTimeSpan = Cast(pivotDoc[fieldKey + '-timelineSpan'], 'number', null);
const minTimeReq = curTimeSpan === undefined ? Cast(pivotDoc[fieldKey + '-timelineMinReq'], 'number', null) : curTime && curTime - curTimeSpan;
@@ -290,7 +290,7 @@ export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc:
let maxTime = maxTimeReq === undefined ? -Number.MAX_VALUE : maxTimeReq;
childPairs.forEach(pair => {
const num = NumCast(pair.layout[timelineFieldKey], Number(StrCast(pair.layout[timelineFieldKey])));
- if (!Number.isNaN(num) && (!minTimeReq || num >= minTimeReq) && (!maxTimeReq || num <= maxTimeReq)) {
+ if (!isNaN(num) && (!minTimeReq || num >= minTimeReq) && (!maxTimeReq || num <= maxTimeReq)) {
!pivotDateGroups.get(num) && pivotDateGroups.set(num, []);
pivotDateGroups.get(num)!.push(pair.layout);
minTime = Math.min(num, minTime);
@@ -400,7 +400,7 @@ function normalizeResults(
const height = aggBounds.b - aggBounds.y === 0 ? 1 : aggBounds.b - aggBounds.y;
const wscale = panelDim[0] / width;
let scale = wscale * height > panelDim[1] ? panelDim[1] / height : wscale;
- if (Number.isNaN(scale)) scale = 1;
+ if (isNaN(scale)) scale = 1;
Array.from(docMap.entries())
.filter(ele => ele[1].pair)
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
index 69cbae86f..707f6c198 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
@@ -4,26 +4,28 @@ import * as React from 'react';
import { Doc } from '../../../../fields/Doc';
import { ScriptField } from '../../../../fields/ScriptField';
import { PresBox } from '../../nodes/trails/PresBox';
-import { CollectionFreeFormView } from './CollectionFreeFormView';
import './CollectionFreeFormView.scss';
+import { ObservableReactComponent } from '../../ObservableReactComponent';
+
export interface CollectionFreeFormPannableContentsProps {
Document: Doc;
viewDefDivClick?: ScriptField;
children?: React.ReactNode | undefined;
transition?: string;
isAnnotationOverlay: boolean | undefined;
+ showPresPaths: () => boolean;
transform: () => string;
brushedView: () => { panX: number; panY: number; width: number; height: number } | undefined;
}
@observer
-export class CollectionFreeFormPannableContents extends React.Component<CollectionFreeFormPannableContentsProps> {
+export class CollectionFreeFormPannableContents extends ObservableReactComponent<CollectionFreeFormPannableContentsProps> {
constructor(props: CollectionFreeFormPannableContentsProps) {
super(props);
makeObservable(this);
}
@computed get presPaths() {
- return CollectionFreeFormView.ShowPresPaths ? PresBox.Instance.pathLines(this.props.Document) : null;
+ return this._props.showPresPaths() ? PresBox.Instance.pathLines(this._props.Document) : null;
}
// rectangle highlight used when following trail/link to a region of a collection that isn't a document
showViewport = (viewport: { panX: number; panY: number; width: number; height: number } | undefined) =>
@@ -42,7 +44,7 @@ export class CollectionFreeFormPannableContents extends React.Component<Collecti
render() {
return (
<div
- className={'collectionfreeformview' + (this.props.viewDefDivClick ? '-viewDef' : '-none')}
+ className={'collectionfreeformview' + (this._props.viewDefDivClick ? '-viewDef' : '-none')}
onScroll={e => {
const target = e.target as any;
if (getComputedStyle(target)?.overflow === 'visible') {
@@ -50,13 +52,13 @@ export class CollectionFreeFormPannableContents extends React.Component<Collecti
}
}}
style={{
- transform: this.props.transform(),
- transition: this.props.transition,
- width: this.props.isAnnotationOverlay ? undefined : 0, // if not an overlay, then this will be the size of the collection, but panning and zooming will move it outside the visible border of the collection and make it selectable. This problem shows up after zooming/panning on a background collection -- you can drag the collection by clicking on apparently empty space outside the collection
+ transform: this._props.transform(),
+ transition: this._props.transition,
+ width: this._props.isAnnotationOverlay ? undefined : 0, // if not an overlay, then this will be the size of the collection, but panning and zooming will move it outside the visible border of the collection and make it selectable. This problem shows up after zooming/panning on a background collection -- you can drag the collection by clicking on apparently empty space outside the collection
}}>
{this.props.children}
{this.presPaths}
- {this.showViewport(this.props.brushedView())}
+ {this.showViewport(this._props.brushedView())}
</div>
);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
index fa8218bdd..35394016d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.tsx
@@ -9,17 +9,17 @@ import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { listSpec } from '../../../../fields/Schema';
import { Cast } from '../../../../fields/Types';
-import { CollectionViewProps } from '../CollectionView';
+import { CollectionViewProps } from '../CollectionSubView';
import './CollectionFreeFormView.scss';
@observer
export class CollectionFreeFormRemoteCursors extends React.Component<CollectionViewProps> {
@computed protected get cursors(): CursorField[] {
- const doc = this.props.Document;
+ const { Document } = this.props;
let cursors: FieldResult<List<CursorField>>;
const id = Doc.UserDoc()[Id];
- if (!id || !(cursors = Cast(doc.cursors, listSpec(CursorField)))) {
+ if (!id || !(cursors = Cast(Document.cursors, listSpec(CursorField)))) {
return [];
}
const now = mobxUtils.now();
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3fab00968..a70713429 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,14 +1,17 @@
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { Bezier } from 'bezier-js';
import { Colors } from 'browndash-components';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import * as React from 'react';
+import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils';
import { DateField } from '../../../../fields/DateField';
-import { Doc, DocListCast, Field, Opt } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, Opt } from '../../../../fields/Doc';
import { DocData, Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
-import { InkData, InkField, InkTool, PointData, Segment } from '../../../../fields/InkField';
+import { InkData, InkField, InkTool, Segment } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
import { RichTextField } from '../../../../fields/RichTextField';
import { listSpec } from '../../../../fields/Schema';
@@ -16,13 +19,15 @@ import { ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
import { TraceMobx } from '../../../../fields/util';
+import { Gestures, PointData } from '../../../../pen-gestures/GestureTypes';
import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { aggregateBounds, emptyFunction, intersectRect, Utils } from '../../../../Utils';
import { CognitiveServices } from '../../../cognitive_services/CognitiveServices';
import { Docs, DocUtils } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DocumentManager } from '../../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../../util/DragManager';
+import { DragManager } from '../../../util/DragManager';
+import { dropActionType } from '../../../util/DropActionTypes';
import { ReplayMovements } from '../../../util/ReplayMovements';
import { CompileScript } from '../../../util/Scripting';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
@@ -33,8 +38,8 @@ import { Transform } from '../../../util/Transform';
import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
import { Timeline } from '../../animationtimeline/Timeline';
import { ContextMenu } from '../../ContextMenu';
+import { PinProps } from '../../DocComponent';
import { GestureOverlay } from '../../GestureOverlay';
-import { CtrlKey } from '../../GlobalKeyHandler';
import { ActiveInkWidth, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
import { LightboxView } from '../../LightboxView';
import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
@@ -42,7 +47,7 @@ import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp';
import { DocumentView, OpenWhere } from '../../nodes/DocumentView';
import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
-import { PinProps, PresBox } from '../../nodes/trails/PresBox';
+import { PresBox } from '../../nodes/trails/PresBox';
import { CreateImage } from '../../nodes/WebBoxRenderer';
import { StyleProp } from '../../StyleProvider';
import { CollectionSubView } from '../CollectionSubView';
@@ -77,7 +82,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable _paintedId = 'id' + Utils.GenerateGuid().replace(/-/g, '');
@computed get paintFunc() {
const field = this.dataDoc[this.fieldKey];
- const paintFunc = StrCast(Field.toJavascriptString(Cast(field, RichTextField, null)?.Text as Field)).trim();
+ const paintFunc = StrCast(Field.toJavascriptString(Cast(field, RichTextField, null)?.Text as FieldType)).trim();
return !paintFunc
? ''
: paintFunc.includes('dashDiv')
@@ -635,11 +640,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onGesture = (e: Event, ge: GestureUtils.GestureEvent) => {
switch (ge.gesture) {
default:
- case GestureUtils.Gestures.Line:
- case GestureUtils.Gestures.Circle:
- case GestureUtils.Gestures.Rectangle:
- case GestureUtils.Gestures.Triangle:
- case GestureUtils.Gestures.Stroke:
+ case Gestures.Line:
+ case Gestures.Circle:
+ case Gestures.Rectangle:
+ case Gestures.Triangle:
+ case Gestures.Stroke:
const points = ge.points;
const B = this.screenToFreeformContentsXf.transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale;
@@ -660,7 +665,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.addDocument(inkDoc);
e.stopPropagation();
break;
- case GestureUtils.Gestures.Rectangle:
+ case Gestures.Rectangle:
const strokes = this.getActiveDocuments()
.filter(doc => doc.type === DocumentType.INK)
.map(i => {
@@ -672,7 +677,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
CognitiveServices.Inking.Appliers.InterpretStrokes(strokes).then(results => {});
break;
- case GestureUtils.Gestures.Text:
+ case Gestures.Text:
if (ge.text) {
const B = this.screenToFreeformContentsXf.transformPoint(ge.points[0].X, ge.points[0].Y);
this.addDocument(Docs.Create.TextDocument(ge.text, { title: ge.text, x: B[0], y: B[1] }));
@@ -690,7 +695,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
onClick = (e: React.MouseEvent) => {
if (this._lightboxDoc) this._lightboxDoc = undefined;
- if (Utils.isClick(e.pageX, e.pageY, this._downX, this._downY, this._downTime)) {
+ if (ClientUtils.isClick(e.pageX, e.pageY, this._downX, this._downY, this._downTime)) {
if (this.onBrowseClickHandler()) {
this.onBrowseClickHandler().script.run({ documentView: this.DocumentView?.(), clientX: e.clientX, clientY: e.clientY });
e.stopPropagation();
@@ -746,7 +751,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
segments.forEach(segment =>
this.forceStrokeGesture(
e,
- GestureUtils.Gestures.Stroke,
+ Gestures.Stroke,
segment.reduce((data, curve) => [...data, ...curve.points.map(p => intersect.inkView.ComponentView?.ptToScreen?.({ X: p.x, Y: p.y }) ?? { X: 0, Y: 0 })], [] as PointData[])
)
);
@@ -759,7 +764,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
});
return false;
};
- forceStrokeGesture = (e: PointerEvent, gesture: GestureUtils.Gestures, points: InkData, text?: any) => {
+ forceStrokeGesture = (e: PointerEvent, gesture: Gestures, points: InkData, text?: any) => {
this.onGesture(e, new GestureUtils.GestureEvent(gesture, points, GestureOverlay.getBounds(points), text));
};
@@ -956,7 +961,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
switch (
!e.ctrlKey && !e.shiftKey && !e.metaKey && !e.altKey ?//
Doc.UserDoc().freeformScrollMode : // no modifiers, do assigned mode
- e.ctrlKey && !CtrlKey? // otherwise, if ctrl key (pinch gesture) try to zoom else pan
+ e.ctrlKey && !SnappingManager.CtrlKey? // otherwise, if ctrl key (pinch gesture) try to zoom else pan
freeformScrollMode.Zoom : freeformScrollMode.Pan // prettier-ignore
) {
case freeformScrollMode.Pan:
@@ -1030,9 +1035,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
(!this._props.getScrollHeight?.() ? fitYscroll : 0); // when not zoomed, scrolling is handled via a scrollbar, not panning
let newPanY = Math.max(minPanY, Math.min(maxPanY, panY));
if (false && NumCast(this.layoutDoc.layout_scrollTop) && NumCast(this.layoutDoc._freeform_scale, minScale) !== minScale) {
- const relTop = NumCast(this.layoutDoc.layout_scrollTop) / maxScrollTop;
- this.layoutDoc.layout_scrollTop = undefined;
- newPanY = minPanY + relTop * (maxPanY - minPanY);
} else if (fitYscroll > 2 && this.layoutDoc.layout_scrollTop === undefined && NumCast(this.layoutDoc._freeform_scale, minScale) === minScale) {
const maxPanY = minPanY + fitYscroll;
const relTop = (panY - minPanY) / (maxPanY - minPanY);
@@ -1289,8 +1291,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
: NumCast(this.layoutDoc._rotation_jitter) * random(-1, 1, NumCast(x), NumCast(y)) );
const childProps = { ...this._props, fieldKey: '', styleProvider: this.clusterStyleProvider };
return {
- x: Number.isNaN(NumCast(x)) ? 0 : NumCast(x),
- y: Number.isNaN(NumCast(y)) ? 0 : NumCast(y),
+ x: isNaN(NumCast(x)) ? 0 : NumCast(x),
+ y: isNaN(NumCast(y)) ? 0 : NumCast(y),
z: Cast(z, 'number'),
autoDim,
rotation,
@@ -1424,8 +1426,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return anchor;
};
- @action closeInfo = () => (Doc.IsInfoUIDisabled = true);
- infoUI = () => (Doc.IsInfoUIDisabled || this.Document.annotationOn || this._props.renderDepth ? null : <CollectionFreeFormInfoUI Document={this.Document} Freeform={this} close={this.closeInfo} />);
+ childDocsFunc = () => this.childDocs;
+ @action closeInfo = () => { Doc.IsInfoUIDisabled = true }; // prettier-ignore
+ infoUI = () => (Doc.IsInfoUIDisabled || this.Document.annotationOn || this._props.renderDepth ? null : <CollectionFreeFormInfoUI Document={this.Document} LayoutDoc={this.layoutDoc} childDocs={this.childDocsFunc} close={this.closeInfo} />);
componentDidMount() {
this._props.setContentViewBox?.(this);
@@ -1483,6 +1486,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (!code.includes('dashDiv')) {
const script = CompileScript(code, { params: { docView: 'any' }, typecheck: false, editable: true });
if (script.compiled) script.run({ this: this.DocumentView?.() });
+ // eslint-disable-next-line no-eval
} else code && !first && eval?.(code);
},
{ fireImmediately: true }
@@ -1491,7 +1495,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._disposers.layoutElements = reaction(
// layoutElements can't be a computed value because doLayoutComputation() is an action that has side effect of updating clusters
() => this.doInternalLayoutComputation,
- computation => (this._layoutElements = this.doLayoutComputation(computation.newPool, computation.computedElementData)),
+ computation => {
+ this._layoutElements = this.doLayoutComputation(computation.newPool, computation.computedElementData);
+ },
{ fireImmediately: true }
);
}
@@ -1512,7 +1518,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const canvas = oldDiv;
const img = document.createElement('img'); // create a Image Element
try {
- img.src = canvas.toDataURL(); //image source
+ img.src = canvas.toDataURL(); // image source
} catch (e) {
console.log(e);
}
@@ -1567,14 +1573,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const htmlString = new XMLSerializer().serializeToString(newDiv);
const nativeWidth = width;
const nativeHeight = height;
- return CreateImage(Utils.prepend(''), document.styleSheets, htmlString, nativeWidth, (nativeWidth * panelHeight) / panelWidth, (scrollTop * panelHeight) / realNativeHeight)
- .then(async (data_url: any) => {
- const returnedFilename = await Utils.convertDataUri(data_url, filename, noSuffix, replaceRootFilename);
+ return CreateImage(ClientUtils.prepend(''), document.styleSheets, htmlString, nativeWidth, (nativeWidth * panelHeight) / panelWidth, (scrollTop * panelHeight) / realNativeHeight)
+ .then(async (dataUrl: any) => {
+ const returnedFilename = await ClientUtils.convertDataUri(dataUrl, filename, noSuffix, replaceRootFilename);
cb(returnedFilename as string, nativeWidth, nativeHeight);
})
- .catch(function (error: any) {
- console.error('oops, something went wrong!', error);
- });
+ .catch((error: any) => console.error('oops, something went wrong!', error));
}
componentWillUnmount() {
@@ -1583,14 +1587,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
@action
- onCursorMove = (e: React.PointerEvent) => {
+ onCursorMove = () => {
// super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY));
};
@undoBatch
promoteCollection = () => {
const childDocs = this.childDocs.slice();
- childDocs.forEach(doc => {
+ childDocs.forEach(docIn => {
+ const doc = docIn;
const scr = this.screenToFreeformContentsXf.inverse().transformPoint(NumCast(doc.x), NumCast(doc.y));
doc.x = scr?.[0];
doc.y = scr?.[1];
@@ -1604,7 +1609,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const width = Math.max(...docs.map(doc => NumCast(doc._width))) + 20;
const height = Math.max(...docs.map(doc => NumCast(doc._height))) + 20;
const dim = Math.ceil(Math.sqrt(docs.length));
- docs.forEach((doc, i) => {
+ docs.forEach((docIn, i) => {
+ const doc = docIn;
doc.x = NumCast(this.Document[this.panXFieldKey]) + (i % dim) * width - (width * dim) / 2;
doc.y = NumCast(this.Document[this.panYFieldKey]) + Math.floor(i / dim) * height - (height * dim) / 2;
});
@@ -1704,14 +1710,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
activeDocs
- .filter(doc => doc.isGroup && SnappingManager.IsResizing !== doc && !DragManager.docsBeingDragged.includes(doc))
+ .filter(doc => doc.isGroup && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))
.forEach(doc => DocumentManager.Instance.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
const horizLines: number[] = [];
const vertLines: number[] = [];
const invXf = this.screenToFreeformContentsXf.inverse();
snappableDocs
- .filter(doc => !doc.isGroup && (snapToDraggedDoc || (SnappingManager.IsResizing !== doc && !DragManager.docsBeingDragged.includes(doc))))
+ .filter(doc => !doc.isGroup && (snapToDraggedDoc || (SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))))
.forEach(doc => {
const { left, top, width, height } = docDims(doc);
const topLeftInScreen = invXf.transformPoint(left, top);
@@ -1727,10 +1733,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
incrementalRender = action(() => {
if (!LightboxView.LightboxDoc || LightboxView.Contains(this.DocumentView?.())) {
- const layout_unrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
+ const layoutUnrendered = this.childDocs.filter(doc => !this._renderCutoffData.get(doc[Id]));
const loadIncrement = this.Document.isTemplateDoc ? Number.MAX_VALUE : 5;
- for (var i = 0; i < Math.min(layout_unrendered.length, loadIncrement); i++) {
- this._renderCutoffData.set(layout_unrendered[i][Id] + '', true);
+ for (let i = 0; i < Math.min(layoutUnrendered.length, loadIncrement); i++) {
+ this._renderCutoffData.set(layoutUnrendered[i][Id] + '', true);
}
}
this.childDocs.some(doc => !this._renderCutoffData.get(doc[Id])) && setTimeout(this.incrementalRender, 1);
@@ -1744,6 +1750,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
);
}
+ showPresPaths = () => CollectionFreeFormView.ShowPresPaths;
brushedView = () => this._brushedView;
gridColor = () =>
DashColor(lightOrDark(this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor)))
@@ -1776,6 +1783,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
brushedView={this.brushedView}
isAnnotationOverlay={this.isAnnotationOverlay}
transform={this.PanZoomCenterXf}
+ showPresPaths={this.showPresPaths}
transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.Document._viewTransition, 'string', null))}
viewDefDivClick={this._props.viewDefDivClick}>
{this.props.children ?? null} {/* most likely case of children is document content that's being annoated: eg., an image */}
@@ -1828,7 +1836,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._brushtimer1 = setTimeout(
action(() => {
this._brushedView = { ...viewport, panX: viewport.panX - viewport.width / 2, panY: viewport.panY - viewport.height / 2 };
- this._brushtimer = setTimeout(action(() => (this._brushedView = undefined)), holdTime); // prettier-ignore
+ this._brushtimer = setTimeout(action(() => { this._brushedView = undefined; }), holdTime); // prettier-ignore
}),
transTime + 1
);
@@ -1912,6 +1920,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observer
class CollectionFreeFormOverlayView extends React.Component<{ elements: () => ViewDefResult[] }> {
render() {
+ // eslint-disable-next-line react/destructuring-assignment
return this.props.elements().filter(ele => ele.bounds?.z).map(ele => ele.ele); // prettier-ignore
}
}
@@ -1923,11 +1932,12 @@ export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY
DocumentManager.Instance.showDocument(dv.Document, { zoomScale: 0.8, willZoomCentered: true }, (focused: boolean) => {
if (!focused) {
const selfFfview = !dv.Document.isGroup && dv.ComponentView instanceof CollectionFreeFormView ? dv.ComponentView : undefined;
- let containers = dv.containerViewPath?.() ?? [];
+ const containers = dv.containerViewPath?.() ?? [];
let parFfview = dv.CollectionFreeFormView;
- for (var cont of containers) {
+ containers.forEach(cont => {
parFfview = parFfview ?? cont.CollectionFreeFormView;
- }
+ });
+
while (parFfview?.Document.isGroup) parFfview = parFfview.DocumentView?.().CollectionFreeFormView;
const ffview = selfFfview && selfFfview.layoutDoc[selfFfview.scaleFieldKey] !== 0.5 ? selfFfview : parFfview; // if focus doc is a freeform that is not at it's default 0.5 scale, then zoom out on it. Otherwise, zoom out on the parent ffview
ffview?.zoomSmoothlyAboutPt(ffview.screenToFreeformContentsXf.transformPoint(clientX, clientY), ffview?.isAnnotationOverlay ? 1 : 0.5, browseTransitionTime);
@@ -1936,17 +1946,21 @@ export function CollectionBrowseClick(dv: DocumentView, clientX: number, clientY
});
}
ScriptingGlobals.add(CollectionBrowseClick);
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function nextKeyFrame(readOnly: boolean) {
!readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame();
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function prevKeyFrame(readOnly: boolean) {
!readOnly && (SelectionManager.Views[0].ComponentView as CollectionFreeFormView)?.changeKeyFrame(true);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function curKeyFrame(readOnly: boolean) {
const selView = SelectionManager.Views;
if (readOnly) return selView[0].ComponentView?.getKeyFrameEditing?.() ? Colors.MEDIUM_BLUE : 'transparent';
runInAction(() => selView[0].ComponentView?.setKeyFrameEditing?.(!selView[0].ComponentView?.getKeyFrameEditing?.()));
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
SelectionManager.Views.forEach(view =>
view._props.pinToPres(view.Document, {
@@ -1959,15 +1973,19 @@ ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
})
);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function bringToFront() {
SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document));
});
-ScriptingGlobals.add(function sendToBack(doc: Doc) {
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(function sendToBack() {
SelectionManager.Views.forEach(view => view.CollectionFreeFormView?.bringToFront(view.Document, true));
});
-ScriptingGlobals.add(function datavizFromSchema(doc: Doc) {
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(function datavizFromSchema() {
// creating a dataviz doc to represent the schema table
- SelectionManager.Views.forEach(view => {
+ SelectionManager.Views.forEach(viewIn => {
+ const view = viewIn;
if (!view.layoutDoc.schema_columnKeys) {
view.layoutDoc.schema_columnKeys = new List<string>(['title', 'type', 'author', 'author_date']);
}
@@ -1975,13 +1993,13 @@ ScriptingGlobals.add(function datavizFromSchema(doc: Doc) {
if (!keys) return;
const children = DocListCast(view.Document[Doc.LayoutFieldKey(view.Document)]);
- let csvRows = [];
+ const csvRows = [];
csvRows.push(keys.join(','));
for (let i = 0; i < children.length; i++) {
- let eachRow = [];
+ const eachRow = [];
for (let j = 0; j < keys.length; j++) {
- var cell = children[i][keys[j]]?.toString();
- if (cell) cell = cell.toString().replace(/\,/g, '');
+ let cell = children[i][keys[j]]?.toString();
+ if (cell) cell = cell.toString().replace(/,/g, '');
eachRow.push(cell);
}
csvRows.push(eachRow);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 6eca91e9d..b03e435ce 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,7 +1,9 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, intersectRect, lightOrDark, returnFalse } from '../../../../Utils';
+import { ClientUtils, lightOrDark, returnFalse } from '../../../../ClientUtils';
+import { intersectRect } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
@@ -20,6 +22,7 @@ import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { UndoManager, undoBatch } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
+import { MarqueeViewBounds } from '../../DocComponent';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { PreviewCursor } from '../../PreviewCursor';
import { OpenWhere } from '../../nodes/DocumentView';
@@ -28,6 +31,7 @@ import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { SubCollectionViewProps } from '../CollectionSubView';
import { MarqueeOptionsMenu } from './MarqueeOptionsMenu';
import './MarqueeView.scss';
+
interface MarqueeViewProps {
getContainerTransform: () => Transform;
getTransform: () => Transform;
@@ -44,13 +48,6 @@ interface MarqueeViewProps {
slowLoadDocuments: (files: File[] | string, options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: ((doc: Doc[]) => void) | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => Promise<void>;
}
-export interface MarqueeViewBounds {
- left: number;
- top: number;
- width: number;
- height: number;
-}
-
@observer
export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps & MarqueeViewProps> {
public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) {
@@ -102,7 +99,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
@action
onKeyDown = (e: KeyboardEvent) => {
- //make textbox and add it to this collection
+ // make textbox and add it to this collection
// tslint:disable-next-line:prefer-const
const cm = ContextMenu.Instance;
const [x, y] = this.Transform.transformPoint(this._downX, this._downY);
@@ -141,7 +138,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
}
}
let ypos = y;
- ns.map(line => {
+ ns.forEach(line => {
const indent = line.search(/\S|$/);
const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + (indent / 3) * 10, y: ypos, title: line });
this._props.addDocument?.(newBox);
@@ -155,7 +152,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
pasteImageBitmap((data: any, error: any) => {
error && console.log(error);
data &&
- Utils.convertDataUri(data, this._props.Document[Id] + '-thumb-frozen').then(returnedfilename => {
+ ClientUtils.convertDataUri(data, this._props.Document[Id] + '-thumb-frozen').then(returnedfilename => {
this._props.Document['thumb-frozen'] = new ImageField(returnedfilename);
});
})
@@ -169,7 +166,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
TreeView._editTitleOnLoad = { id: slide[Id], parent: undefined };
this._props.addDocument?.(slide);
e.stopPropagation();
- }*/ else if (e.key === 'p' && e.ctrlKey) {
+ } */ else if (e.key === 'p' && e.ctrlKey) {
e.preventDefault();
(async () => {
const text: string = await navigator.clipboard.readText();
@@ -184,7 +181,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
e.stopPropagation();
}
};
- //heuristically converts pasted text into a table.
+ // heuristically converts pasted text into a table.
// assumes each entry is separated by a tab
// skips all rows until it gets to a row with more than one entry
// assumes that 1st row has header entry for each column
@@ -192,7 +189,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
// any row that has only one column is a section header-- this header is then added as a column to subsequent rows until the next header
// assumes each cell is a string or a number
pasteTable(ns: string[], x: number, y: number) {
- let csvRows = [];
+ const csvRows = [];
const headers = ns[0].split('\t');
csvRows.push(headers.join(','));
ns[0] = '';
@@ -200,7 +197,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
let eachRow = [];
for (let i = 1; i < eachCell.length; i++) {
eachRow.push(eachCell[i].replace(/\,/g, ''));
- if (i % headers.length == 0) {
+ if (i % headers.length === 0) {
csvRows.push(eachRow);
eachRow = [];
}
@@ -233,7 +230,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this._lastY = e.pageY;
this._lassoPts.push([e.clientX, e.clientY]);
if (!e.cancelBubble) {
- if (!Utils.isClick(this._lastX, this._lastY, this._downX, this._downY, Date.now())) {
+ if (!ClientUtils.isClick(this._lastX, this._lastY, this._downX, this._downY, Date.now())) {
if (!this._commandExecuted) {
this.showMarquee();
}
@@ -320,7 +317,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
@action
onClick = (e: React.MouseEvent): void => {
if (this._props.pointerEvents?.() === 'none') return;
- if (Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
+ if (ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
if (Doc.ActiveTool === InkTool.None) {
if (!this._props.trySelectCluster(e.shiftKey)) {
!SnappingManager.ExploreMode && this.setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Document);
@@ -335,15 +332,21 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
};
@action
- showMarquee = () => (this._visible = true);
+ showMarquee = () => {
+ this._visible = true;
+ };
@action
- hideMarquee = () => (this._visible = false);
+ hideMarquee = () => {
+ this._visible = false;
+ };
@undoBatch
delete = action((e?: React.PointerEvent<Element> | KeyboardEvent | undefined, hide?: boolean) => {
const selected = this.marqueeSelect(false);
SelectionManager.DeselectAll();
- selected.forEach(doc => (hide ? (doc.hidden = true) : this._props.removeDocument?.(doc)));
+ selected.forEach(doc => {
+ hide ? (doc.hidden = true) : this._props.removeDocument?.(doc);
+ });
this.cleanupInteractions(false);
MarqueeOptionsMenu.Instance.fadeOut(true);
@@ -540,6 +543,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
};
touchesLine(r1: { left: number; top: number; width: number; height: number }) {
+ // eslint-disable-next-line no-restricted-syntax
for (const lassoPt of this._lassoPts) {
const topLeft = this.Transform.transformPoint(lassoPt[0], lassoPt[1]);
if (r1.left < topLeft[0] && topLeft[0] < r1.left + r1.width && r1.top < topLeft[1] && topLeft[1] < r1.top + r1.height) {
@@ -560,6 +564,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
let hasLeft = false;
let hasBottom = false;
let hasRight = false;
+ // eslint-disable-next-line no-restricted-syntax
for (const lassoPt of this._lassoPts) {
const truePoint = this.Transform.transformPoint(lassoPt[0], lassoPt[1]);
hasLeft = hasLeft || (truePoint[0] > tl[0] && truePoint[0] < r1.left && truePoint[1] > r1.top && truePoint[1] < r1.top + r1.height);
@@ -662,6 +667,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
};
render() {
return (
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
<div
className="marqueeView"
ref={r => {
@@ -673,7 +679,9 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
cursor: [InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool) || this._visible ? 'crosshair' : 'pointer',
}}
onDragOver={e => e.preventDefault()}
- onScroll={e => (e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0)}
+ onScroll={e => {
+ e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0;
+ }}
onClick={this.onClick}
onPointerDown={this.onPointerDown}>
{this._visible ? this.marqueeDiv : null}
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
index f25872c2b..ab6788e6f 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
@@ -4,7 +4,8 @@ import * as React from 'react';
import { Doc, Opt } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction } from '../../../../Utils';
+import { returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils';
import { Docs } from '../../../documents/Documents';
import { DragManager } from '../../../util/DragManager';
import { Transform } from '../../../util/Transform';
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 228af78aa..6635ab222 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -1,10 +1,13 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { Toggle, ToggleType, Type } from 'browndash-components';
import { IReactionDisposer, action, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, returnEmptyDoclist, returnTrue } from '../../../../Utils';
+import { ClientUtils, returnTrue } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
@@ -46,13 +49,15 @@ export class CollectionLinearView extends CollectionSubView() {
this._dropDisposer?.();
this._widthDisposer?.();
this._selectedDisposer?.();
- this.childLayoutPairs.map((pair, ind) => ScriptCast(DocCast(pair.layout.proto)?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log));
+ this.childLayoutPairs.map(pair => ScriptCast(DocCast(pair.layout.proto)?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log));
}
componentDidMount() {
this._widthDisposer = reaction(
() => 5 + NumCast(this.dataDoc.linearBtnWidth, this.dimension()) + (this.layoutDoc.linearView_IsOpen ? this.childDocs.filter(doc => !doc.hidden).reduce((tot, doc) => (NumCast(doc._width) || this.dimension()) + tot + 4, 0) : 0),
- width => this.childDocs.length && (this.layoutDoc._width = width),
+ width => {
+ this.childDocs.length && (this.layoutDoc._width = width);
+ },
{ fireImmediately: true }
);
}
@@ -64,14 +69,14 @@ export class CollectionLinearView extends CollectionSubView() {
dimension = () => NumCast(this.layoutDoc._height);
getTransform = (ele: Opt<HTMLDivElement>) => {
if (!ele) return Transform.Identity();
- const { scale, translateX, translateY } = Utils.GetScreenTransform(ele);
+ const { translateX, translateY } = ClientUtils.GetScreenTransform(ele);
return new Transform(-translateX, -translateY, 1);
};
@action
exitLongLinks = () => {
if (DocumentLinksButton.StartLink?.Document) {
- action((e: React.PointerEvent<HTMLDivElement>) => Doc.UnBrushDoc(DocumentLinksButton.StartLink?.Document as Doc));
+ action(() => Doc.UnBrushDoc(DocumentLinksButton.StartLink?.Document as Doc));
}
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
@@ -97,8 +102,8 @@ export class CollectionLinearView extends CollectionSubView() {
e.preventDefault();
};
- getLinkUI = () => {
- return !DocumentLinksButton.StartLink ? null : (
+ getLinkUI = () =>
+ !DocumentLinksButton.StartLink ? null : (
<span className="bottomPopup-background" style={{ pointerEvents: 'all' }} onPointerDown={e => e.stopPropagation()}>
<span className="bottomPopup-text">
Creating link from:{' '}
@@ -108,7 +113,7 @@ export class CollectionLinearView extends CollectionSubView() {
</b>
</span>
- <Tooltip title={<div className="dash-tooltip">{'Toggle description pop-up'} </div>} placement="top">
+ <Tooltip title={<div className="dash-tooltip">Toggle description pop-up </div>} placement="top">
<span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}>
Labels: {LinkDescriptionPopup.Instance.showDescriptions ? LinkDescriptionPopup.Instance.showDescriptions : 'ON'}
</span>
@@ -121,9 +126,8 @@ export class CollectionLinearView extends CollectionSubView() {
</Tooltip>
</span>
);
- };
- getCurrentlyPlayingUI = () => {
- return !CollectionStackedTimeline.CurrentlyPlaying?.length ? null : (
+ getCurrentlyPlayingUI = () =>
+ !CollectionStackedTimeline.CurrentlyPlaying?.length ? null : (
<span className="bottomPopup-background">
<span className="bottomPopup-text">
Currently playing:
@@ -139,7 +143,6 @@ export class CollectionLinearView extends CollectionSubView() {
</span>
</span>
);
- };
getDisplayDoc = (doc: Doc, preview: boolean = false) => {
// hack to avoid overhead of making UndoStack,etc into DocumentView style Boxes. If the UndoStack is ever intended to become part of the persisten state of the dashboard, then this would have to change.
@@ -149,6 +152,7 @@ export class CollectionLinearView extends CollectionSubView() {
case '<CurrentlyPlayingUI>': return this.getCurrentlyPlayingUI();
case '<UndoStack>': return <UndoStack key={doc[Id]}/>;
case '<Branching>': return Doc.UserDoc().isBranchingMode ? <BranchingTrailManager key={doc[Id]} /> : null;
+ default:
}
const nested = doc._type_collection === CollectionViewType.Linear;
@@ -161,7 +165,9 @@ export class CollectionLinearView extends CollectionSubView() {
<div
className={preview ? 'preview' : `collectionLinearView-docBtn`}
key={doc[Id]}
- ref={r => (dref = r || undefined)}
+ ref={r => {
+ dref = r || undefined;
+ }}
style={{
pointerEvents: 'all',
width: NumCast(doc._width),
@@ -194,7 +200,7 @@ export class CollectionLinearView extends CollectionSubView() {
childFilters={this._props.childFilters}
childFiltersByRanges={this._props.childFiltersByRanges}
searchFilterDocs={this._props.searchFilterDocs}
- hideResizeHandles={true}
+ hideResizeHandles
/>
</div>
);
@@ -220,30 +226,26 @@ export class CollectionLinearView extends CollectionSubView() {
ScriptCast(this.Document.onClick)?.script.run({ this: this.Document }, console.log);
}}
tooltip={isExpanded ? 'Close' : 'Open'}
- fillWidth={true}
- align={'center'}
+ fillWidth
+ align="center"
/>
);
return (
<div className={`collectionLinearView-outer ${this.layoutDoc.linearView_SubMenu}`} style={{ backgroundColor: this.layoutDoc.linearView_IsOpen ? undefined : 'transparent' }}>
<div className="collectionLinearView" ref={this.createDashEventsTarget} onContextMenu={this.myContextMenu} style={{ minHeight: this.dimension(), pointerEvents: 'all' }}>
- {
- <>
- {!this.layoutDoc.linearView_Expandable ? null : menuOpener}
- {!this.layoutDoc.linearView_IsOpen ? null : (
- <div
- className="collectionLinearView-content"
- style={{
- height: this.dimension(),
- flexDirection: flexDir as any,
- gap: flexGap,
- }}>
- {this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
- </div>
- )}
- </>
- }
+ {!this.layoutDoc.linearView_Expandable ? null : menuOpener}
+ {!this.layoutDoc.linearView_IsOpen ? null : (
+ <div
+ className="collectionLinearView-content"
+ style={{
+ height: this.dimension(),
+ flexDirection: flexDir as any,
+ gap: flexGap,
+ }}>
+ {this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
+ </div>
+ )}
</div>
</div>
);
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 6a956f2ac..46bf56dc8 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -3,16 +3,19 @@ import { Popup, PopupTrigger, Type } from 'browndash-components';
import { ObservableMap, action, computed, makeObservable, observable, observe } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
-import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
+import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
+import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
import { DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { listSpec } from '../../../../fields/Schema';
+import { ColumnType } from '../../../../fields/SchemaHeaderField';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { DocUtils, Docs, DocumentOptions, FInfo } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../../util/DragManager';
+import { DragManager } from '../../../util/DragManager';
+import { dropActionType } from '../../../util/DropActionTypes';
import { SelectionManager } from '../../../util/SelectionManager';
import { SettingsManager } from '../../../util/SettingsManager';
import { undoBatch, undoable } from '../../../util/UndoManager';
@@ -30,17 +33,6 @@ import { SchemaColumnHeader } from './SchemaColumnHeader';
import { SchemaRowBox } from './SchemaRowBox';
const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
-export enum ColumnType {
- Number,
- String,
- Boolean,
- Date,
- Image,
- RTF,
- Enumeration,
- Any,
-}
-
export const FInfotoColType: { [key: string]: ColumnType } = {
string: ColumnType.String,
number: ColumnType.Number,
@@ -823,8 +815,8 @@ export class CollectionSchemaView extends CollectionSubView() {
const docs = !field
? this.childDocs
: [...this.childDocs].sort((docA, docB) => {
- const aStr = Field.toString(docA[field] as Field);
- const bStr = Field.toString(docB[field] as Field);
+ const aStr = Field.toString(docA[field] as FieldType);
+ const bStr = Field.toString(docB[field] as FieldType);
var out = 0;
if (aStr < bStr) out = -1;
if (aStr > bStr) out = 1;
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 5f8b412be..2823e1936 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -2,7 +2,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, setupMoveUpEvents } from '../../../../Utils';
+import { setupMoveUpEvents } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
import { Colors } from '../../global/globalEnums';
import './CollectionSchemaView.scss';
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 39fea2d2e..27a4493cb 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -5,7 +5,8 @@ import { computedFn } from 'mobx-utils';
import * as React from 'react';
import { CgClose, CgLock, CgLockUnlock } from 'react-icons/cg';
import { FaExternalLinkAlt } from 'react-icons/fa';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction } from '../../../../Utils';
+import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { BoolCast } from '../../../../fields/Types';
import { DragManager } from '../../../util/DragManager';
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index bf36b2668..08eb35586 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -7,15 +7,17 @@ import * as React from 'react';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import Select from 'react-select';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../Utils';
+import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
import { DateField } from '../../../../fields/DateField';
import { Doc, DocListCast, Field } from '../../../../fields/Doc';
import { RichTextField } from '../../../../fields/RichTextField';
+import { ColumnType } from '../../../../fields/SchemaHeaderField';
import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types';
import { ImageField } from '../../../../fields/URLField';
import { FInfo, FInfoFieldType } from '../../../documents/Documents';
import { DocFocusOrOpen } from '../../../util/DocumentManager';
-import { dropActionType } from '../../../util/DragManager';
+import { dropActionType } from '../../../util/DropActionTypes';
import { SettingsManager } from '../../../util/SettingsManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
@@ -28,7 +30,7 @@ import { OpenWhere, returnEmptyDocViewList } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
import { KeyValueBox } from '../../nodes/KeyValueBox';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
-import { ColumnType, FInfotoColType } from './CollectionSchemaView';
+import { FInfotoColType } from './CollectionSchemaView';
import './CollectionSchemaView.scss';
export interface SchemaTableCellProps {
@@ -204,7 +206,7 @@ export class SchemaImageCell extends ObservableReactComponent<SchemaTableCellPro
choosePath(url: URL) {
if (url.protocol === 'data') return url.href; // if the url ises the data protocol, just return the href
- if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
+ if (url.href.indexOf(window.location.origin) === -1) return ClientUtils.CorsProxy(url.href); // otherwise, put it through the cors proxy erver
if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href; //Why is this here — good question
const ext = extname(url.href);
@@ -220,7 +222,7 @@ export class SchemaImageCell extends ObservableReactComponent<SchemaTableCellPro
.map(url => this.choosePath(url)); // access the primary layout data of the alternate documents
const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths;
// If there is a path, follow it; otherwise, follow a link to a default image icon
- const url = paths.length ? paths : [Utils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
+ const url = paths.length ? paths : [ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
return url[0];
}
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 2a5732708..50cf26cdb 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -2,10 +2,11 @@ import { Colors } from 'browndash-components';
import { action, runInAction } from 'mobx';
import { aggregateBounds } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
import { InkTool } from '../../../fields/InkField';
import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
-import { GestureUtils } from '../../../pen-gestures/GestureUtils';
+import { Gestures } from '../../../pen-gestures/GestureTypes';
import { DocumentType } from '../../documents/DocumentTypes';
import { LinkManager } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
@@ -14,26 +15,28 @@ import { UndoManager, undoable } from '../../util/UndoManager';
import { GestureOverlay } from '../GestureOverlay';
import { ActiveFillColor, ActiveInkColor, ActiveInkHideTextLabels, ActiveInkWidth, ActiveIsInkMask, InkingStroke, SetActiveFillColor, SetActiveInkColor, SetActiveInkHideTextLabels, SetActiveInkWidth, SetActiveIsInkMask } from '../InkingStroke';
import { CollectionFreeFormView } from '../collections/collectionFreeForm';
-// import { InkTranscription } from '../InkTranscription';
-import { DocData } from '../../../fields/DocSymbols';
import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';
import { DocumentView } from '../nodes/DocumentView';
+import { ImageBox } from '../nodes/ImageBox';
import { VideoBox } from '../nodes/VideoBox';
import { WebBox } from '../nodes/WebBox';
import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
-import { ImageBox } from '../nodes/ImageBox';
+// import { InkTranscription } from '../InkTranscription';
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function IsNoneSelected() {
return SelectionManager.Views.length <= 0;
}, 'are no document selected');
// toggle: Set overlay status of selected document
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setView(view: string) {
const selected = SelectionManager.Docs.lastElement();
selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed');
});
// toggle: Set overlay status of selected document
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
const selectedViews = SelectionManager.Views;
if (Doc.ActiveTool !== InkTool.None) {
@@ -70,15 +73,18 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
return selected.lastElement()?._backgroundColor ?? 'transparent';
}
SetActiveFillColor(color ?? 'transparent');
- selected.forEach(doc => (doc[DocData].backgroundColor = color));
+ selected.forEach(doc => { doc[DocData].backgroundColor = color; }); // prettier-ignore
}
+ return '';
});
// toggle: Set overlay status of selected document
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setDefaultTemplate(checkResult?: boolean) {
return DocumentView.setDefaultTemplate(checkResult);
});
// toggle: Set overlay status of selected document
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
if (checkResult) {
return SelectionManager.Views.length ? StrCast(SelectionManager.Docs.lastElement().layout_headingColor) : Doc.SharingDoc().headingColor;
@@ -93,9 +99,11 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole
Doc.GetProto(Doc.SharingDoc()).headingColor = color === 'transparent' ? undefined : color;
Doc.UserDoc().layout_showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().layout_showTitle, 'title');
}
+ return undefined;
});
// toggle: Set overlay status of selected document
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
const selected = SelectionManager.Views.length ? SelectionManager.Views[0] : undefined;
if (checkResult) {
@@ -103,19 +111,21 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
return false;
}
selected ? selected.CollectionFreeFormDocumentView?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
+ return undefined;
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) {
const selected = SelectionManager.Docs.lastElement();
// prettier-ignore
const map: Map<'center' |'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([
['grid', {
checkResult: (doc:Doc) => BoolCast(doc?._freeform_backgroundGrid, false),
- setDoc: (doc:Doc,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
+ setDoc: (doc:Doc) => { doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid; },
}],
['snaplines', {
checkResult: (doc:Doc) => BoolCast(doc?._freeform_snapLines, false),
- setDoc: (doc:Doc, dv:DocumentView) => doc._freeform_snapLines = !doc._freeform_snapLines,
+ setDoc: (doc:Doc) => { doc._freeform_snapLines = !doc._freeform_snapLines; },
}],
['viewAll', {
checkResult: (doc:Doc) => BoolCast(doc?._freeform_fitContentsToBox, false),
@@ -127,12 +137,12 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines'
}],
['center', {
checkResult: (doc:Doc) => BoolCast(doc?._stacking_alignCenter, false),
- setDoc: (doc:Doc,dv:DocumentView) => doc._stacking_alignCenter = !doc._stacking_alignCenter,
+ setDoc: (doc:Doc) => { doc._stacking_alignCenter = !doc._stacking_alignCenter; },
}],
['clusters', {
waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
checkResult: (doc:Doc) => BoolCast(doc?._freeform_useClusters, false),
- setDoc: (doc:Doc,dv:DocumentView) => doc._freeform_useClusters = !doc._freeform_useClusters,
+ setDoc: (doc:Doc) => { doc._freeform_useClusters = !doc._freeform_useClusters; },
}],
]);
@@ -142,11 +152,12 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines'
const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
SelectionManager.Views.map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv));
setTimeout(() => batch.end(), 100);
+ return undefined;
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- const selected = SelectionManager.Docs.lastElement();
// prettier-ignore
const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => any; setDoc: () => void;}> = new Map([
['font', {
@@ -163,14 +174,15 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh
}],
['alignment', {
checkResult: () => RichTextMenu.Instance?.textAlign,
- setDoc: () => value && editorView?.state ? RichTextMenu.Instance?.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value),
+ setDoc: () => { value && editorView?.state ? RichTextMenu.Instance?.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value); },
}],
['fontSize', {
checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
setDoc: () => {
- if (typeof value === 'number') value = value.toString();
- if (value && Number(value).toString() === value) value += 'px';
- RichTextMenu.Instance?.setFontSize(value);
+ let fsize = value;
+ if (typeof fsize === 'number') fsize = fsize.toString();
+ if (fsize && Number(fsize).toString() === fsize) fsize += 'px';
+ RichTextMenu.Instance?.setFontSize(fsize);
},
}],
]);
@@ -179,63 +191,55 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh
return map.get(attr)?.checkResult();
}
map.get(attr)?.setDoc?.();
+ return undefined;
});
type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'elide' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal';
type attrfuncs = [attrname, { checkResult: () => boolean; toggle?: () => any }];
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
const textView = RichTextMenu.Instance?.TextView;
const editorView = textView?.EditorView;
// prettier-ignore
const alignments:attrfuncs[] = (['left','right','center','vcent'] as ("left"|"center"|"right"|"vcent")[]).map((where) =>
- [ where, { checkResult: () =>(editorView ? (where === 'vcent' ? RichTextMenu.Instance?.textVcenter ?? false:
- (RichTextMenu.Instance?.textAlign === where)):
- where === 'vcent' ? BoolCast(Doc.UserDoc()._layout_centered):
- (Doc.UserDoc().textAlign ===where) ? true:false),
- toggle: () => (editorView?.state ? (where === 'vcent' ? RichTextMenu.Instance?.vcenterToggle(editorView, editorView.dispatch):
- RichTextMenu.Instance?.align(editorView, editorView.dispatch, where)):
+ [ where, { checkResult: () => editorView ? (where === 'vcent' ? RichTextMenu.Instance?.textVcenter ?? false:
+ (RichTextMenu.Instance?.textAlign === where)):
+ where === 'vcent' ? BoolCast(Doc.UserDoc()._layout_centered):
+ (Doc.UserDoc().textAlign === where),
+ toggle: () => { editorView?.state ? (where === 'vcent' ? RichTextMenu.Instance?.vcenterToggle(editorView, editorView.dispatch):
+ RichTextMenu.Instance?.align(editorView, editorView.dispatch, where)):
where === 'vcent' ? Doc.UserDoc()._layout_centered = !Doc.UserDoc()._layout_centered:
- (Doc.UserDoc().textAlign = where))}]); // prettier-ignore
+ (Doc.UserDoc().textAlign = where); }
+ }]); // prettier-ignore
// prettier-ignore
const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list =>
[ list, { checkResult: () => (editorView ? RichTextMenu.Instance?.listStyle === list:false),
toggle: () => editorView?.state && RichTextMenu.Instance?.changeListType(list) }]);
// prettier-ignore
const attrs:attrfuncs[] = [
- ['dictation', { checkResult: () => textView?._recordingDictation ? true:false,
- toggle: () => textView && runInAction(() => (textView._recordingDictation = !textView._recordingDictation)) }],
+ ['dictation', { checkResult: () => !!textView?._recordingDictation,
+ toggle: () => textView && runInAction(() => { textView._recordingDictation = !textView._recordingDictation;} ) }],
['elide', { checkResult: () => false,
toggle: () => editorView ? RichTextMenu.Instance?.elideSelection(): 0}],
['noAutoLink',{ checkResult: () => ((editorView && RichTextMenu.Instance?.noAutoLink) ?? false),
toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}],
- ['bold', { checkResult: () => (editorView ? RichTextMenu.Instance?.bold??false : (Doc.UserDoc().fontWeight === 'bold') ? true:false),
- toggle: editorView ? RichTextMenu.Instance?.toggleBold : () => (Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold')}],
- ['italics', { checkResult: () => (editorView ? RichTextMenu.Instance?.italics ?? false : (Doc.UserDoc().fontStyle === 'italics') ? true:false),
- toggle: editorView ? RichTextMenu.Instance?.toggleItalics : () => (Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics')}],
- ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance?.underline ?? false: (Doc.UserDoc().textDecoration === 'underline') ? true:false),
- toggle: editorView ? RichTextMenu.Instance?.toggleUnderline : () => (Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline') }]]
+ ['bold', { checkResult: () => (editorView ? RichTextMenu.Instance?.bold??false : (Doc.UserDoc().fontWeight === 'bold')),
+ toggle: editorView ? RichTextMenu.Instance?.toggleBold : () => { Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold'; }}],
+ ['italics', { checkResult: () => (editorView ? RichTextMenu.Instance?.italics ?? false : (Doc.UserDoc().fontStyle === 'italics')),
+ toggle: editorView ? RichTextMenu.Instance?.toggleItalics : () => { Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics'; }}],
+ ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance?.underline ?? false: (Doc.UserDoc().textDecoration === 'underline')),
+ toggle: editorView ? RichTextMenu.Instance?.toggleUnderline : () => { Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline'; } }]]
const map = new Map(attrs.concat(alignments).concat(listings));
if (checkResult) {
return map.get(charStyle)?.checkResult();
}
undoable(() => map.get(charStyle)?.toggle?.(), 'toggle ' + charStyle)();
+ return undefined;
});
-export function checkInksToGroup() {
- if (Doc.ActiveTool === InkTool.Write) {
- CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
- // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
- // find all inkDocs in ffView.unprocessedDocs that are within 200 pixels of each other
- const inksToGroup = ffView.unprocessedDocs.filter(inkDoc => {
- // console.log(inkDoc.x, inkDoc.y);
- });
- });
- }
-}
-
-export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
+export function createInkGroup(/* inksToGroup?: Doc[], isSubGroup?: boolean */) {
// TODO nda - if document being added to is a inkGrouping then we can just add to that group
if (Doc.ActiveTool === InkTool.Write) {
CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
@@ -301,26 +305,24 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
}
-function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean, checkResult?: boolean) {
+function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult?: boolean) {
// InkTranscription.Instance?.createInkGroup();
if (checkResult) {
return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
- ? GestureOverlay.Instance?.KeepPrimitiveMode || ![GestureUtils.Gestures.Circle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Rectangle].includes(tool as GestureUtils.Gestures)
- ? true
- : true
+ ? GestureOverlay.Instance?.KeepPrimitiveMode || ![Gestures.Circle, Gestures.Line, Gestures.Rectangle].includes(tool as Gestures)
: false;
}
runInAction(() => {
if (GestureOverlay.Instance) {
GestureOverlay.Instance.KeepPrimitiveMode = keepPrim;
}
- if (Object.values(GestureUtils.Gestures).includes(tool as any)) {
+ if (Object.values(Gestures).includes(tool as any)) {
if (GestureOverlay.Instance.InkShape === tool && !keepPrim) {
Doc.ActiveTool = InkTool.None;
GestureOverlay.Instance.InkShape = undefined;
} else {
Doc.ActiveTool = InkTool.Pen;
- GestureOverlay.Instance.InkShape = tool as GestureUtils.Gestures;
+ GestureOverlay.Instance.InkShape = tool as Gestures;
}
} else if (tool) {
// pen or eraser
@@ -334,38 +336,40 @@ function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean,
Doc.ActiveTool = InkTool.None;
}
});
+ return undefined;
}
ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
// toggle: Set overlay status of selected document
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
const selected = SelectionManager.Docs.lastElement() ?? Doc.UserDoc();
// prettier-ignore
const map: Map<'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
['inkMask', {
checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_isInkMask) : ActiveIsInkMask())),
- setInk: (doc: Doc) => (doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask),
+ setInk: (doc: Doc) => { doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask; },
setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
}],
['labels', {
checkResult: () => ((selected?._stroke_showLabel ? BoolCast(selected[DocData].stroke_showLabel) : ActiveInkHideTextLabels())),
- setInk: (doc: Doc) => (doc[DocData].stroke_showLabel = !doc.stroke_showLabel),
+ setInk: (doc: Doc) => { doc[DocData].stroke_showLabel = !doc.stroke_showLabel; },
setMode: () => selected?.type !== DocumentType.INK && SetActiveInkHideTextLabels(!ActiveInkHideTextLabels()),
}],
['fillColor', {
checkResult: () => (selected?._layout_isSvg ? StrCast(selected[DocData].fillColor) : ActiveFillColor() ?? "transparent"),
- setInk: (doc: Doc) => (doc[DocData].fillColor = StrCast(value)),
+ setInk: (doc: Doc) => { doc[DocData].fillColor = StrCast(value); },
setMode: () => SetActiveFillColor(StrCast(value)),
}],
[ 'strokeWidth', {
checkResult: () => (selected?._layout_isSvg ? NumCast(selected[DocData].stroke_width) : ActiveInkWidth()),
- setInk: (doc: Doc) => (doc[DocData].stroke_width = NumCast(value)),
+ setInk: (doc: Doc) => { doc[DocData].stroke_width = NumCast(value); },
setMode: () => { SetActiveInkWidth(value.toString()); selected?.type === DocumentType.INK && setActiveTool( GestureOverlay.Instance.InkShape ?? InkTool.Pen, true, false);},
}],
['strokeColor', {
checkResult: () => (selected?._layout_isSvg? StrCast(selected[DocData].color) : ActiveInkColor()),
- setInk: (doc: Doc) => (doc[DocData].color = String(value)),
+ setInk: (doc: Doc) => { doc[DocData].color = String(value); },
setMode: () => { SetActiveInkColor(StrCast(value)); selected?.type === DocumentType.INK && setActiveTool(GestureOverlay.Instance.InkShape ?? InkTool.Pen, true, false);},
}],
]);
@@ -375,11 +379,13 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fil
}
map.get(option)?.setMode();
SelectionManager.Docs.filter(doc => doc._layout_isSvg).map(doc => map.get(option)?.setInk(doc));
+ return undefined;
});
/** WEB
* webSetURL
- **/
+ * */
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
const selected = SelectionManager.Views.lastElement();
if (selected?.Document.type === DocumentType.WEB) {
@@ -387,30 +393,36 @@ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
return StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href);
}
selected.ComponentView?.setData?.(url);
- //selected.Document.data = new WebField(url);
}
+ return '';
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function webForward(checkResult?: boolean) {
const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox;
if (checkResult) {
return selected?.forward(checkResult) ? undefined : 'lightGray';
}
selected?.forward();
+ return undefined;
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function webBack() {
const selected = SelectionManager.Views.lastElement()?.ComponentView as WebBox;
selected?.back();
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function videoSnapshot() {
const selected = SelectionManager.Views.lastElement()?.ComponentView as VideoBox;
selected?.Snapshot();
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function imageSetPixelSize() {
const selected = SelectionManager.Views.lastElement()?.ComponentView as ImageBox;
selected?.setNativeSize();
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function imageRotate90() {
const selected = SelectionManager.Views.lastElement()?.ComponentView as ImageBox;
selected?.rotate();
@@ -418,21 +430,25 @@ ScriptingGlobals.add(function imageRotate90() {
/** Schema
* toggleSchemaPreview
- **/
+ * */
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
const selected = SelectionManager.Docs.lastElement();
if (checkResult && selected) {
const result: boolean = NumCast(selected.schema_previewWidth) > 0;
if (result) return Colors.MEDIUM_BLUE;
- else return 'transparent';
- } else if (selected) {
+ return 'transparent';
+ }
+ if (selected) {
if (NumCast(selected.schema_previewWidth) > 0) {
selected.schema_previewWidth = 0;
} else {
selected.schema_previewWidth = 200;
}
}
+ return '';
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
const selected = SelectionManager.Docs.lastElement();
if (checkResult && selected) {
@@ -441,17 +457,20 @@ ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) {
if (selected) {
selected._schema_singleLine = !selected._schema_singleLine;
}
+ return undefined;
});
/** STACK
* groupBy
*/
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
- SelectionManager.Docs.map(doc => (doc._text_fontFamily = key));
+ SelectionManager.Docs.forEach(doc => { doc._text_fontFamily = key; }); // prettier-ignore
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc())?.fontFamily);
}
if (editorView) RichTextMenu.Instance?.setFontFamily(key);
else Doc.UserDoc().fontFamily = key;
+ return undefined;
});
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index a2c9d10b6..38ef08ef9 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -4,13 +4,15 @@ import { Tooltip } from '@mui/material';
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
+import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
import { Cast, DocCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { LinkFollower } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { SelectionManager } from '../../util/SelectionManager';
diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx
index c9e3c203d..f2681bf2e 100644
--- a/src/client/views/linking/LinkPopup.tsx
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -2,7 +2,8 @@ import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import { EditorView } from 'prosemirror-view';
import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils';
import { Doc } from '../../../fields/Doc';
import { Transform } from '../../util/Transform';
import { undoBatch } from '../../util/UndoManager';
diff --git a/src/client/views/newlightbox/NewLightboxView.tsx b/src/client/views/newlightbox/NewLightboxView.tsx
index 12b9870ca..dcbc9fc50 100644
--- a/src/client/views/newlightbox/NewLightboxView.tsx
+++ b/src/client/views/newlightbox/NewLightboxView.tsx
@@ -2,7 +2,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { InkTool } from '../../../fields/InkField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index c685ec66f..c37466914 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -1,15 +1,18 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { DateField } from '../../../fields/DateField';
import { Doc } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { ComputedField } from '../../../fields/ScriptField';
import { Cast, DateCast, NumCast } from '../../../fields/Types';
import { AudioField, nullAudio } from '../../../fields/URLField';
-import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils';
+import { formatTime } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { Networking } from '../../Network';
import { DragManager } from '../../util/DragManager';
@@ -18,11 +21,11 @@ import { undoBatch } from '../../util/UndoManager';
import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxAnnotatableComponent } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent } from '../DocComponent';
import './AudioBox.scss';
-import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView';
-import { PinProps, PresBox } from './trails';
import { OpenWhere } from './DocumentView';
+import { FieldView, FieldViewProps } from './FieldView';
+import { PresBox } from './trails';
/**
* AudioBox
@@ -42,7 +45,7 @@ declare class MediaRecorder {
constructor(e: any); // whatever MediaRecorder has
}
-export enum media_state {
+export enum mediaState {
PendingRecording = 'pendingRecording',
Recording = 'recording',
Paused = 'paused',
@@ -97,16 +100,16 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return LinkManager.Links(this.dataDoc);
}
@computed get mediaState() {
- return this.dataDoc.mediaState as media_state;
+ return this.dataDoc.mediaState as mediaState;
+ }
+ set mediaState(value) {
+ this.dataDoc.mediaState = value;
}
@computed get path() {
// returns the path of the audio file
const path = Cast(this.Document[this.fieldKey], AudioField, null)?.url.href || '';
return path === nullAudio ? '' : path;
}
- set mediaState(value) {
- this.dataDoc.mediaState = value;
- }
@computed get timeline() {
return this._stackedTimeline;
@@ -117,17 +120,17 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._dropDisposer?.();
Object.values(this._disposers).forEach(disposer => disposer?.());
- this.mediaState === media_state.Recording && this.stopRecording();
+ this.mediaState === mediaState.Recording && this.stopRecording();
}
@action
componentDidMount() {
this._props.setContentViewBox?.(this);
if (this.path) {
- this.mediaState = media_state.Paused;
+ this.mediaState = mediaState.Paused;
this.setPlayheadTime(NumCast(this.layoutDoc.clipStart));
} else {
- this.mediaState = undefined as any as media_state;
+ this.mediaState = undefined as any as mediaState;
}
}
@@ -149,7 +152,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.Document,
this.dataDoc,
this.annotationKey,
- this._ele?.currentTime || Cast(this.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
+ this._ele?.currentTime || Cast(this.Document._layout_currentTimecode, 'number', null) || (this.mediaState === mediaState.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
undefined,
undefined,
addAsAnnotation
@@ -163,10 +166,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// updates timecode and shows it in timeline, follows links at time
@action
timecodeChanged = () => {
- if (this.mediaState !== media_state.Recording && this._ele) {
+ if (this.mediaState !== mediaState.Recording && this._ele) {
this.links
.map(l => this.getLinkData(l))
- .forEach(({ la1, la2, linkTime }) => {
+ .forEach(({ la1, linkTime }) => {
if (linkTime > NumCast(this.layoutDoc._layout_currentTimecode) && linkTime < this._ele!.currentTime) {
Doc.linkFollowHighlight(la1);
}
@@ -180,7 +183,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
playFrom = (seekTimeInSeconds: number, endTime?: number, fullPlay: boolean = false) => {
clearTimeout(this._play); // abort any previous clip ending
- if (Number.isNaN(this._ele?.duration)) {
+ if (isNaN(this._ele?.duration ?? Number.NaN)) {
// audio element isn't loaded yet... wait 1/2 second and try again
setTimeout(() => this.playFrom(seekTimeInSeconds, endTime), 500);
} else if (this.timeline && this._ele && AudioBox.Enabled) {
@@ -191,7 +194,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
if (seekTimeInSeconds >= 0 && this.timeline.trimStart <= end && seekTimeInSeconds <= this.timeline.trimEnd) {
this._ele.currentTime = start;
this._ele.play();
- this.mediaState = media_state.Playing;
+ this.mediaState = mediaState.Playing;
this.addCurrentlyPlaying();
this._play = setTimeout(
() => {
@@ -233,7 +236,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// update the recording time
updateRecordTime = () => {
- if (this.mediaState === media_state.Recording) {
+ if (this.mediaState === mediaState.Recording) {
setTimeout(this.updateRecordTime, 30);
if (!this._paused) {
this.layoutDoc._layout_currentTimecode = (new Date().getTime() - this._recordStart - this._pausedTime) / 1000;
@@ -254,7 +257,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
this._recordStart = new Date().getTime();
- runInAction(() => (this.mediaState = media_state.Recording));
+ runInAction(() => {
+ this.mediaState = mediaState.Recording;
+ });
setTimeout(this.updateRecordTime);
this._recorder.start();
setTimeout(this.stopRecording, 60 * 60 * 1000); // stop after an hour
@@ -269,7 +274,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const now = new Date().getTime();
this._paused && (this._pausedTime += now - this._pauseStart);
this.dataDoc[this.fieldKey + '_duration'] = (now - this._recordStart - this._pausedTime) / 1000;
- this.mediaState = media_state.Paused;
+ this.mediaState = mediaState.Paused;
this._stream?.getAudioTracks()[0].stop();
const ind = DocUtils.ActiveRecordings.indexOf(this);
ind !== -1 && DocUtils.ActiveRecordings.splice(ind, 1);
@@ -277,26 +282,26 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
// context menu
- specificContextMenu = (e: React.MouseEvent): void => {
+ specificContextMenu = (): void => {
const funcs: ContextMenuProps[] = [];
funcs.push({
description: (this.layoutDoc.hideAnchors ? "Don't hide" : 'Hide') + ' anchors',
- event: e => (this.layoutDoc.hideAnchors = !this.layoutDoc.hideAnchors),
+ event: () => { this.layoutDoc.hideAnchors = !this.layoutDoc.hideAnchors; }, // prettier-ignore
icon: 'expand-arrows-alt',
});
funcs.push({
description: (this.layoutDoc.dontAutoFollowLinks ? '' : "Don't") + ' follow links when encountered',
- event: e => (this.layoutDoc.dontAutoFollowLinks = !this.layoutDoc.dontAutoFollowLinks),
+ event: () => { this.layoutDoc.dontAutoFollowLinks = !this.layoutDoc.dontAutoFollowLinks}, // prettier-ignore
icon: 'expand-arrows-alt',
});
funcs.push({
description: (this.layoutDoc.dontAutoPlayFollowedLinks ? '' : "Don't") + ' play when link is selected',
- event: e => (this.layoutDoc.dontAutoPlayFollowedLinks = !this.layoutDoc.dontAutoPlayFollowedLinks),
+ event: () => { this.layoutDoc.dontAutoPlayFollowedLinks = !this.layoutDoc.dontAutoPlayFollowedLinks; }, // prettier-ignore
icon: 'expand-arrows-alt',
});
funcs.push({
description: (this.layoutDoc.autoPlayAnchors ? "Don't auto" : 'Auto') + ' play anchors onClick',
- event: e => (this.layoutDoc.autoPlayAnchors = !this.layoutDoc.autoPlayAnchors),
+ event: () => { this.layoutDoc.autoPlayAnchors = !this.layoutDoc.autoPlayAnchors; }, // prettier-ignore
icon: 'expand-arrows-alt',
});
ContextMenu.Instance?.addItem({
@@ -342,9 +347,9 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
- IsPlaying = () => this.mediaState === media_state.Playing;
+ IsPlaying = () => this.mediaState === mediaState.Playing;
TogglePause = () => {
- if (this.mediaState === media_state.Paused) this.Play();
+ if (this.mediaState === mediaState.Paused) this.Play();
else this.pause();
};
// pause playback without removing from the playback list to allow user to play it again.
@@ -352,7 +357,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
pause = () => {
if (this._ele) {
this._ele.pause();
- this.mediaState = media_state.Paused;
+ this.mediaState = mediaState.Paused;
// if paused in the middle of playback, prevents restart on next play
if (!this._finished) clearTimeout(this._play);
@@ -434,7 +439,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
// plays link
- playLink = (link: Doc, options: FocusViewOptions) => {
+ playLink = (link: Doc /* , options: FocusViewOptions */) => {
if (link.annotationOn === this.Document) {
if (!this.layoutDoc.dontAutoPlayFollowedLinks) {
this.playFrom(this.timeline?.anchorStart(link) || 0, this.timeline?.anchorEnd(link));
@@ -460,13 +465,17 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
@action
- timelineWhenChildContentsActiveChanged = (isActive: boolean) => this._props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive));
+ timelineWhenChildContentsActiveChanged = (isActive: boolean) => {
+ this._props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive));
+ };
timelineScreenToLocal = () => this.ScreenToLocalBoxXf().translate(0, -AudioBox.topControlsHeight);
- setPlayheadTime = (time: number) => (this._ele!.currentTime /*= this.layoutDoc._layout_currentTimecode*/ = time);
+ setPlayheadTime = (time: number) => {
+ this._ele!.currentTime /* = this.layoutDoc._layout_currentTimecode */ = time;
+ };
- playing = () => this.mediaState === media_state.Playing;
+ playing = () => this.mediaState === mediaState.Playing;
isActiveChild = () => this._isAnyChildContentActive;
@@ -497,7 +506,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
e,
returnFalse,
returnFalse,
- action(e => {
+ action(() => {
if (this.timeline?.IsTrimming !== TrimScope.None) {
this.timeline?.CancelTrimming();
} else {
@@ -566,7 +575,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._dropDisposer = DragManager.MakeDropTarget(
r,
(e, de) => {
- const [xp, yp] = this.ScreenToLocalBoxXf().transformPoint(de.x, de.y);
+ const [xp] = this.ScreenToLocalBoxXf().transformPoint(de.x, de.y);
de.complete.docDragData && this.timeline?.internalDocDrop(e, de, de.complete.docDragData, xp);
},
this.layoutDoc
@@ -581,7 +590,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<div className="audiobox-dictation" onPointerDown={this.onFile}>
<FontAwesomeIcon size="2x" icon="file-alt" />
</div>
- {[media_state.Recording, media_state.Playing].includes(this.mediaState) ? (
+ {[mediaState.Recording, mediaState.Playing].includes(this.mediaState) ? (
<div className="recording-controls" onClick={e => e.stopPropagation()}>
<div className="record-button" onPointerDown={this.Record}>
<FontAwesomeIcon size="2x" icon="stop" />
@@ -614,31 +623,29 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<div className="controls-left">
<div
className="audiobox-button"
- title={this.mediaState === media_state.Paused ? 'play' : 'pause'}
+ title={this.mediaState === mediaState.Paused ? 'play' : 'pause'}
onPointerDown={
- this.mediaState === media_state.Paused
+ this.mediaState === mediaState.Paused
? this.Play
: e => {
e.stopPropagation();
this.Pause();
}
}>
- <FontAwesomeIcon icon={this.mediaState === media_state.Paused ? 'play' : 'pause'} size={'1x'} />
+ <FontAwesomeIcon icon={this.mediaState === mediaState.Paused ? 'play' : 'pause'} size="1x" />
</div>
{!this.miniPlayer && (
<>
<Tooltip title={<>trim audio</>}>
<div className="audiobox-button" onPointerDown={this.onClipPointerDown}>
- <FontAwesomeIcon icon={this.timeline?.IsTrimming !== TrimScope.None ? 'check' : 'cut'} size={'1x'} />
+ <FontAwesomeIcon icon={this.timeline?.IsTrimming !== TrimScope.None ? 'check' : 'cut'} size="1x" />
</div>
</Tooltip>
- {this.timeline?.IsTrimming == TrimScope.None && !NumCast(this.layoutDoc.clipStart) && NumCast(this.layoutDoc.clipEnd) === this.rawDuration ? (
- <></>
- ) : (
- <Tooltip title={<>{this.timeline?.IsTrimming !== TrimScope.None ? 'Cancel trimming' : 'Edit original timeline'}</>}>
+ {this.timeline?.IsTrimming === TrimScope.None && !NumCast(this.layoutDoc.clipStart) && NumCast(this.layoutDoc.clipEnd) === this.rawDuration ? null : (
+ <Tooltip title={this.timeline?.IsTrimming !== TrimScope.None ? 'Cancel trimming' : 'Edit original timeline'}>
<div className="audiobox-button" onPointerDown={this.onResetPointerDown}>
- <FontAwesomeIcon icon={this.timeline?.IsTrimming !== TrimScope.None ? 'cancel' : 'arrows-left-right'} size={'1x'} />
+ <FontAwesomeIcon icon={this.timeline?.IsTrimming !== TrimScope.None ? 'cancel' : 'arrows-left-right'} size="1x" />
</div>
</Tooltip>
)}
@@ -705,9 +712,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@computed get renderTimeline() {
return (
<CollectionStackedTimeline
- ref={action((r: CollectionStackedTimeline | null) => (this._stackedTimeline = r))}
+ ref={action((r: CollectionStackedTimeline | null) => {
+ this._stackedTimeline = r;
+ })}
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
- CollectionFreeFormDocumentView={undefined}
dataFieldKey={this.fieldKey}
fieldKey={this.annotationKey}
dictationKey={this.fieldKey + '_dictation'}
@@ -738,10 +747,13 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// returns the html audio element
@computed get audio() {
return (
+ // eslint-disable-next-line jsx-a11y/media-has-caption
<audio
ref={this.setRef}
className={`audiobox-control${this._props.isContentActive() ? '-interactive' : ''}`}
- onLoadedData={action(e => this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '_duration'] = this._ele.duration))}>
+ onLoadedData={action(() => {
+ this._ele?.duration && this._ele?.duration !== Infinity && (this.dataDoc[this.fieldKey + '_duration'] = this._ele.duration);
+ })}>
<source src={this.path} type="audio/mpeg" />
Not supported.
</audio>
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 0d0a7c623..958d63267 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,8 +1,10 @@
-import { action, makeObservable, observable, trace } from 'mobx';
+import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { OmitKeys, numberRange } from '../../../Utils';
+import { OmitKeys } from '../../../ClientUtils';
+import { numberRange } from '../../../Utils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
+import { TransitionTimer } from '../../../fields/DocSymbols';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { ComputedField } from '../../../fields/ScriptField';
@@ -17,7 +19,6 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec
import './CollectionFreeFormDocumentView.scss';
import { DocumentView, DocumentViewProps, OpenWhere } from './DocumentView';
import { FieldViewProps } from './FieldView';
-import { TransitionTimer } from '../../../fields/DocSymbols';
/// Ugh, typescript has no run-time way of iterating through the keys of an interface. so we need
/// manaully keep this list of keys in synch wih the fields of the freeFormProps interface
@@ -239,6 +240,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
const isGroup = this.dataDoc.isGroup && (!backColor || backColor === 'transparent');
return isGroup ? (this._props.isDocumentActive?.() ? 'group' : this._props.isGroupActive?.() ? 'child' : 'inactive') : this._props.isGroupActive?.() ? 'child' : undefined;
};
+ localRotation = () => this._props.rotation;
render() {
TraceMobx();
@@ -259,6 +261,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
<DocumentView
{...OmitKeys(this._props,this.WrapperKeys.map(val => val.lower)).omit} // prettier-ignore
DataTransition={this.DataTransition}
+ LocalRotation={this.localRotation}
CollectionFreeFormDocumentView={this.returnThis}
styleProvider={this.styleProvider}
ScreenToLocalTransform={this.screenToLocalTransform}
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 9ffdc350d..99f9c03bf 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,22 +1,24 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, makeObservable, observable } from 'mobx';
+import { action, computed, makeObservable, observable, trace } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils';
+import { returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { RichTextField } from '../../../fields/RichTextField';
import { DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types';
import { DocUtils, Docs } from '../../documents/Documents';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { undoBatch } from '../../util/UndoManager';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { StyleProp } from '../StyleProvider';
import './ComparisonBox.scss';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { KeyValueBox } from './KeyValueBox';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
-import { PinProps, PresBox } from './trails';
+import { PresBox } from './trails';
@observer
export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -164,7 +166,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
* @returns a JSX layout string if a text field is found, othwerise undefined
*/
testForTextFields = (whichSlot: string) => {
- const slotHasText = Doc.Get(this.dataDoc, whichSlot, true) instanceof RichTextField || typeof Doc.Get(this.dataDoc, whichSlot, true) === 'string';
+ const slotData = Doc.Get(this.dataDoc, whichSlot, true);
+ const slotHasText = slotData instanceof RichTextField || typeof slotData === 'string';
const subjectText = RTFCast(this.Document[this.fieldKey])?.Text.trim();
const altText = RTFCast(this.Document[this.fieldKey + '_alternate'])?.Text.trim();
const layoutTemplateString =
@@ -180,8 +183,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// where (this) is replaced by the text in the fieldKey slot abd this.excludeWords is repalced by the conetnts of the excludeWords field
// The GPT call will put the "answer" in the second slot of the comparison (eg., text_2)
if (whichSlot.endsWith('2') && !layoutTemplateString?.includes(whichSlot)) {
- var queryText = altText?.replace('(this)', subjectText); // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ...
- if (queryText && queryText.match(/\(\(.*\)\)/)) {
+ const queryText = altText?.replace('(this)', subjectText); // TODO: this should be done in KeyValueBox.setField but it doesn't know about the fieldKey ...
+ if (queryText?.match(/\(\(.*\)\)/)) {
KeyValueBox.SetField(this.Document, whichSlot, ':=' + queryText, false); // make the second slot be a computed field on the data doc that calls ChatGpt
}
}
@@ -190,17 +193,16 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
_closeRef = React.createRef<HTMLDivElement>();
render() {
- const clearButton = (which: string) => {
- return (
- <div
- ref={this._closeRef}
- className={`clear-button ${which}`}
- onPointerDown={e => this.closeDown(e, which)} // prevent triggering slider movement in registerSliding
- >
- <FontAwesomeIcon className={`clear-button ${which}`} icon="times" size="sm" />
- </div>
- );
- };
+ trace();
+ const clearButton = (which: string) => (
+ <div
+ ref={this._closeRef}
+ className={`clear-button ${which}`}
+ onPointerDown={e => this.closeDown(e, which)} // prevent triggering slider movement in registerSliding
+ >
+ <FontAwesomeIcon className={`clear-button ${which}`} icon="times" size="sm" />
+ </div>
+ );
/**
* Display the Docs in the before/after fields of the comparison. This also supports a GPT flash card use case
@@ -229,7 +231,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
isDocumentActive={returnFalse}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
styleProvider={this._isAnyChildContentActive ? this._props.styleProvider : this.docStyleProvider}
- hideLinkButton={true}
+ hideLinkButton
pointerEvents={this._isAnyChildContentActive ? undefined : returnNone}
/>
{layoutTemplateString ? null : clearButton(whichSlot)}
@@ -240,13 +242,11 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
</div>
);
};
- const displayBox = (which: string, index: number, cover: number) => {
- return (
- <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this._props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}>
- {displayDoc(which)}
- </div>
- );
- };
+ const displayBox = (which: string, index: number, cover: number) => (
+ <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this._props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}>
+ {displayDoc(which)}
+ </div>
+ );
return (
<div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 22f1f7b79..2a0bc42ee 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -1,9 +1,11 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Checkbox } from '@mui/material';
import { Colors, Toggle, ToggleType, Type } from 'browndash-components';
import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils';
+import { returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
@@ -14,20 +16,18 @@ import { TraceMobx } from '../../../../fields/util';
import { DocUtils, Docs } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { UndoManager, undoable } from '../../../util/UndoManager';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
import { MarqueeAnnotator } from '../../MarqueeAnnotator';
import { SidebarAnnos } from '../../SidebarAnnos';
import { AnchorMenu } from '../../pdf/AnchorMenu';
import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup';
import { DocumentView } from '../DocumentView';
-import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView';
-import { PinProps } from '../trails';
+import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView';
import './DataVizBox.scss';
import { Histogram } from './components/Histogram';
import { LineChart } from './components/LineChart';
import { PieChart } from './components/PieChart';
import { TableBox } from './components/TableBox';
-import { Checkbox } from '@mui/material';
export enum DataVizView {
TABLE = 'table',
diff --git a/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx b/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
index 24023077f..0084d7394 100644
--- a/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
+++ b/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
@@ -3,7 +3,8 @@ import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { CgClose } from 'react-icons/cg';
-import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../Utils';
+import { ClientUtils, setupMoveUpEvents } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
import { Doc } from '../../../../fields/Doc';
import { StrCast } from '../../../../fields/Types';
import { DragManager } from '../../../util/DragManager';
@@ -84,7 +85,7 @@ export class SchemaCSVPopUp extends React.Component<SchemaCSVPopUpProps> {
const embedding = Doc.MakeEmbedding(this.dataVizDoc!);
return embedding;
};
- if (this.view && sourceAnchorCreator && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
+ if (this.view && sourceAnchorCreator && !ClientUtils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
DragManager.StartAnchorAnnoDrag(e.target instanceof HTMLElement ? [e.target] : [], new DragManager.AnchorAnnoDragData(this.view, sourceAnchorCreator, targetCreator), downX, downY, {
dragComplete: e => {
this.setVisible(false);
diff --git a/src/client/views/nodes/DataVizBox/components/Histogram.tsx b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
index 6672603f3..58cacef76 100644
--- a/src/client/views/nodes/DataVizBox/components/Histogram.tsx
+++ b/src/client/views/nodes/DataVizBox/components/Histogram.tsx
@@ -11,8 +11,9 @@ import { listSpec } from '../../../../../fields/Schema';
import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
import { undoable } from '../../../../util/UndoManager';
+import { PinProps } from '../../../DocComponent';
import { ObservableReactComponent } from '../../../ObservableReactComponent';
-import { PinProps, PresBox } from '../../trails';
+import { PresBox } from '../../trails';
import { scaleCreatorNumerical, yAxisCreator } from '../utils/D3Utils';
import './Chart.scss';
@@ -64,7 +65,7 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
if (this._props.axes.length < 1) return [];
if (this._props.axes.length < 2) {
var ax0 = this._props.axes[0];
- if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])){
+ if (!/[A-Za-z-:]/.test(this._props.records[0][ax0])) {
this.numericalXData = true;
}
return this._tableData.map(record => ({ [ax0]: record[this._props.axes[0]] }));
@@ -132,7 +133,7 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
// cleans data by converting numerical data to numbers and taking out empty cells
data = (dataSet: any) => {
- var validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || Number.isNaN(d[key])));
+ var validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key])));
const field = dataSet[0] ? Object.keys(dataSet[0])[0] : undefined;
return !field
? []
@@ -191,7 +192,7 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
const endingPoint = this.numericalXData ? this.rangeVals.xMax! : numBins;
// converts data into Objects
- var histDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || Number.isNaN(d[key])));
+ var histDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key])));
if (!this.numericalXData) {
var histStringDataSet: { [x: string]: unknown }[] = [];
if (this.numericalYData) {
@@ -452,17 +453,16 @@ export class Histogram extends ObservableReactComponent<HistogramProps> {
: ''
);
selected = selected.substring(0, selected.length - 2) + ' }';
- if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10)){
- selected+= "\n" + this._props.titleCol + ": "
+ if (this._props.titleCol != '' && (!this._currSelected['frequency'] || this._currSelected['frequency'] < 10)) {
+ selected += '\n' + this._props.titleCol + ': ';
this._tableData.forEach(each => {
- if (this._currSelected[this._props.axes[0]]==each[this._props.axes[0]]) {
- if (this._props.axes[1]){
- if (this._currSelected[this._props.axes[1]]==each[this._props.axes[1]]) selected+= each[this._props.titleCol] + ", ";
- }
- else selected+= each[this._props.titleCol] + ", ";
+ if (this._currSelected[this._props.axes[0]] == each[this._props.axes[0]]) {
+ if (this._props.axes[1]) {
+ if (this._currSelected[this._props.axes[1]] == each[this._props.axes[1]]) selected += each[this._props.titleCol] + ', ';
+ } else selected += each[this._props.titleCol] + ', ';
}
- })
- selected = selected.slice(0,-1).slice(0,-1);
+ });
+ selected = selected.slice(0, -1).slice(0, -1);
}
}
var selectedBarColor;
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index e093ec648..c667a15de 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -11,10 +11,11 @@ import { Docs } from '../../../../documents/Documents';
import { DocumentManager } from '../../../../util/DocumentManager';
import { undoable } from '../../../../util/UndoManager';
import { ObservableReactComponent } from '../../../ObservableReactComponent';
-import { PinProps, PresBox } from '../../trails';
+import { PresBox } from '../../trails';
import { DataVizBox } from '../DataVizBox';
import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils';
import './Chart.scss';
+import { PinProps } from '../../../DocComponent';
export interface DataPoint {
x: number;
@@ -258,17 +259,18 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
.attr('transform', `translate(${margin.left}, ${margin.top})`));
var validSecondData;
- if (this._props.axes.length>2){ // for when there are 2 lines on the chart
+ if (this._props.axes.length > 2) {
+ // for when there are 2 lines on the chart
var next = this._tableData.map(record => ({ x: Number(record[this._props.axes[0]]), y: Number(record[this._props.axes[2]]) })).sort((a, b) => (a.x < b.x ? -1 : 1));
validSecondData = next.filter(d => {
- if (!d.x || Number.isNaN(d.x) || !d.y || Number.isNaN(d.y)) return false;
+ if (!d.x || isNaN(d.x) || !d.y || isNaN(d.y)) return false;
return true;
});
var secondDataRange = minMaxRange([validSecondData]);
- if (secondDataRange.xMax!>xMax) xMax = secondDataRange.xMax;
- if (secondDataRange.yMax!>yMax) yMax = secondDataRange.yMax;
- if (secondDataRange.xMin!<xMin) xMin = secondDataRange.xMin;
- if (secondDataRange.yMin!<yMin) yMin = secondDataRange.yMin;
+ if (secondDataRange.xMax! > xMax) xMax = secondDataRange.xMax;
+ if (secondDataRange.yMax! > yMax) yMax = secondDataRange.yMax;
+ if (secondDataRange.xMin! < xMin) xMin = secondDataRange.xMin;
+ if (secondDataRange.yMin! < yMin) yMin = secondDataRange.yMin;
}
// creating the x and y scales
@@ -285,37 +287,45 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
if (validSecondData) {
drawLine(svg.append('path'), validSecondData, lineGen, true);
this.drawDataPoints(validSecondData, 0, xScale, yScale);
- svg.append('path').attr("stroke", "red");
+ svg.append('path').attr('stroke', 'red');
// legend
- var color = d3.scaleOrdinal()
- .range(["black", "blue"])
- .domain([this._props.axes[1], this._props.axes[2]])
- svg.selectAll("mydots")
+ var color = d3.scaleOrdinal().range(['black', 'blue']).domain([this._props.axes[1], this._props.axes[2]]);
+ svg.selectAll('mydots')
.data([this._props.axes[1], this._props.axes[2]])
.enter()
- .append("circle")
- .attr("cx", 5)
- .attr("cy", function(d,i){ return -30 + i*15})
- .attr("r", 7)
- .style("fill", function(d){ return color(d)})
- svg.selectAll("mylabels")
+ .append('circle')
+ .attr('cx', 5)
+ .attr('cy', function (d, i) {
+ return -30 + i * 15;
+ })
+ .attr('r', 7)
+ .style('fill', function (d) {
+ return color(d);
+ });
+ svg.selectAll('mylabels')
.data([this._props.axes[1], this._props.axes[2]])
.enter()
- .append("text")
- .attr("x", 25)
- .attr("y", function(d,i){ return -30 + i*15})
- .style("fill", function(d){ return color(d)})
- .text(function(d){ return d})
- .attr("text-anchor", "left")
- .style("alignment-baseline", "middle")
+ .append('text')
+ .attr('x', 25)
+ .attr('y', function (d, i) {
+ return -30 + i * 15;
+ })
+ .style('fill', function (d) {
+ return color(d);
+ })
+ .text(function (d) {
+ return d;
+ })
+ .attr('text-anchor', 'left')
+ .style('alignment-baseline', 'middle');
}
// get valid data points
const data = dataSet[0];
var validData = data.filter(d => {
Object.keys(data[0]).map(key => {
- if (!d[key] || Number.isNaN(d[key])) return false;
+ if (!d[key] || isNaN(d[key])) return false;
});
return true;
});
@@ -399,16 +409,16 @@ export class LineChart extends ObservableReactComponent<LineChartProps> {
else if (this._props.axes.length > 0) titleAccessor = titleAccessor + this._props.axes[0];
if (!this._props.layoutDoc[titleAccessor]) this._props.layoutDoc[titleAccessor] = this.defaultGraphTitle;
const selectedPt = this._currSelected ? `{ ${this._props.axes[0]}: ${this._currSelected.x} ${this._props.axes[1]}: ${this._currSelected.y} }` : 'none';
- var selectedTitle = "";
- if (this._currSelected && this._props.titleCol){
- selectedTitle+= "\n" + this._props.titleCol + ": "
+ var selectedTitle = '';
+ if (this._currSelected && this._props.titleCol) {
+ selectedTitle += '\n' + this._props.titleCol + ': ';
this._tableData.forEach(each => {
- var mapThisEntry = false;
- if (this._currSelected.x==each[this._props.axes[0]] && this._currSelected.y==each[this._props.axes[1]]) mapThisEntry = true;
- else if (this._currSelected.y==each[this._props.axes[0]] && this._currSelected.x==each[this._props.axes[1]]) mapThisEntry = true;
- if (mapThisEntry) selectedTitle += each[this._props.titleCol] + ", ";
- })
- selectedTitle = selectedTitle.slice(0,-1).slice(0,-1);
+ var mapThisEntry = false;
+ if (this._currSelected.x == each[this._props.axes[0]] && this._currSelected.y == each[this._props.axes[1]]) mapThisEntry = true;
+ else if (this._currSelected.y == each[this._props.axes[0]] && this._currSelected.x == each[this._props.axes[1]]) mapThisEntry = true;
+ if (mapThisEntry) selectedTitle += each[this._props.titleCol] + ', ';
+ });
+ selectedTitle = selectedTitle.slice(0, -1).slice(0, -1);
}
if (this._lineChartData.length > 0 || !this.parentViz || this.parentViz.length == 0) {
return this._props.axes.length >= 2 && /\d/.test(this._props.records[0][this._props.axes[0]]) && /\d/.test(this._props.records[0][this._props.axes[1]]) ? (
diff --git a/src/client/views/nodes/DataVizBox/components/PieChart.tsx b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
index fc23f47de..2735a40d5 100644
--- a/src/client/views/nodes/DataVizBox/components/PieChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/PieChart.tsx
@@ -12,8 +12,9 @@ import { Cast, DocCast, StrCast } from '../../../../../fields/Types';
import { Docs } from '../../../../documents/Documents';
import { undoable } from '../../../../util/UndoManager';
import { ObservableReactComponent } from '../../../ObservableReactComponent';
-import { PinProps, PresBox } from '../../trails';
+import { PresBox } from '../../trails';
import './Chart.scss';
+import { PinProps } from '../../../DocComponent';
export interface PieChartProps {
Document: Doc;
@@ -122,7 +123,7 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
// cleans data by converting numerical data to numbers and taking out empty cells
data = (dataSet: any) => {
- const validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || Number.isNaN(d[key])));
+ const validData = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key])));
const field = dataSet[0] ? Object.keys(dataSet[0])[0] : undefined;
return !field
? undefined
@@ -192,7 +193,7 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
// converts data into Objects
var data = this.data(dataSet);
- var pieDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || Number.isNaN(d[key])));
+ var pieDataSet = dataSet.filter((d: { [x: string]: unknown }) => !Object.keys(dataSet[0]).some(key => !d[key] || isNaN(d[key])));
if (this.byCategory) {
let uniqueCategories = [...new Set(data)];
var pieStringDataSet: { frequency: number }[] = [];
@@ -348,17 +349,16 @@ export class PieChart extends ObservableReactComponent<PieChartProps> {
});
selected = selected.substring(0, selected.length - 2);
selected += ' }';
- if (this._props.titleCol!="" && (!this._currSelected["frequency"] || this._currSelected["frequency"]<10)){
- selected+= "\n" + this._props.titleCol + ": "
+ if (this._props.titleCol != '' && (!this._currSelected['frequency'] || this._currSelected['frequency'] < 10)) {
+ selected += '\n' + this._props.titleCol + ': ';
this._tableData.forEach(each => {
- if (this._currSelected[this._props.axes[0]]==each[this._props.axes[0]]) {
- if (this._props.axes[1]){
- if (this._currSelected[this._props.axes[1]]==each[this._props.axes[1]]) selected+= each[this._props.titleCol] + ", ";
- }
- else selected+= each[this._props.titleCol] + ", ";
+ if (this._currSelected[this._props.axes[0]] == each[this._props.axes[0]]) {
+ if (this._props.axes[1]) {
+ if (this._currSelected[this._props.axes[1]] == each[this._props.axes[1]]) selected += each[this._props.titleCol] + ', ';
+ } else selected += each[this._props.titleCol] + ', ';
}
- })
- selected = selected.slice(0,-1).slice(0,-1);
+ });
+ selected = selected.slice(0, -1).slice(0, -1);
}
} else selected = 'none';
var selectedSliceColor;
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index 53d1869d9..15959c61d 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -2,7 +2,8 @@ import { Button, Type } from 'browndash-components';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../../Utils';
+import { ClientUtils, setupMoveUpEvents } from '../../../../../ClientUtils';
+import { emptyFunction } from '../../../../../Utils';
import { Doc, Field, NumListCast } from '../../../../../fields/Doc';
import { List } from '../../../../../fields/List';
import { listSpec } from '../../../../../fields/Schema';
@@ -137,7 +138,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
embedding.pieSliceColors = Field.Copy(this._props.layoutDoc.pieSliceColors);
return embedding;
};
- if (this._props.docView?.() && !Utils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
+ if (this._props.docView?.() && !ClientUtils.isClick(e.clientX, e.clientY, downX, downY, Date.now())) {
DragManager.StartAnchorAnnoDrag(e.target instanceof HTMLElement ? [e.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
dragComplete: e => {
if (!e.aborted && e.annoDragData && e.annoDragData.linkSourceDoc && e.annoDragData.dropDocument && e.linkDocument) {
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e729e2fa2..518158a7f 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -3,7 +3,8 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import JsxParser from 'react-jsx-parser';
import * as XRegExp from 'xregexp';
-import { OmitKeys, Without, emptyPath } from '../../../Utils';
+import { OmitKeys } from '../../../ClientUtils';
+import { Without, emptyPath } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { AclPrivate, DocData } from '../../../fields/DocSymbols';
import { ScriptField } from '../../../fields/ScriptField';
@@ -20,7 +21,6 @@ import { SchemaRowBox } from '../collections/collectionSchema/SchemaRowBox';
import { PresElementBox } from '../nodes/trails/PresElementBox';
import { SearchBox } from '../search/SearchBox';
import { DashWebRTCVideo } from '../webcam/DashWebRTCVideo';
-import { YoutubeBox } from './../../apis/youtube/YoutubeBox';
import { AudioBox } from './AudioBox';
import { ComparisonBox } from './ComparisonBox';
import { DataVizBox } from './DataVizBox/DataVizBox';
@@ -250,7 +250,6 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
AudioBox,
RecordingBox,
PresBox,
- YoutubeBox,
PresElementBox,
SearchBox,
FunctionPlotBox,
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index 4a22766cc..364406197 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -3,11 +3,12 @@ import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { factory } from 'typescript';
-import { Field } from '../../../fields/Doc';
+import { FieldType } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
+import { StrCast } from '../../../fields/Types';
import { DocumentManager } from '../../util/DocumentManager';
import { Transformer, ts } from '../../util/Scripting';
-import { SettingsManager } from '../../util/SettingsManager';
+import { SnappingManager } from '../../util/SnappingManager';
import { LightboxView } from '../LightboxView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DocumentView } from './DocumentView';
@@ -28,22 +29,22 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> {
return LightboxView.LightboxDoc ? DocumentManager.Instance.DocumentViews.filter(v => LightboxView.Contains(v)) : DocumentManager.Instance.DocumentViews;
}
render() {
- const view = this._props.view;
- const { left, top, right, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 };
+ const { view } = this._props;
+ const { left, top, right } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 };
return (
<div
className="documentIcon-outerDiv"
- onPointerEnter={action(e => (this._hovered = true))}
- onPointerLeave={action(e => (this._hovered = false))}
+ onPointerEnter={action(() => { this._hovered = true; })} // prettier-ignore
+ onPointerLeave={action(() => { this._hovered = false; })} // prettier-ignore
style={{
pointerEvents: 'all',
opacity: this._hovered ? 0.3 : 1,
position: 'absolute',
- background: SettingsManager.userBackgroundColor,
+ background: SnappingManager.userBackgroundColor,
transform: `translate(${(left + right) / 2}px, ${top}px)`,
}}>
- <Tooltip title={<>{this._props.view.Document.title}</>}>
+ <Tooltip title={<div>{StrCast(this._props.view.Document?.title)}</div>}>
<p>d{this._props.index}</p>
</Tooltip>
</div>
@@ -56,40 +57,40 @@ export class DocumentIconContainer extends React.Component {
public static getTransformer(): Transformer {
const usedDocuments = new Set<number>();
return {
- transformer: context => {
- return root => {
- function visit(node: ts.Node) {
- node = ts.visitEachChild(node, visit, context);
+ transformer: context => root => {
+ function visit(nodeIn: ts.Node) {
+ const node = ts.visitEachChild(nodeIn, visit, context);
- if (ts.isIdentifier(node)) {
- const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node;
- const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node;
- const isntParameter = !ts.isParameter(node.parent);
- if (isntPropAccess && isntPropAssign && isntParameter && !(node.text in globalThis)) {
- const match = node.text.match(/d([0-9]+)/);
- if (match) {
- const m = parseInt(match[1]);
- const doc = DocumentIcon.DocViews[m].Document;
- usedDocuments.add(m);
- return factory.createIdentifier(`idToDoc("${doc[Id]}")`);
- }
+ if (ts.isIdentifier(node)) {
+ const isntPropAccess = !ts.isPropertyAccessExpression(node.parent) || node.parent.expression === node;
+ const isntPropAssign = !ts.isPropertyAssignment(node.parent) || node.parent.name !== node;
+ const isntParameter = !ts.isParameter(node.parent);
+ if (isntPropAccess && isntPropAssign && isntParameter && !(node.text in globalThis)) {
+ const match = node.text.match(/d([0-9]+)/);
+ if (match) {
+ const m = parseInt(match[1]);
+ const doc = DocumentIcon.DocViews[m].Document;
+ usedDocuments.add(m);
+ return factory.createIdentifier(`idToDoc("${doc[Id]}")`);
}
}
-
- return node;
}
- return ts.visitNode(root, visit);
- };
+
+ return node;
+ }
+ return ts.visitNode(root, visit);
},
getVars() {
const docs = DocumentIcon.DocViews;
- const capturedVariables: { [name: string]: Field } = {};
- usedDocuments.forEach(index => (capturedVariables[`d${index}`] = docs.length > index ? docs[index].Document : `d${index}`));
+ const capturedVariables: { [name: string]: FieldType } = {};
+ usedDocuments.forEach(index => {
+ capturedVariables[`d${index}`] = docs.length > index ? docs[index].Document : `d${index}`;
+ });
return capturedVariables;
},
};
}
render() {
- return DocumentIcon.DocViews.map((dv, i) => <DocumentIcon key={i} index={i} view={dv} />);
+ return DocumentIcon.DocViews.map((dv, i) => <DocumentIcon key={dv.DocUniqueId} index={i} view={dv} />);
}
}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 2a68d2bf6..d378082f8 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -3,21 +3,22 @@ import { Tooltip } from '@mui/material';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { StopEvent, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
+import { StopEvent, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
import { StrCast } from '../../../fields/Types';
import { DocUtils } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { Hypothesis } from '../../util/HypothesisUtils';
import { LinkManager } from '../../util/LinkManager';
import { UndoManager, undoBatch } from '../../util/UndoManager';
+import { PinProps } from '../DocComponent';
import { ObservableReactComponent } from '../ObservableReactComponent';
import './DocumentLinksButton.scss';
import { DocumentView } from './DocumentView';
import { LinkDescriptionPopup } from './LinkDescriptionPopup';
import { TaskCompletionBox } from './TaskCompletedBox';
-import { PinProps } from './trails';
-import { DocData } from '../../../fields/DocSymbols';
interface DocumentLinksButtonProps {
View: DocumentView;
@@ -151,7 +152,7 @@ export class DocumentLinksButton extends ObservableReactComponent<DocumentLinksB
DocumentLinksButton.StartLinkView = undefined;
DocumentLinksButton.AnnotationId = undefined;
DocumentLinksButton.AnnotationUri = undefined;
- //!this._props.StartLink
+ // !this._props.StartLink
} else if (startLink !== endLink) {
endLink = endLinkView?.ComponentView?.getAnchor?.(true, pinProps) || endLink;
startLink = DocumentLinksButton.StartLinkView?.ComponentView?.getAnchor?.(true) || startLink;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index ee7bbbdba..dbd2ebe0d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,11 +1,15 @@
+/* eslint-disable no-use-before-define */
+/* eslint-disable react/jsx-props-no-spreading */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { Howl } from 'howler';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Bounce, Fade, Flip, JackInTheBox, Roll, Rotate, Zoom } from 'react-awesome-reveal';
-import { DivWidth, Utils, emptyFunction, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../Utils';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
+import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnEmptyString, returnFalse, returnTrue, returnVal, simulateMouseClick } from '../../../ClientUtils';
+import { Utils, emptyFunction, emptyPath } from '../../../Utils';
+import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
import { AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
@@ -23,14 +27,14 @@ import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'
import { DocUtils, Docs } from '../../documents/Documents';
import { DictationManager } from '../../util/DictationManager';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { MakeTemplate, makeUserTemplateButton } from '../../util/DropConverter';
import { FollowLinkScript } from '../../util/LinkFollower';
-import { LinkManager } from '../../util/LinkManager';
+import { LinkManager, UPDATE_SERVER_CACHE } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SearchUtil } from '../../util/SearchUtil';
import { SelectionManager } from '../../util/SelectionManager';
-import { SettingsManager } from '../../util/SettingsManager';
import { SharingManager } from '../../util/SharingManager';
import { SnappingManager } from '../../util/SnappingManager';
import { UndoManager, undoBatch, undoable } from '../../util/UndoManager';
@@ -42,6 +46,7 @@ import { FieldsDropdown } from '../FieldsDropdown';
import { GestureOverlay } from '../GestureOverlay';
import { LightboxView } from '../LightboxView';
import { AudioAnnoState, StyleProp } from '../StyleProvider';
+import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView';
import { DocumentContentsView, ObserverJsxParser } from './DocumentContentsView';
import { DocumentLinksButton } from './DocumentLinksButton';
import './DocumentView.scss';
@@ -50,12 +55,6 @@ import { KeyValueBox } from './KeyValueBox';
import { LinkAnchorBox } from './LinkAnchorBox';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { PresEffect, PresEffectDirection } from './trails';
-interface Window {
- MediaRecorder: MediaRecorder;
-}
-declare class MediaRecorder {
- constructor(e: any); // whatever MediaRecorder has
-}
export enum OpenWhereMod {
none = '',
@@ -83,9 +82,6 @@ export enum OpenWhere {
addRightKeyvalue = 'add:right:keyValue',
}
-export function returnEmptyDocViewList() {
- return [] as DocumentView[];
-}
export interface DocumentViewProps extends FieldViewSharedProps {
hideDecorations?: boolean; // whether to suppress all DocumentDecorations when doc is selected
hideResizeHandles?: boolean; // whether to suppress resized handles on doc decorations when this document is selected
@@ -183,12 +179,12 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
@computed get disableClickScriptFunc() {
const onScriptDisable = this._props.onClickScriptDisable ?? this._componentView?.onClickScriptDisable?.() ?? this.layoutDoc.onClickScriptDisable;
- // prettier-ignore
return (
+ // eslint-disable-next-line no-use-before-define
DocumentView.LongPress ||
onScriptDisable === 'always' ||
(onScriptDisable !== 'never' && (this.rootSelected() || this._componentView?.isAnyChildContentActive?.()))
- );
+ ); // prettier-ignore
}
@computed get _rootSelected() {
return this._props.isSelected() || BoolCast(this._props.TemplateDataDocument && this._props.rootSelected?.());
@@ -237,7 +233,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
componentDidMount() {
- runInAction(() => (this._mounted = true));
+ runInAction(() => {
+ this._mounted = true;
+ });
this.setupHandlers();
this._disposers.contentActive = reaction(
() =>
@@ -249,19 +247,23 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
: Doc.ActiveTool !== InkTool.None || SnappingManager.CanEmbed || this.rootSelected() || this.Document.forceActive || this._componentView?.isAnyChildContentActive?.() || this._props.isContentActive()
? true
: undefined,
- active => (this._isContentActive = active),
+ active => {
+ this._isContentActive = active;
+ },
{ fireImmediately: true }
);
this._disposers.pointerevents = reaction(
() => this.style(this.Document, StyleProp.PointerEvents),
- pointerevents => (this._pointerEvents = pointerevents),
+ pointerevents => {
+ this._pointerEvents = pointerevents;
+ },
{ fireImmediately: true }
);
}
preDrop = (e: Event, de: DragManager.DropEvent, dropAction: dropActionType) => {
const dragData = de.complete.docDragData;
if (dragData && this.isContentActive() && !this.props.dontRegisterView) {
- dragData.dropAction = dropAction ? dropAction : dragData.dropAction;
+ dragData.dropAction = dropAction || dragData.dropAction;
e.stopPropagation();
}
};
@@ -291,7 +293,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
dragData.removeDocument = this._props.removeDocument;
dragData.moveDocument = this._props.moveDocument;
dragData.draggedViews = [docView];
- dragData.canEmbed = this.Document.dragAction ?? this._props.dragAction ? true : false;
+ dragData.canEmbed = !!(this.Document.dragAction ?? this._props.dragAction);
(this._props.dragConfig ?? this._componentView?.dragConfig)?.(dragData);
DragManager.StartDocumentDrag(
selected.map(dv => dv.ContentDiv!),
@@ -311,7 +313,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
onClick = action((e: React.MouseEvent | React.PointerEvent) => {
if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
const documentView = this._docView;
- if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
+ if (documentView && !this.Document.ignoreClick && this._props.renderDepth >= 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
let stopPropagate = true;
let preventDefault = true;
!this.layoutDoc._keepZWhenDragged && this._props.bringToFront?.(this.Document);
@@ -368,6 +370,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if ((clickFunc && waitFordblclick !== 'never') || waitFordblclick === 'always') {
this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout);
this._doubleClickTimeout = setTimeout(this._singleClickFunc, 300);
+ // eslint-disable-next-line no-use-before-define
} else if (!DocumentView.LongPress) {
this._singleClickFunc();
this._singleClickFunc = undefined;
@@ -380,6 +383,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
onPointerDown = (e: React.PointerEvent): void => {
if (this._props.isGroupActive?.() === 'child' && !this._props.isDocumentActive?.()) return;
+ // eslint-disable-next-line no-use-before-define
this._longPressSelector = setTimeout(() => DocumentView.LongPress && this._props.select(false), 1000);
if (!GestureOverlay.DownDocView) GestureOverlay.DownDocView = this._docView;
@@ -412,7 +416,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
onPointerMove = (e: PointerEvent): void => {
if (e.buttons !== 1 || [InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) return;
- if (!Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
+ if (!ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
this.cleanupPointerEvents();
this._longPressSelector && clearTimeout(this._longPressSelector);
this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && dropActionType.embed) || ((this.Document.dragAction || this._props.dragAction || undefined) as dropActionType));
@@ -430,14 +434,15 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (this.onPointerUpHandler?.script) {
this.onPointerUpHandler.script.run({ this: this.Document }, console.log);
- } else if (e.button === 0 && Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
- this._doubleTap = (this.onDoubleClickHandler?.script || this.Document.defaultDoubleClick !== 'ignore') && Date.now() - this._lastTap < Utils.CLICK_TIME;
+ } else if (e.button === 0 && ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime)) {
+ this._doubleTap = (this.onDoubleClickHandler?.script || this.Document.defaultDoubleClick !== 'ignore') && Date.now() - this._lastTap < ClientUtils.CLICK_TIME;
if (!this.isContentActive()) this._lastTap = Date.now(); // don't want to process the start of a double tap if the doucment is selected
}
+ // eslint-disable-next-line no-use-before-define
if (DocumentView.LongPress) e.preventDefault();
};
- toggleFollowLink = undoable((zoom?: boolean, setTargetToggle?: boolean): void => {
+ toggleFollowLink = undoable((): void => {
const hadOnClick = this.Document.onClick;
this.noOnClick();
this.Document.onClick = hadOnClick ? undefined : FollowLinkScript();
@@ -458,16 +463,14 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}, 'default on click');
deleteClicked = undoable(() => this._props.removeDocument?.(this.Document), 'delete doc');
- setToggleDetail = undoable(
- (scriptFieldKey: 'onClick') =>
- (this.Document[scriptFieldKey] = ScriptField.MakeScript(
- `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey)
- .replace('layout_', '')
- .replace(/^layout$/, 'detail')}")`,
- { documentView: 'any' }
- )),
- 'set toggle detail'
- );
+ setToggleDetail = undoable((scriptFieldKey: 'onClick') => {
+ this.Document[scriptFieldKey] = ScriptField.MakeScript(
+ `toggleDetail(documentView, "${StrCast(this.Document.layout_fieldKey)
+ .replace('layout_', '')
+ .replace(/^layout$/, 'detail')}")`,
+ { documentView: 'any' }
+ );
+ }, 'set toggle detail');
drop = undoable((e: Event, de: DragManager.DropEvent) => {
if (this._props.dontRegisterView || this._props.LayoutTemplateString?.includes(LinkAnchorBox.name)) return false;
@@ -505,7 +508,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const input = document.createElement('input');
input.type = 'file';
input.accept = '.zip';
- input.onchange = _e => {
+ input.onchange = () => {
if (input.files) {
const batch = UndoManager.StartBatch('importing');
Doc.importDocument(input.files[0]).then(doc => {
@@ -523,7 +526,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (e && this.layoutDoc.layout_hideContextMenu && Doc.noviceMode) {
e.preventDefault();
e.stopPropagation();
- //!this._props.isSelected(true) && SelectionManager.SelectView(this.DocumentView(), false);
+ // !this._props.isSelected(true) && SelectionManager.SelectView(this.DocumentView(), false);
}
// the touch onContextMenu is button 0, the pointer onContextMenu is button 2
if (e) {
@@ -535,7 +538,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
e.stopPropagation();
e.persist();
- if (!navigator.userAgent.includes('Mozilla') && (Math.abs(this._downX - e?.clientX) > 3 || Math.abs(this._downY - e?.clientY) > 3)) {
+ if (!navigator.userAgent.includes('Mozilla') && (Math.abs(this._downX - (e?.clientX ?? 0)) > 3 || Math.abs(this._downY - (e?.clientY ?? 0)) > 3)) {
return;
}
}
@@ -587,7 +590,11 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
zorderItems.push({ description: 'Send to Back', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' });
zorderItems.push({
description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged',
- event: undoBatch(action(() => (this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged))),
+ event: undoBatch(
+ action(() => {
+ this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged;
+ })
+ ),
icon: 'hand-point-up',
});
!zorders && cm.addItem({ description: 'Z Order...', addDivider: true, noexpand: true, subitems: zorderItems, icon: 'layer-group' });
@@ -597,7 +604,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const existingOnClick = cm.findByDescription('OnClick...');
const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
- onClicks.push({ description: 'Enter Portal', event: undoable(e => DocUtils.makeIntoPortal(this.Document, this.layoutDoc, this._allLinks), 'make into portal'), icon: 'window-restore' });
+ onClicks.push({ description: 'Enter Portal', event: undoable(() => DocUtils.makeIntoPortal(this.Document, this.layoutDoc, this._allLinks), 'make into portal'), icon: 'window-restore' });
!Doc.noviceMode && onClicks.push({ description: 'Toggle Detail', event: this.setToggleDetail, icon: 'concierge-bell' });
if (!this.Document.annotationOn) {
@@ -613,9 +620,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const funcs: ContextMenuProps[] = [];
if (!Doc.noviceMode && this.layoutDoc.onDragStart) {
- funcs.push({ description: 'Drag an Embedding', icon: 'edit', event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getEmbedding(this.dragFactory)')) });
- funcs.push({ description: 'Drag a Copy', icon: 'edit', event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
- funcs.push({ description: 'Drag Document', icon: 'edit', event: () => (this.layoutDoc.onDragStart = undefined) });
+ funcs.push({ description: 'Drag an Embedding', icon: 'edit', event: () => { this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getEmbedding(this.dragFactory)')); } }); // prettier-ignore
+ funcs.push({ description: 'Drag a Copy', icon: 'edit', event: () => { this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')); } }); // prettier-ignore
+ funcs.push({ description: 'Drag Document', icon: 'edit', event: () => { this.layoutDoc.onDragStart = undefined; } }); // prettier-ignore
cm.addItem({ description: 'OnDrag...', noexpand: true, subitems: funcs, icon: 'asterisk' });
}
@@ -624,14 +631,14 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (!Doc.IsSystem(this.Document)) {
if (!Doc.noviceMode) {
moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' });
- moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => (this.Document._chromeHidden = !this.Document._chromeHidden), icon: 'project-diagram' });
+ moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => { this.Document._chromeHidden = !this.Document._chromeHidden; }, icon: 'project-diagram' }); // prettier-ignore
if (Cast(Doc.GetProto(this.Document).data, listSpec(Doc))) {
moreItems.push({ description: 'Export to Google Photos Album', event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.Document }).then(console.log), icon: 'caret-square-right' });
moreItems.push({ description: 'Tag Child Images via Google Photos', event: () => GooglePhotos.Query.TagChildImages(this.Document), icon: 'caret-square-right' });
moreItems.push({ description: 'Write Back Link to Album', event: () => GooglePhotos.Transactions.AddTextEnrichment(this.Document), icon: 'caret-square-right' });
}
- moreItems.push({ description: 'Copy ID', event: () => Utils.CopyText(Doc.globalServerPath(this.Document)), icon: 'fingerprint' });
+ moreItems.push({ description: 'Copy ID', event: () => ClientUtils.CopyText(Doc.globalServerPath(this.Document)), icon: 'fingerprint' });
}
}
@@ -639,7 +646,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
const constantItems: ContextMenuProps[] = [];
if (!Doc.IsSystem(this.Document) && this.Document._type_collection !== CollectionViewType.Docking) {
- constantItems.push({ description: 'Zip Export', icon: 'download', event: async () => Doc.Zip(this.Document) });
+ constantItems.push({ description: 'Zip Export', icon: 'download', event: async () => DocUtils.Zip(this.Document) });
(this.Document._type_collection !== CollectionViewType.Docking || !Doc.noviceMode) && constantItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this._docView), icon: 'users' });
if (this._props.removeDocument && Doc.ActiveDashboard !== this.Document) {
// need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions)
@@ -655,8 +662,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
!Doc.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.Document), icon: 'hand-point-right' });
!Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.dataDoc), icon: 'hand-point-right' });
- let documentationDescription: string | undefined = undefined;
- let documentationLink: string | undefined = undefined;
+ let documentationDescription: string | undefined;
+ let documentationLink: string | undefined;
switch (this.Document.type) {
case DocumentType.COL:
documentationDescription = 'See collection documentation';
@@ -690,6 +697,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
documentationDescription = 'See DataViz node documentation';
documentationLink = 'https://brown-dash.github.io/Dash-Documentation/documents/dataViz/';
break;
+ default:
}
// Add link to help documentation (unless the doc contents have been overriden in which case the documentation isn't relevant)
if (!this.docContents && documentationDescription && documentationLink) {
@@ -710,8 +718,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
panelHeight = () => this._props.PanelHeight() - this.headerMargin;
screenToLocalContent = () => this._props.ScreenToLocalTransform().translate(0, -this.headerMargin);
onClickFunc = this.disableClickScriptFunc ? undefined : () => this.onClickHandler;
- setHeight = (height: number) => !this._props.suppressSetHeight && (this.layoutDoc._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), height));
- setContentView = action((view: ViewBoxInterface) => (this._componentView = view));
+ setHeight = (height: number) => { !this._props.suppressSetHeight && (this.layoutDoc._height = Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), height)); } // prettier-ignore
+ setContentView = action((view: ViewBoxInterface) => { this._componentView = view; }); // prettier-ignore
isContentActive = (): boolean | undefined => this._isContentActive;
childFilters = () => [...this._props.childFilters(), ...StrListCast(this.layoutDoc.childFilters)];
@@ -729,11 +737,13 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const filtered = DocUtils.FilterDocs(this.directLinks, this._props.childFilters?.() ?? [], []).filter(d => d.link_displayLine || Doc.UserDoc().showLinkLines);
return filtered.some(link => link._link_displayArrow) ? 0 : undefined;
}
+ default:
}
return this._props.styleProvider?.(doc, props, property);
};
- removeLinkByHiding = (link: Doc) => () => (link.link_displayLine = false);
+ // eslint-disable-next-line no-return-assign
+ removeLinkByHiding = (link: Doc) => () => link.link_displayLine = false; // prettier-ignore
@computed get allLinkEndpoints() {
// the small blue dots that mark the endpoints of links
if (this._componentView instanceof KeyValueBox || this._props.hideLinkAnchors || this.layoutDoc.layout_hideLinkAnchors || this._props.dontRegisterView || this.layoutDoc.layout_unrendered) return null;
@@ -748,8 +758,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
PanelHeight={this.anchorPanelHeight}
dontRegisterView={false}
layout_showTitle={returnEmptyString}
- hideCaptions={true}
- hideLinkAnchors={true}
+ hideCaptions
+ hideLinkAnchors
layout_fitWidth={returnTrue}
removeDocument={this.removeLinkByHiding(link)}
styleProvider={this.anchorStyleProvider}
@@ -792,32 +802,30 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
captionStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string) => this._props?.styleProvider?.(doc, props, property + ':caption');
- fieldsDropdown = (placeholder: string) => {
- return (
- <div
- ref={action((r: any) => r && (this._titleDropDownInnerWidth = DivWidth(r)))}
- onPointerDown={action(e => (this._changingTitleField = true))}
- style={{ width: 'max-content', background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, transformOrigin: 'left', transform: `scale(${this.titleHeight / 30 /* height of Dropdown */})` }}>
- <FieldsDropdown
- Document={this.Document}
- placeholder={placeholder}
- selectFunc={action((field: string | number) => {
- if (this.layoutDoc.layout_showTitle) {
- this.layoutDoc._layout_showTitle = field;
- } else if (!this._props.layout_showTitle) {
- Doc.UserDoc().layout_showTitle = field;
- }
- this._changingTitleField = false;
- })}
- menuClose={action(() => (this._changingTitleField = false))}
- />
- </div>
- );
- };
+ fieldsDropdown = (placeholder: string) => (
+ <div
+ ref={action((r: any) => { r && (this._titleDropDownInnerWidth = DivWidth(r));} )} // prettier-ignore
+ onPointerDown={action(() => { this._changingTitleField = true; })} // prettier-ignore
+ style={{ width: 'max-content', background: SnappingManager.userBackgroundColor, color: SnappingManager.userColor, transformOrigin: 'left', transform: `scale(${this.titleHeight / 30 /* height of Dropdown */})` }}>
+ <FieldsDropdown
+ Document={this.Document}
+ placeholder={placeholder}
+ selectFunc={action((field: string | number) => {
+ if (this.layoutDoc.layout_showTitle) {
+ this.layoutDoc._layout_showTitle = field;
+ } else if (!this._props.layout_showTitle) {
+ Doc.UserDoc().layout_showTitle = field;
+ }
+ this._changingTitleField = false;
+ })}
+ menuClose={action(() => { this._changingTitleField = false; })} // prettier-ignore
+ />
+ </div>
+ );
/**
* displays a 'title' at the top of a document. The title contents default to the 'title' field, but can be changed to one or more fields by
* setting layout_showTitle using the format: field1[:hover]
- **/
+ * */
@computed get titleView() {
const showTitle = this.layout_showTitle?.split(':')[0];
const showTitleHover = this.layout_showTitle?.includes(':hover');
@@ -825,7 +833,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.Document;
const background = StrCast(
this.layoutDoc.layout_headingColor,
- StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SettingsManager.userBackgroundColor))
+ StrCast(SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, StrCast(Doc.SharingDoc().headingColor, SnappingManager.userBackgroundColor))
);
const dropdownWidth = this._titleRef.current?._editing || this._changingTitleField ? Math.max(10, (this._titleDropDownInnerWidth * this.titleHeight) / 30) : 0;
const sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', '');
@@ -839,7 +847,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
position: this.headerMargin ? 'relative' : 'absolute',
height: this.titleHeight,
width: 100 - sidebarWidthPercent + '%',
- color: background === 'transparent' ? SettingsManager.userColor : lightOrDark(background),
+ color: background === 'transparent' ? SnappingManager.userColor : lightOrDark(background),
background,
pointerEvents: (!this.disableClickScriptFunc && this.onClickHandler) || this.Document.ignoreClick ? 'none' : this.isContentActive() || this._props.isDocumentActive?.() ? 'all' : undefined,
}}>
@@ -860,11 +868,11 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
contents={
showTitle
.split(';')
- .map(field => Field.toJavascriptString(this.Document[field] as Field))
+ .map(field => Field.toJavascriptString(this.Document[field] as FieldType))
.join(' \\ ') || '-unset-'
}
display="block"
- oneLine={true}
+ oneLine
fontSize={(this.titleHeight / 15) * 10}
GetValue={() =>
showTitle
@@ -905,10 +913,10 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
xPadding={10}
fieldKey={this.layout_showCaption}
styleProvider={this.captionStyleProvider}
- dontRegisterView={true}
+ dontRegisterView
rootSelected={this.rootSelected}
- noSidebar={true}
- dontScale={true}
+ noSidebar
+ dontScale
renderDepth={this._props.renderDepth}
isContentActive={this.isContentActive}
/>
@@ -952,8 +960,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
render() {
TraceMobx();
- const highlighting = this.highlighting;
- const borderPath = this.borderPath;
+ const { highlighting, borderPath } = this;
const boxShadow = !highlighting
? this.boxShadow
: highlighting && this.borderRounding && highlighting.highlightStyle !== 'dashed'
@@ -968,23 +975,22 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
});
return (
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
<div
className={`${DocumentView.ROOT_DIV} docView-hack`}
ref={this._mainCont}
onContextMenu={this.onContextMenu}
onPointerDown={this.onPointerDown}
onClick={this.onClick}
- onPointerEnter={e => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)}
- onPointerOver={e => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)}
+ onPointerEnter={() => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)}
+ onPointerOver={() => (!SnappingManager.IsDragging || SnappingManager.CanEmbed) && Doc.BrushDoc(this.Document)}
onPointerLeave={e => !isParentOf(this._contentDiv, document.elementFromPoint(e.nativeEvent.x, e.nativeEvent.y)) && Doc.UnBrushDoc(this.Document)}
style={{
borderRadius: this.borderRounding,
pointerEvents: this._pointerEvents === 'visiblePainted' ? 'none' : this._pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here)
}}>
- <>
- {this._componentView instanceof KeyValueBox ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)}
- {borderPath?.jsx}
- </>
+ {this._componentView instanceof KeyValueBox ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation])}
+ {borderPath?.jsx}
</div>
);
}
@@ -994,7 +1000,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
* @param presEffectDoc presentation effects document that specifies the animation effect parameters
* @returns a function that will wrap a JSX animation element wrapping any JSX element
*/
- public static AnimationEffect(renderDoc: JSX.Element, presEffectDoc: Opt<Doc>, root: Doc) {
+ public static AnimationEffect(renderDoc: JSX.Element, presEffectDoc: Opt<Doc> /* , root: Doc */) {
const dir = presEffectDoc?.presentation_effectDirection ?? presEffectDoc?.followLinkAnimDirection;
const effectProps = {
left: dir === PresEffectDirection.Left,
@@ -1005,10 +1011,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
delay: 0,
duration: Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)),
};
- //prettier-ignore
+ // prettier-ignore
switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) {
- default:
- case PresEffect.None: return renderDoc;
case PresEffect.Zoom: return <Zoom {...effectProps}>{renderDoc}</Zoom>;
case PresEffect.Fade: return <Fade {...effectProps}>{renderDoc}</Fade>;
case PresEffect.Flip: return <Flip {...effectProps}>{renderDoc}</Flip>;
@@ -1016,17 +1020,19 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
case PresEffect.Bounce: return <Bounce {...effectProps}>{renderDoc}</Bounce>;
case PresEffect.Roll: return <Roll {...effectProps}>{renderDoc}</Roll>;
case PresEffect.Lightspeed: return <JackInTheBox {...effectProps}>{renderDoc}</JackInTheBox>;
+ case PresEffect.None:
+ default: return renderDoc;
}
}
public static recordAudioAnnotation(dataDoc: Doc, field: string, onRecording?: (stop: () => void) => void, onEnd?: () => void) {
let gumStream: any;
let recorder: any;
- navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) {
+ navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
let audioTextAnnos = Cast(dataDoc[field + '_audioAnnotations_text'], listSpec('string'), null);
if (audioTextAnnos) audioTextAnnos.push('');
else audioTextAnnos = dataDoc[field + '_audioAnnotations_text'] = new List<string>(['']);
DictationManager.Controls.listen({
- interimHandler: value => (audioTextAnnos[audioTextAnnos.length - 1] = value),
+ interimHandler: value => { audioTextAnnos[audioTextAnnos.length - 1] = value; }, // prettier-ignore
continuous: { indefinite: false },
}).then(results => {
if (results && [DictationManager.Controls.Infringed].includes(results)) {
@@ -1060,9 +1066,9 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
@observer
-export class DocumentView extends DocComponent<DocumentViewProps>() {
+export class DocumentView extends DocComponent<DocumentViewProps & { CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView }>() {
public static ROOT_DIV = 'documentView-effectsWrapper';
- public get displayName() { return 'DocumentView(' + this.Document?.title + ')'; } // prettier-ignore
+ public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore
public ContentRef = React.createRef<HTMLDivElement>();
private _htmlOverlayEffect: Opt<Doc>;
private _disposers: { [name: string]: IReactionDisposer } = {};
@@ -1084,7 +1090,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
return () => (SnappingManager.ExploreMode ? ScriptField.MakeScript('CollectionBrowseClick(documentView, clientX, clientY)', { documentView: 'any', clientX: 'number', clientY: 'number' })! : undefined);
}
- constructor(props: DocumentViewProps) {
+ constructor(props: DocumentViewProps & { CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView }) {
super(props);
makeObservable(this);
}
@@ -1161,7 +1167,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
!BoolCast(this.Document.dontRegisterView, this._props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
}
- public set IsSelected(val) { runInAction(() => (this._selected = val)); } // prettier-ignore
+ public set IsSelected(val) { runInAction(() => { this._selected = val; }); } // prettier-ignore
public get IsSelected() { return this._selected; } // prettier-ignore
public get topMost() { return this._props.renderDepth === 0; } // prettier-ignore
public get ContentDiv() { return this._docViewInternal?._contentDiv; } // prettier-ignore
@@ -1176,7 +1182,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
return this._props.layout_fitWidth?.(this.layoutDoc) ?? this.layoutDoc?.layout_fitWidth;
}
@computed get anchorViewDoc() {
- return this._props.LayoutTemplateString?.includes('link_anchor_2') ? DocCast(this.Document['link_anchor_2']) : this._props.LayoutTemplateString?.includes('link_anchor_1') ? DocCast(this.Document['link_anchor_1']) : undefined;
+ return this._props.LayoutTemplateString?.includes('link_anchor_2') ? DocCast(this.Document.link_anchor_2) : this._props.LayoutTemplateString?.includes('link_anchor_1') ? DocCast(this.Document.link_anchor_1) : undefined;
}
@computed get getBounds(): Opt<{ left: number; top: number; right: number; bottom: number; transition?: string }> {
@@ -1213,6 +1219,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
public get containerViewPath() { return this._props.containerViewPath; } // prettier-ignore
public get CollectionFreeFormView() { return this.CollectionFreeFormDocumentView?.CollectionFreeFormView; } // prettier-ignore
public get CollectionFreeFormDocumentView() { return this._props.CollectionFreeFormDocumentView?.(); } // prettier-ignore
+ public get LocalRotation() { return this._props.LocalRotation?.(); } // prettier-ignore
public clearViewTransition = () => {
this._viewTimer && clearTimeout(this._viewTimer);
@@ -1231,18 +1238,18 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
public iconify(finished?: () => void, animateTime?: number) {
this.ComponentView?.updateIcon?.();
const animTime = this._docViewInternal?.animateScaleTime();
- runInAction(() => this._docViewInternal && animateTime !== undefined && (this._docViewInternal._animateScaleTime = animateTime));
+ runInAction(() => { this._docViewInternal && animateTime !== undefined && (this._docViewInternal._animateScaleTime = animateTime); }); // prettier-ignore
const finalFinished = action(() => {
finished?.();
this._docViewInternal && (this._docViewInternal._animateScaleTime = animTime);
});
- const layout_fieldKey = Cast(this.Document.layout_fieldKey, 'string', null);
- if (layout_fieldKey !== 'layout_icon') {
+ const layoutFieldKey = Cast(this.Document.layout_fieldKey, 'string', null);
+ if (layoutFieldKey !== 'layout_icon') {
this.switchViews(true, 'icon', finalFinished);
- if (layout_fieldKey && layout_fieldKey !== 'layout' && layout_fieldKey !== 'layout_icon') this.Document.deiconifyLayout = layout_fieldKey.replace('layout_', '');
+ if (layoutFieldKey && layoutFieldKey !== 'layout' && layoutFieldKey !== 'layout_icon') this.Document.deiconifyLayout = layoutFieldKey.replace('layout_', '');
} else {
const deiconifyLayout = Cast(this.Document.deiconifyLayout, 'string', null);
- this.switchViews(deiconifyLayout ? true : false, deiconifyLayout, finalFinished, true);
+ this.switchViews(!!deiconifyLayout, deiconifyLayout, finalFinished, true);
this.Document.deiconifyLayout = undefined;
this._props.bringToFront?.(this.Document);
}
@@ -1262,7 +1269,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
autoplay: true,
loop: false,
volume: 0.5,
- onend: action(() => (self.dataDoc.audioAnnoState = AudioAnnoState.stopped)),
+ onend: action(() => { self.dataDoc.audioAnnoState = AudioAnnoState.stopped; }), // prettier-ignore
});
this.dataDoc.audioAnnoState = AudioAnnoState.playing;
break;
@@ -1270,6 +1277,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
this.dataDoc[AudioPlay]?.stop();
this.dataDoc.audioAnnoState = AudioAnnoState.stopped;
break;
+ default:
}
}
};
@@ -1284,10 +1292,10 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
this._docViewInternal._animateScaleTime = time;
}
});
- public setAnimEffect = (presEffect: Doc, timeInMs: number, afterTrans?: () => void) => {
+ public setAnimEffect = (presEffect: Doc, timeInMs: number /* , afterTrans?: () => void */) => {
this._animEffectTimer && clearTimeout(this._animEffectTimer);
this.Document[Animation] = presEffect;
- this._animEffectTimer = setTimeout(() => (this.Document[Animation] = undefined), timeInMs);
+ this._animEffectTimer = setTimeout(() => { this.Document[Animation] = undefined; }, timeInMs); // prettier-ignore
};
public setViewTransition = (transProp: string, timeInMs: number, afterTrans?: () => void, dataTrans = false) => {
this._viewTimer = DocumentView.SetViewTransition([this.layoutDoc], transProp, timeInMs, this._viewTimer, afterTrans, dataTrans);
@@ -1304,7 +1312,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
const view = SelectionManager.Views[0]?._props.renderDepth > 0 ? SelectionManager.Views[0] : undefined;
undoable(() => {
- var tempDoc: Opt<Doc>;
+ let tempDoc: Opt<Doc>;
if (view) {
if (!view.layoutDoc.isTemplateDoc) {
tempDoc = view.Document;
@@ -1322,6 +1330,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
Doc.UserDoc().defaultTextLayout = tempDoc ? new PrefetchProxy(tempDoc) : undefined;
}, 'set default template')();
+ return undefined;
}
/**
@@ -1335,12 +1344,13 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
const curLayout = StrCast(this.Document.layout_fieldKey).replace('layout_', '').replace('layout', '');
if (!this.Document.layout_default && curLayout !== detailLayoutKeySuffix) this.Document.layout_default = curLayout;
const defaultLayout = StrCast(this.Document.layout_default);
- if (this.Document.layout_fieldKey === 'layout_' + detailLayoutKeySuffix) this.switchViews(defaultLayout ? true : false, defaultLayout, undefined, true);
+ if (this.Document.layout_fieldKey === 'layout_' + detailLayoutKeySuffix) this.switchViews(!!defaultLayout, defaultLayout, undefined, true);
else this.switchViews(true, detailLayoutKeySuffix, undefined, true);
};
public switchViews = (custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => {
const batch = UndoManager.StartBatch('switchView:' + view);
- runInAction(() => this._docViewInternal && (this._docViewInternal._animateScalingTo = 0.1)); // shrink doc
+ // shrink doc first..
+ runInAction(() => { this._docViewInternal && (this._docViewInternal._animateScalingTo = 0.1); }); // prettier-ignore
setTimeout(
action(() => {
if (useExistingLayout && custom && this.Document['layout_' + view]) {
@@ -1348,7 +1358,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
} else {
this.setCustomView(custom, view);
}
- this._docViewInternal && (this._docViewInternal._animateScalingTo = 1); // expand it
+ this._docViewInternal && (this._docViewInternal._animateScalingTo = 1); // now expand it
setTimeout(
action(() => {
this._docViewInternal && (this._docViewInternal._animateScalingTo = 0);
@@ -1366,7 +1376,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
*/
public docViewPath = () => (this.containerViewPath ? [...this.containerViewPath(), this] : [this]);
- layout_fitWidthFunc = (doc: Doc) => BoolCast(this.layout_fitWidth);
+ layout_fitWidthFunc = (/* doc: Doc */) => BoolCast(this.layout_fitWidth);
screenToLocalScale = () => this._props.ScreenToLocalTransform().Scale;
isSelected = () => this.IsSelected;
select = (extendSelection: boolean, focusSelection?: boolean) => {
@@ -1390,7 +1400,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
PanelWidth = () => this.panelWidth;
PanelHeight = () => this.panelHeight;
NativeDimScaling = () => this.nativeScaling;
- hideLinkCount = () => (this.hideLinkButton ? true : false);
+ hideLinkCount = () => !!this.hideLinkButton;
selfView = () => this;
/**
* @returns Transform to the document view (in the coordinate system of whatever contains the DocumentView)
@@ -1413,17 +1423,16 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
ref={r => {
const val = r?.style.display !== 'none'; // if the outer overlay has been displayed, trigger the innner div to start it's opacity fade in transition
if (r && val !== this._enableHtmlOverlayTransitions) {
- setTimeout(action(() => (this._enableHtmlOverlayTransitions = val)));
+ setTimeout(action(() => { this._enableHtmlOverlayTransitions = val; })); // prettier-ignore
}
}}
style={{ display: !this._htmlOverlayText ? 'none' : undefined }}>
<div className="documentView-htmlOverlayInner" style={{ transition: `all 500ms`, opacity: this._enableHtmlOverlayTransitions ? 0.9 : 0 }}>
{DocumentViewInternal.AnimationEffect(
<div className="webBox-textHighlight">
- <ObserverJsxParser autoCloseVoidElements={true} key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this._htmlOverlayText)} />
+ <ObserverJsxParser autoCloseVoidElements key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this._htmlOverlayText)} />
</div>,
- { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc,
- this.Document
+ { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc
)}
</div>
</div>
@@ -1436,7 +1445,15 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
const yshift = Math.abs(this.Yshift) <= 0.001 ? this._props.PanelHeight() : undefined;
return (
- <div id={this.ViewGuid} className="contentFittingDocumentView" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))}>
+ <div
+ id={this.ViewGuid}
+ className="contentFittingDocumentView"
+ onPointerEnter={action(() => {
+ this._isHovering = true;
+ })}
+ onPointerLeave={action(() => {
+ this._isHovering = false;
+ })}>
{!this.Document || !this._props.PanelWidth() ? null : (
<div
className="contentFittingDocumentView-previewDoc"
@@ -1462,14 +1479,16 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
layout_fitWidth={this.layout_fitWidthFunc}
ScreenToLocalTransform={this.screenToContentsTransform}
focus={this._props.focus || emptyFunction}
- ref={action((r: DocumentViewInternal | null) => r && (this._docViewInternal = r))}
+ ref={action((r: DocumentViewInternal | null) => {
+ r && (this._docViewInternal = r);
+ })}
/>
{this.htmlOverlay()}
{this.ComponentView?.infoUI?.()}
</div>
)}
{/* display link count button */}
- <DocumentLinksButton hideCount={this.hideLinkCount} View={this} scaling={this.screenToLocalScale} OnHover={true} Bottom={this.topMost} ShowCount={true} />
+ <DocumentLinksButton hideCount={this.hideLinkCount} View={this} scaling={this.screenToLocalScale} OnHover Bottom={this.topMost} ShowCount />
</div>
);
}
@@ -1493,7 +1512,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
// shows a stacking view collection (by default, but the user can change) of all documents linked to the source
public static showBackLinks(linkAnchor: Doc) {
- const docId = Doc.CurrentUserEmail + Doc.GetProto(linkAnchor)[Id] + '-pivotish';
+ const docId = ClientUtils.CurrentUserEmail + Doc.GetProto(linkAnchor)[Id] + '-pivotish';
// prettier-ignore
DocServer.GetRefField(docId).then(docx =>
LightboxView.Instance.SetLightboxDoc(
@@ -1504,19 +1523,27 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
}
}
+export function returnEmptyDocViewList() {
+ return emptyPath;
+}
+
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) {
documentView.iconify();
documentView.select(false);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function deiconifyViewToLightbox(documentView: DocumentView) {
- LightboxView.Instance.AddDocTab(documentView.Document, OpenWhere.lightbox, 'layout'); //, 0);
+ LightboxView.Instance.AddDocTab(documentView.Document, OpenWhere.lightbox, 'layout'); // , 0);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string) {
dv.toggleDetail(detailLayoutKeySuffix);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSource: Doc) {
const collectedLinks = DocListCast(linkCollection[DocData].data);
let wid = NumCast(linkSource._width);
@@ -1534,9 +1561,10 @@ ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc, linkSour
Doc.AddDocToList(Doc.GetProto(linkCollection), 'data', embedding);
}
});
- embedding && DocServer.UPDATE_SERVER_CACHE(); // if a new embedding was made, update the client's server cache so that it will not come back as a promise
+ embedding && UPDATE_SERVER_CACHE(); // if a new embedding was made, update the client's server cache so that it will not come back as a promise
return links;
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function updateTagsCollection(collection: Doc) {
const tag = StrCast(collection.title).split('-->')[1];
const matchedTags = Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, tag, false, ['tags']).keys());
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index a557cff4f..9be66ba4a 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -1,7 +1,7 @@
import { action, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { DivHeight, DivWidth } from '../../../Utils';
+import { DivHeight, DivWidth } from '../../../ClientUtils';
import { Id } from '../../../fields/FieldSymbols';
import { NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 771856788..14454ff61 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,3 +1,4 @@
+import { computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { DateField } from '../../../fields/DateField';
@@ -5,13 +6,10 @@ import { Doc, Field, Opt } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { ScriptField } from '../../../fields/ScriptField';
import { WebField } from '../../../fields/URLField';
-import { dropActionType } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { Transform } from '../../util/Transform';
-import { ViewBoxInterface } from '../DocComponent';
-import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView';
+import { PinProps, ViewBoxInterface } from '../DocComponent';
import { DocumentView, OpenWhere } from './DocumentView';
-import { PinProps } from './trails';
-import { computed } from 'mobx';
export interface FocusViewOptions {
willPan?: boolean; // determines whether to pan to target document
@@ -56,7 +54,7 @@ export interface FieldViewSharedProps {
disableBrushing?: boolean; // should highlighting for this view be disabled when same document in another view is hovered over.
hideClickBehaviors?: boolean; // whether to suppress menu item options for changing click behaviors
ignoreUsePath?: boolean; // ignore the usePath field for selecting the fieldKey (eg., on text docs)
- CollectionFreeFormDocumentView?: () => CollectionFreeFormDocumentView;
+ LocalRotation?: () => number | undefined; // amount of rotation applied to freeformdocumentview containing document view
containerViewPath?: () => DocumentView[];
fitContentsToBox?: () => boolean; // used by freeformview to fit its contents to its panel. corresponds to _freeform_fitContentsToBox property on a Document
isGroupActive?: () => string | undefined; // is this document part of a group that is active
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 57ae92359..70fc63115 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -6,7 +6,8 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
import { BoolCast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnTrue, setupMoveUpEvents, Utils } from '../../../../Utils';
+import { emptyFunction, Utils } from '../../../../Utils';
+import { ClientUtils, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { SelectionManager } from '../../../util/SelectionManager';
import { SettingsManager } from '../../../util/SettingsManager';
@@ -183,7 +184,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
if (selected.length > 1) {
text = selected.length + ' selected';
} else {
- text = Utils.cleanDocumentType(StrCast(selected.lastElement().type) as DocumentType);
+ text = ClientUtils.cleanDocumentType(StrCast(selected.lastElement().type) as DocumentType);
icon = Doc.toIcon(selected.lastElement());
}
return (
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index a86bdbd79..180c651fb 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -2,18 +2,18 @@ import functionPlot from 'function-plot';
import { computed, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCast } from '../../../fields/Doc';
+import { DocListCast } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { Cast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { DocUtils, Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
+import { LinkManager } from '../../util/LinkManager';
import { undoBatch } from '../../util/UndoManager';
-import { ViewBoxAnnotatableComponent } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent } from '../DocComponent';
import { FieldView, FieldViewProps } from './FieldView';
-import { PinProps, PresBox } from './trails';
-import { LinkManager } from '../../util/LinkManager';
+import { PresBox } from './trails';
@observer
export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@@ -89,7 +89,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.docDragData?.droppedDocuments.length) {
const added = de.complete.docDragData.droppedDocuments.reduce((res, doc) => {
- ///const ret = res && Doc.AddDocToList(this.dataDoc, this._props.fieldKey, doc);
+ // const ret = res && Doc.AddDocToList(this.dataDoc, this._props.fieldKey, doc);
if (res) {
const link = DocUtils.MakeLink(doc, this.Document, { link_relationship: 'function', link_description: 'input' });
link && this._props.addDocument?.(link);
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index bb1f70f97..231300a65 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,10 +1,11 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { Colors } from 'browndash-components';
-import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { extname } from 'path';
import * as React from 'react';
+import { ClientUtils, DashColor, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -14,7 +15,7 @@ import { ObjectField } from '../../../fields/ObjectField';
import { Cast, ImageCast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
-import { DashColor, emptyFunction, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { Networking } from '../../Network';
@@ -24,7 +25,7 @@ import { undoBatch } from '../../util/UndoManager';
import { ContextMenu } from '../../views/ContextMenu';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { OverlayView } from '../OverlayView';
import { AnchorMenu } from '../pdf/AnchorMenu';
@@ -32,26 +33,29 @@ import { StyleProp } from '../StyleProvider';
import { OpenWhere } from './DocumentView';
import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView';
import './ImageBox.scss';
-import { PinProps, PresBox } from './trails';
+import { PresBox } from './trails';
export class ImageEditorData {
+ // eslint-disable-next-line no-use-before-define
private static _instance: ImageEditorData;
private static get imageData() { return (ImageEditorData._instance ?? new ImageEditorData()).imageData; } // prettier-ignore
@observable imageData: { rootDoc: Doc | undefined; open: boolean; source: string; addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean> } = observable({ rootDoc: undefined, open: false, source: '', addDoc: undefined });
- @action private static set = (open: boolean, rootDoc: Doc | undefined, source: string, addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean>) => (this._instance.imageData = { open, rootDoc, source, addDoc });
+ @action private static set = (open: boolean, rootDoc: Doc | undefined, source: string, addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean>) => {
+ this._instance.imageData = { open, rootDoc, source, addDoc };
+ };
constructor() {
makeObservable(this);
ImageEditorData._instance = this;
}
- public static get Open() { return ImageEditorData.imageData.open; } // prettier-ignore
- public static get Source() { return ImageEditorData.imageData.source; } // prettier-ignore
- public static get RootDoc() { return ImageEditorData.imageData.rootDoc; } // prettier-ignore
- public static get AddDoc() { return ImageEditorData.imageData.addDoc; } // prettier-ignore
+ public static get Open() { return ImageEditorData.imageData.open; } // prettier-ignore
public static set Open(open: boolean) { ImageEditorData.set(open, this.imageData.rootDoc, this.imageData.source, this.imageData.addDoc); } // prettier-ignore
+ public static get Source() { return ImageEditorData.imageData.source; } // prettier-ignore
public static set Source(source: string) { ImageEditorData.set(this.imageData.open, this.imageData.rootDoc, source, this.imageData.addDoc); } // prettier-ignore
+ public static get RootDoc() { return ImageEditorData.imageData.rootDoc; } // prettier-ignore
public static set RootDoc(rootDoc: Opt<Doc>) { ImageEditorData.set(this.imageData.open, rootDoc, this.imageData.source, this.imageData.addDoc); } // prettier-ignore
+ public static get AddDoc() { return ImageEditorData.imageData.addDoc; } // prettier-ignore
public static set AddDoc(addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean>) { ImageEditorData.set(this.imageData.open, this.imageData.rootDoc, this.imageData.source, addDoc); } // prettier-ignore
}
@observer
@@ -93,7 +97,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
if (anchor) {
if (!addAsAnnotation) anchor.backgroundColor = 'transparent';
addAsAnnotation && this.addDocument(anchor);
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: visibleAnchor ? false : true } }, this.Document);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: !visibleAnchor } }, this.Document);
return anchor;
}
return this.Document;
@@ -106,10 +110,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
scrSize: (this.ScreenToLocalBoxXf().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth) * NumCast(this.layoutDoc._freeform_scale, 1),
selected: this._props.isSelected(),
}),
- ({ forceFull, scrSize, selected }) => (this._curSuffix = selected ? '_o' : this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 ? '_l' : '_o'),
+ ({ forceFull, scrSize, selected }) => {
+ this._curSuffix = selected ? '_o' : this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 ? '_l' : '_o';
+ },
{ fireImmediately: true, delay: 1000 }
);
- const layoutDoc = this.layoutDoc;
+ const { layoutDoc } = this;
this._disposers.path = reaction(
() => ({ nativeSize: this.nativeSize, width: NumCast(this.layoutDoc._width) }),
({ nativeSize, width }) => {
@@ -121,10 +127,10 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
);
this._disposers.scroll = reaction(
() => this.layoutDoc.layout_scrollTop,
- s_top => {
+ sTop => {
this._forcedScroll = true;
- !this._ignoreScroll && this._mainCont.current && (this._mainCont.current.scrollTop = NumCast(s_top));
- this._mainCont.current?.scrollTo({ top: NumCast(s_top) });
+ !this._ignoreScroll && this._mainCont.current && (this._mainCont.current.scrollTop = NumCast(sTop));
+ this._mainCont.current?.scrollTo({ top: NumCast(sTop) });
this._forcedScroll = false;
},
{ fireImmediately: true }
@@ -138,7 +144,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
@undoBatch
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.docDragData) {
- let added: boolean | undefined = undefined;
+ let added: boolean | undefined;
const targetIsBullseye = (ele: HTMLElement): boolean => {
if (!ele) return false;
if (ele === this._overlayIconRef.current) return true;
@@ -168,7 +174,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
};
@undoBatch
- resolution = () => (this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes);
+ resolution = () => {
+ this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes;
+ };
@undoBatch
setNativeSize = action(() => {
@@ -189,7 +197,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
const nh = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']);
const w = this.layoutDoc._width;
const h = this.layoutDoc._height;
- this.dataDoc[this.fieldKey + '-rotation'] = (NumCast(this.dataDoc[this.fieldKey + '-rotation']) + 90) % 360;
+ this.dataDoc[this.fieldKey + '_rotation'] = (NumCast(this.dataDoc[this.fieldKey + '_rotation']) + 90) % 360;
this.dataDoc[this.fieldKey + '_nativeWidth'] = nh;
this.dataDoc[this.fieldKey + '_nativeHeight'] = nw;
this.layoutDoc._width = h;
@@ -197,7 +205,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
});
crop = (region: Doc | undefined, addCrop?: boolean) => {
- if (!region) return;
+ if (!region) return undefined;
const cropping = Doc.MakeCopy(region, true);
const regionData = region[DocData];
regionData.lockedPosition = true;
@@ -223,8 +231,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
croppingProto.type = DocumentType.IMG;
croppingProto.layout = ImageBox.LayoutString('data');
croppingProto.data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField);
- croppingProto['data_nativeWidth'] = anchw;
- croppingProto['data_nativeHeight'] = anchh;
+ croppingProto.data_nativeWidth = anchw;
+ croppingProto.data_nativeHeight = anchh;
croppingProto.freeform_scale = viewScale;
croppingProto.freeform_scale_min = viewScale;
croppingProto.freeform_panX = anchx / viewScale;
@@ -244,14 +252,14 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
return cropping;
};
- specificContextMenu = (e: React.MouseEvent): void => {
+ specificContextMenu = (): void => {
const field = Cast(this.dataDoc[this.fieldKey], ImageField);
if (field) {
const funcs: ContextMenuProps[] = [];
funcs.push({ description: 'Rotate Clockwise 90', event: this.rotate, icon: 'redo-alt' });
funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? 'Dynamic Res' : 'Full Res'}`, event: this.resolution, icon: 'expand' });
funcs.push({ description: 'Set Native Pixel Size', event: this.setNativeSize, icon: 'expand-arrows-alt' });
- funcs.push({ description: 'Copy path', event: () => Utils.CopyText(this.choosePath(field.url)), icon: 'copy' });
+ funcs.push({ description: 'Copy path', event: () => ClientUtils.CopyText(this.choosePath(field.url)), icon: 'copy' });
funcs.push({
description: 'Open Image Editor',
event: action(() => {
@@ -270,7 +278,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
if (!url?.href) return '';
const lower = url.href.toLowerCase();
if (url.protocol === 'data') return url.href;
- if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return Utils.CorsProxy(url.href);
+ if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return ClientUtils.CorsProxy(url.href);
if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower) || lower.endsWith('/assets/unknown-file-icon-hi.png')) return `/assets/unknown-file-icon-hi.png`;
const ext = extname(url.href);
@@ -282,7 +290,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
TraceMobx();
const nativeWidth = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth'], NumCast(this.layoutDoc[this.fieldKey + '_nativeWidth'], 500));
const nativeHeight = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight'], NumCast(this.layoutDoc[this.fieldKey + '_nativeHeight'], 500));
- const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + '-nativeOrientation'], 1);
+ const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + '_nativeOrientation'], 1);
return { nativeWidth, nativeHeight, nativeOrientation };
}
@computed get overlayImageIcon() {
@@ -307,7 +315,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
<div
className="imageBox-alternateDropTarget"
ref={this._overlayIconRef}
- onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.layoutDoc[`_${this.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))}
+ onPointerDown={e =>
+ setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, () => {
+ this.layoutDoc[`_${this.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined;
+ })
+ }
style={{
display: (this._props.isContentActive() !== false && DragManager.DocDragData?.canEmbed) || this.dataDoc[this.fieldKey + '_alternates'] ? 'block' : 'none',
width: 'min(10%, 25px)',
@@ -324,7 +336,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
@computed get paths() {
const field = Cast(this.dataDoc[this.fieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc
const alts = this.dataDoc[this.fieldKey + '_alternates'] as any as List<Doc>; // retrieve alternate documents that may be rendered as alternate images
- const defaultUrl = new URL(Utils.prepend('/assets/unknown-file-icon-hi.png'));
+ const defaultUrl = new URL(ClientUtils.prepend('/assets/unknown-file-icon-hi.png'));
const altpaths =
alts
?.map(doc => (doc instanceof Doc ? ImageCast(doc[Doc.LayoutFieldKey(doc)])?.url ?? defaultUrl : defaultUrl))
@@ -344,8 +356,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
const backAlpha = backColor.red() === 0 && backColor.green() === 0 && backColor.blue() === 0 ? backColor.alpha() : 1;
const srcpath = this.layoutDoc.hideImage ? '' : this.paths[0];
const fadepath = this.layoutDoc.hideImage ? '' : this.paths.lastElement();
- const { nativeWidth, nativeHeight, nativeOrientation } = this.nativeSize;
- const rotation = NumCast(this.dataDoc[this.fieldKey + '-rotation']);
+ const { nativeWidth, nativeHeight /* , nativeOrientation */ } = this.nativeSize;
+ const rotation = NumCast(this.dataDoc[this.fieldKey + '_rotation']);
const aspect = rotation % 180 ? nativeHeight / nativeWidth : 1;
let transformOrigin = 'center center';
let transform = `translate(0%, 0%) rotate(${rotation}deg) scale(${aspect})`;
@@ -361,12 +373,32 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
const usePath = this.layoutDoc[`_${this.fieldKey}_usePath`];
return (
- <div className="imageBox-cont" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))} key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}>
+ <div
+ className="imageBox-cont"
+ onPointerEnter={action(() => {
+ this._isHovering = true;
+ })}
+ onPointerLeave={action(() => {
+ this._isHovering = false;
+ })}
+ key={this.layoutDoc[Id]}
+ ref={this.createDropTarget}
+ onPointerDown={this.marqueeDown}>
<div className="imageBox-fader" style={{ opacity: backAlpha }}>
- <img key="paths" src={srcpath} style={{ transform, transformOrigin }} onError={action(e => (this._error = e.toString()))} draggable={false} width={nativeWidth} />
+ <img
+ alt=""
+ key="paths"
+ src={srcpath}
+ style={{ transform, transformOrigin }}
+ onError={action(e => {
+ this._error = e.toString();
+ })}
+ draggable={false}
+ width={nativeWidth}
+ />
{fadepath === srcpath ? null : (
<div className={`imageBox-fadeBlocker${(this._isHovering && usePath === 'alternate:hover') || usePath === 'alternate' ? '-hover' : ''}`} style={{ transition: StrCast(this.layoutDoc.viewTransition, 'opacity 1000ms') }}>
- <img className="imageBox-fadeaway" key="fadeaway" src={fadepath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} />
+ <img alt="" className="imageBox-fadeaway" key="fadeaway" src={fadepath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} />
</div>
)}
</div>
@@ -384,8 +416,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
}
screenToLocalTransform = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop) * this.ScreenToLocalBoxXf().Scale);
marqueeDown = (e: React.PointerEvent) => {
- if (!this.dataDoc[this.fieldKey]) return this.chooseImage();
- if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) && this._props.isContentActive() && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
+ if (!this.dataDoc[this.fieldKey]) {
+ this.chooseImage();
+ } else if (
+ !e.altKey &&
+ e.button === 0 &&
+ NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) &&
+ this._props.isContentActive() &&
+ ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)
+ ) {
setupMoveUpEvents(
this,
e,
@@ -419,7 +458,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
className="imageBox"
onContextMenu={this.specificContextMenu}
ref={this._mainCont}
- onScroll={action(e => {
+ onScroll={action(() => {
if (!this._forcedScroll) {
if (this.layoutDoc._layout_scrollTop || this._mainCont.current?.scrollTop) {
this._ignoreScroll = true;
@@ -444,8 +483,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
renderDepth={this._props.renderDepth + 1}
fieldKey={this.annotationKey}
styleProvider={this._props.styleProvider}
- isAnnotationOverlay={true}
- annotationLayerHostsContent={true}
+ isAnnotationOverlay
+ annotationLayerHostsContent
PanelWidth={this._props.PanelWidth}
PanelHeight={this._props.PanelHeight}
ScreenToLocalTransform={this.screenToLocalTransform}
@@ -476,7 +515,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
selectionText={returnEmptyString}
annotationLayer={this._annotationLayer.current}
marqueeContainer={this._mainCont.current}
- highlightDragSrcColor={''}
+ highlightDragSrcColor=""
anchorMenuCrop={this.crop}
/>
)}
@@ -489,7 +528,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
input.type = 'file';
input.multiple = true;
input.accept = 'image/*';
- input.onchange = async _e => {
+ input.onchange = async () => {
const file = input.files?.[0];
if (file) {
const disposer = OverlayView.ShowSpinner();
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 31a2367fc..74773b244 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -1,8 +1,8 @@
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnAlways, returnTrue } from '../../../Utils';
-import { Doc, Field, FieldResult } from '../../../fields/Doc';
+import { returnAlways, returnTrue } from '../../../ClientUtils';
+import { Doc, Field, FieldType, FieldResult } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { RichTextField } from '../../../fields/RichTextField';
import { ComputedField, ScriptField } from '../../../fields/ScriptField';
@@ -96,15 +96,15 @@ export class KeyValueBox extends ObservableReactComponent<FieldViewProps> {
public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean, setResult?: (value: FieldResult) => void) {
const { script, type, onDelegate } = kvpScript;
- //const target = onDelegate ? Doc.Layout(doc.layout) : Doc.GetProto(doc); // bcz: TODO need to be able to set fields on layout templates
+ // const target = onDelegate ? Doc.Layout(doc.layout) : Doc.GetProto(doc); // bcz: TODO need to be able to set fields on layout templates
const target = forceOnDelegate || onDelegate || key.startsWith('_') ? doc : DocCast(doc.proto, doc);
- let field: Field | undefined;
+ let field: FieldType | undefined;
switch (type) {
case 'computed': field = new ComputedField(script); break; // prettier-ignore
case 'script': field = new ScriptField(script); break; // prettier-ignore
default: {
const _setCacheResult_ = (value: FieldResult) => {
- field = value as Field;
+ field = value as FieldType;
if (setResult) setResult?.(value);
else target[key] = field;
};
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index f9e8ce4f3..c3afc198d 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -2,7 +2,8 @@ import { Tooltip } from '@mui/material';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc, Field } from '../../../fields/Doc';
import { DocCast } from '../../../fields/Types';
import { DocumentOptions, FInfo } from '../../documents/Documents';
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 74e78c671..d1c8c62ed 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -1,21 +1,21 @@
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCast, Field } from '../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
+import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { undoBatch } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxBaseComponent } from '../DocComponent';
+import { PinProps, ViewBoxBaseComponent } from '../DocComponent';
import { StyleProp } from '../StyleProvider';
import { FieldView, FieldViewProps } from './FieldView';
import BigText from './LabelBigText';
import './LabelBox.scss';
-import { PinProps, PresBox } from './trails';
-import { Docs } from '../../documents/Documents';
+import { PresBox } from './trails';
@observer
export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -41,7 +41,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
@computed get Title() {
- return Field.toString(this.dataDoc[this.fieldKey] as Field) || StrCast(this.Document.title);
+ return Field.toString(this.dataDoc[this.fieldKey] as FieldType) || StrCast(this.Document.title);
}
protected createDropTarget = (ele: HTMLDivElement) => {
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index ff1e62885..0155defb7 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -1,11 +1,13 @@
import { action, computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, emptyFunction, setupMoveUpEvents } from '../../../Utils';
+import { setupMoveUpEvents } from '../../../ClientUtils';
+import { Utils, emptyFunction } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
import { NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { LinkFollower } from '../../util/LinkFollower';
import { SelectionManager } from '../../util/SelectionManager';
import { ViewBoxBaseComponent } from '../DocComponent';
@@ -39,7 +41,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
onPointerDown = (e: React.PointerEvent) => {
- const linkSource = this.linkSource;
+ const { linkSource } = this;
linkSource &&
setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, (e, doubleTap) => {
if (doubleTap) LinkFollower.FollowLink(this.Document, linkSource, false);
@@ -58,11 +60,10 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
dragData.dropPropertiesToRemove = ['link_anchor_1_x', 'link_anchor_1_y', 'link_anchor_2_x', 'link_anchor_2_y', 'onClick'];
DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]);
return true;
- } else {
- this.layoutDoc[this.fieldKey + '_x'] = ((pt[0] - bounds.left) / bounds.width) * 100;
- this.layoutDoc[this.fieldKey + '_y'] = ((pt[1] - bounds.top) / bounds.height) * 100;
- this.layoutDoc.link_autoMoveAnchors = false;
}
+ this.layoutDoc[this.fieldKey + '_x'] = ((pt[0] - bounds.left) / bounds.width) * 100;
+ this.layoutDoc[this.fieldKey + '_y'] = ((pt[1] - bounds.top) / bounds.height) * 100;
+ this.layoutDoc.link_autoMoveAnchors = false;
}
return false;
});
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 3a2509c3d..2593491cc 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -2,12 +2,13 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti
import { observer } from 'mobx-react';
import * as React from 'react';
import Xarrow from 'react-xarrows';
+import { DashColor, lightOrDark, returnFalse } from '../../../ClientUtils';
import { FieldResult } from '../../../fields/Doc';
import { DocCss, DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { DocCast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { DashColor, emptyFunction, lightOrDark, returnFalse } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { DocumentManager } from '../../util/DocumentManager';
import { SnappingManager } from '../../util/SnappingManager';
import { ViewBoxBaseComponent } from '../DocComponent';
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index c9c8f9260..539daf0bd 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -4,7 +4,8 @@ import { action, computed, makeObservable, observable, runInAction } from 'mobx'
import { observer } from 'mobx-react';
import * as React from 'react';
import wiki from 'wikijs';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types';
import { DocServer } from '../../DocServer';
diff --git a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
index 7e99795b5..fe7f8d8b3 100644
--- a/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/DirectionsAnchorMenu.tsx
@@ -4,7 +4,8 @@ import { IconButton } from 'browndash-components';
import { IReactionDisposer, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnFalse, unimplementedFunction } from '../../../../Utils';
+import { returnFalse } from '../../../../ClientUtils';
+import { unimplementedFunction } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { SelectionManager } from '../../../util/SelectionManager';
diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
index 08bea5d9d..d17c4298c 100644
--- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
@@ -7,7 +7,8 @@ import { IReactionDisposer, ObservableMap, action, makeObservable, observable, r
import { observer } from 'mobx-react';
import * as React from 'react';
import { CirclePicker, ColorResult } from 'react-color';
-import { returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../../Utils';
+import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
+import { unimplementedFunction } from '../../../../Utils';
import { Doc, Opt } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { CalendarManager } from '../../../util/CalendarManager';
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index b73898f59..7855f8fe8 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -12,7 +12,8 @@ import * as React from 'react';
import { CirclePicker, ColorResult } from 'react-color';
import { Layer, MapProvider, MapRef, Map as MapboxMap, Marker, Source, ViewState, ViewStateChangeEvent } from 'react-map-gl';
import { MarkerEvent } from 'react-map-gl/dist/esm/types';
-import { Utils, emptyFunction, setupMoveUpEvents } from '../../../../Utils';
+import { ClientUtils, setupMoveUpEvents } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc';
import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { DocumentType } from '../../../documents/DocumentTypes';
@@ -22,14 +23,14 @@ import { DragManager } from '../../../util/DragManager';
import { LinkManager } from '../../../util/LinkManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { UndoManager, undoable } from '../../../util/UndoManager';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
import { SidebarAnnos } from '../../SidebarAnnos';
import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
import { Colors } from '../../global/globalEnums';
import { DocumentView } from '../DocumentView';
import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView';
import { FormattedTextBox } from '../formattedText/FormattedTextBox';
-import { PinProps, PresBox } from '../trails';
+import { PresBox } from '../trails';
import { fastSpeedIcon, mediumSpeedIcon, slowSpeedIcon } from './AnimationSpeedIcons';
import { AnimationSpeed, AnimationStatus, AnimationUtility } from './AnimationUtility';
import { MapAnchorMenu } from './MapAnchorMenu';
@@ -401,8 +402,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth();
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop));
- transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter];
- opaqueFilter = () => [...this._props.childFilters(), Utils.OpaqueBackgroundFilter];
+ transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter];
+ opaqueFilter = () => [...this._props.childFilters(), ClientUtils.OpaqueBackgroundFilter];
infoWidth = () => this._props.PanelWidth() / 5;
infoHeight = () => this._props.PanelHeight() / 5;
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
diff --git a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
index 3eb051dbf..e857ef722 100644
--- a/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
+++ b/src/client/views/nodes/MapboxMapBox/MapboxContainer.tsx
@@ -4,9 +4,11 @@ import { IReactionDisposer, ObservableMap, action, computed, makeObservable, obs
import { observer } from 'mobx-react';
import * as React from 'react';
import { MapProvider, Map as MapboxMap } from 'react-map-gl';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents } from '../../../../Utils';
-import { Doc, DocListCast, Field, LinkedTo, Opt } from '../../../../fields/Doc';
+import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
+import { emptyFunction } from '../../../../Utils';
+import { Doc, DocListCast, LinkedTo, Opt } from '../../../../fields/Doc';
import { DocCss, Highlight } from '../../../../fields/DocSymbols';
+import { Id } from '../../../../fields/FieldSymbols';
import { DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { DocumentType } from '../../../documents/DocumentTypes';
import { DocUtils, Docs } from '../../../documents/Documents';
@@ -16,15 +18,15 @@ import { LinkManager } from '../../../util/LinkManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { UndoManager, undoable } from '../../../util/UndoManager';
-import { ViewBoxAnnotatableComponent } from '../../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent } from '../../DocComponent';
import { SidebarAnnos } from '../../SidebarAnnos';
import { MarqueeOptionsMenu } from '../../collections/collectionFreeForm';
import { Colors } from '../../global/globalEnums';
import { DocumentView } from '../DocumentView';
-import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView';
+import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView';
import { MapAnchorMenu } from '../MapBox/MapAnchorMenu';
import { FormattedTextBox } from '../formattedText/FormattedTextBox';
-import { PinProps, PresBox } from '../trails';
+import { PresBox } from '../trails';
import './MapBox.scss';
/**
@@ -268,7 +270,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
sidebarDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.sidebarMove, emptyFunction, () => setTimeout(this.toggleSidebar), true);
};
- sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => {
+ sidebarMove = (e: PointerEvent) => {
const bounds = this._ref.current!.getBoundingClientRect();
this.layoutDoc._layout_sidebarWidthPercent = '' + 100 * Math.max(0, 1 - (e.clientX - bounds.left) / bounds.width) + '%';
this.layoutDoc._layout_showSidebar = this.layoutDoc._layout_sidebarWidthPercent !== '0%';
@@ -276,7 +278,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
return false;
};
- setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => (this._setPreviewCursor = func);
+ setPreviewCursor = (func?: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => {
+ this._setPreviewCursor = func;
+ };
addDocumentWrapper = (doc: Doc | Doc[], annotationKey?: string) => this.addDocument(doc, annotationKey);
@@ -285,8 +289,8 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1) - this.sidebarWidth();
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop));
- transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter];
- opaqueFilter = () => [...this._props.childFilters(), Utils.OpaqueBackgroundFilter];
+ transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter];
+ opaqueFilter = () => [...this._props.childFilters(), ClientUtils.OpaqueBackgroundFilter];
infoWidth = () => this._props.PanelWidth() / 5;
infoHeight = () => this._props.PanelHeight() / 5;
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
@@ -306,11 +310,11 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
// center: new this.MicrosoftMaps.Location(loc.latitude, loc.longitude),
// });
//
- bingGeocode = (map: any, query: string) => {
- return new Promise<{ latitude: number; longitude: number }>((res, reject) => {
- //If search manager is not defined, load the search module.
+ bingGeocode = (map: any, query: string) =>
+ new Promise<{ latitude: number; longitude: number }>((res, reject) => {
+ // If search manager is not defined, load the search module.
if (!this._bingSearchManager) {
- //Create an instance of the search manager and call the geocodeQuery function again.
+ // Create an instance of the search manager and call the geocodeQuery function again.
this.MicrosoftMaps.loadModule('Microsoft.Maps.Search', () => {
this._bingSearchManager = new this.MicrosoftMaps.Search.SearchManager(map.current);
res(this.bingGeocode(map, query));
@@ -319,11 +323,10 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
this._bingSearchManager.geocode({
where: query,
callback: action((r: any) => res(r.results[0].location)),
- errorCallback: (e: any) => reject(),
+ errorCallback: () => reject(),
});
}
});
- };
@observable
bingSearchBarContents: any = this.Document.map; // For Bing Maps: The contents of the Bing search bar (string)
@@ -368,7 +371,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
this._bingMap.current.entities.remove(this.map_docToPinMap.get(temp));
}
const newpin = new this.MicrosoftMaps.Pushpin(new this.MicrosoftMaps.Location(temp.latitude, temp.longitude));
- this.MicrosoftMaps.Events.addHandler(newpin, 'click', (e: any) => this.pushpinClicked(temp as Doc));
+ this.MicrosoftMaps.Events.addHandler(newpin, 'click', () => this.pushpinClicked(temp as Doc));
if (!this._unmounting) {
this._bingMap.current.entities.push(newpin);
}
@@ -383,7 +386,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
this.toggleSidebar();
options.didMove = true;
}
- return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
+ return new Promise<Opt<DocumentView>>(res => {
+ DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ });
};
/*
* Pushpin onclick
@@ -418,7 +423,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
* Map OnClick
*/
@action
- mapOnClick = (e: { location: { latitude: any; longitude: any } }) => {
+ mapOnClick = (/* e: { location: { latitude: any; longitude: any } } */) => {
this._props.select(false);
this.deselectPin();
};
@@ -442,22 +447,23 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
* Updates maptype
*/
@action
- updateMapType = () => (this.dataDoc.map_type = this._bingMap.current.getMapTypeId());
+ updateMapType = () => {
+ this.dataDoc.map_type = this._bingMap.current.getMapTypeId();
+ };
/*
* For Bing Maps
* Called by search button's onClick
* Finds the geocode of the searched contents and sets location to that location
- **/
+ * */
@action
- bingSearch = () => {
- return this.bingGeocode(this._bingMap, this.bingSearchBarContents).then(location => {
+ bingSearch = () =>
+ this.bingGeocode(this._bingMap, this.bingSearchBarContents).then(location => {
this.dataDoc.latitude = location.latitude;
this.dataDoc.longitude = location.longitude;
this.dataDoc.map_zoom = this._bingMap.current.getZoom();
this.dataDoc.map = this.bingSearchBarContents;
});
- };
/*
* Returns doc w/ relevant info
@@ -502,7 +508,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
this._bingMap.current.entities.push(pushPin);
- this.MicrosoftMaps.Events.addHandler(pushPin, 'click', (e: any) => this.pushpinClicked(pin));
+ this.MicrosoftMaps.Events.addHandler(pushPin, 'click', () => this.pushpinClicked(pin));
// this.MicrosoftMaps.Events.addHandler(pushPin, 'dblclick', (e: any) => this.pushpinDblClicked(pushPin, pin));
this.map_docToPinMap.set(pin, pushPin);
};
@@ -591,7 +597,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
};
@action
- searchbarOnEdit = (newText: string) => (this.bingSearchBarContents = newText);
+ searchbarOnEdit = (newText: string) => {
+ this.bingSearchBarContents = newText;
+ };
recolorPin = (pin: Doc, color?: string) => {
this._bingMap.current.entities.remove(this.map_docToPinMap.get(pin));
@@ -620,7 +628,9 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
this._disposers.mapLocation = reaction(
() => this.Document.map,
- mapLoc => (this.bingSearchBarContents = mapLoc),
+ mapLoc => {
+ this.bingSearchBarContents = mapLoc;
+ },
{ fireImmediately: true }
);
this._disposers.highlight = reaction(
@@ -720,6 +730,7 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
MapBoxContainer._rerenderDelay = 0;
}
this._rerenderTimeout = undefined;
+ // eslint-disable-next-line operator-assignment
this.Document[DocCss] = this.Document[DocCss] + 1;
}), MapBoxContainer._rerenderDelay);
return null;
@@ -752,18 +763,19 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="magnifying-glass" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" color="#DFDFDF">
<path
fill="currentColor"
- d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"></path>
+ d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"
+ />
</svg>
}
onClick={this.bingSearch}
type={Type.TERT}
/>
<div style={{ width: 30, height: 30 }} ref={this._dragRef} onPointerDown={this.dragToggle}>
- <Button tooltip="drag to place a pushpin" icon={<FontAwesomeIcon size={'lg'} icon={'bullseye'} />} />
+ <Button tooltip="drag to place a pushpin" icon={<FontAwesomeIcon size="lg" icon="bullseye" />} />
</div>
</div>
<MapProvider>
- <MapboxMap id="mabox-map" mapStyle={`mapbox://styles/mapbox/streets-v9`} mapboxAccessToken={mapboxApiKey} />
+ <MapboxMap id="mabox-map" mapStyle="mapbox://styles/mapbox/streets-v9" mapboxAccessToken={mapboxApiKey} />
</MapProvider>
{/*
@@ -782,7 +794,8 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
.filter(anno => !anno.layout_unrendered)
.map((pushpin, i) => (
<DocumentView
- key={i}
+ key={pushpin[Id]}
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
renderDepth={this._props.renderDepth + 1}
Document={pushpin}
@@ -821,12 +834,13 @@ export class MapBoxContainer extends ViewBoxAnnotatableComponent<FieldViewProps>
<div className="mapBox-sidebar" style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
<SidebarAnnos
ref={this._sidebarRef}
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
fieldKey={this.fieldKey}
Document={this.Document}
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
- usePanelWidth={true}
+ usePanelWidth
showSidebar={this.SidebarShown}
nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 1274220b6..8140c0ca7 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -4,6 +4,7 @@ import { observer } from 'mobx-react';
import * as Pdfjs from 'pdfjs-dist';
import 'pdfjs-dist/web/pdf_viewer.css';
import * as React from 'react';
+import { ClientUtils, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
@@ -12,7 +13,7 @@ import { ComputedField } from '../../../fields/ScriptField';
import { Cast, FieldValue, ImageCast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField, PdfField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnFalse, setupMoveUpEvents, Utils } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
@@ -23,16 +24,16 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm';
import { CollectionStackingView } from '../collections/CollectionStackingView';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { Colors } from '../global/globalEnums';
import { CreateImage } from '../nodes/WebBoxRenderer';
import { PDFViewer } from '../pdf/PDFViewer';
import { SidebarAnnos } from '../SidebarAnnos';
import { DocumentView, OpenWhere } from './DocumentView';
-import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView';
+import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView';
import { ImageBox } from './ImageBox';
import './PDFBox.scss';
-import { PinProps, PresBox } from './trails';
+import { PresBox } from './trails';
@observer
export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -128,9 +129,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
croppingProto.type = DocumentType.IMG;
croppingProto.layout = ImageBox.LayoutString('data');
- croppingProto.data = new ImageField(Utils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png'));
- croppingProto['data_nativeWidth'] = anchw;
- croppingProto['data_nativeHeight'] = anchh;
+ croppingProto.data = new ImageField(ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png'));
+ croppingProto.data_nativeWidth = anchw;
+ croppingProto.data_nativeHeight = anchh;
if (addCrop) {
DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
}
@@ -146,8 +147,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
(NumCast(region.x) * this._props.PanelWidth()) / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']),
4
)
- .then((data_url: any) => {
- Utils.convertDataUri(data_url, region[Id]).then(returnedfilename =>
+ .then((dataUrl: any) => {
+ ClientUtils.convertDataUri(dataUrl, region[Id]).then(returnedfilename =>
setTimeout(
action(() => {
croppingProto.data = new ImageField(returnedfilename);
@@ -182,8 +183,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
(iconFile: string, nativeWidth: number, nativeHeight: number) => {
setTimeout(() => {
this.dataDoc.icon = new ImageField(iconFile);
- this.dataDoc['icon_nativeWidth'] = nativeWidth;
- this.dataDoc['icon_nativeHeight'] = nativeHeight;
+ this.dataDoc.icon_nativeWidth = nativeWidth;
+ this.dataDoc.icon_nativeHeight = nativeHeight;
}, 500);
}
);
@@ -231,11 +232,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
options.didMove = true;
this.toggleSidebar(false);
}
- return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv)));
+ return new Promise<Opt<DocumentView>>(res => {
+ DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv));
+ });
};
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
- let ele: Opt<HTMLDivElement> = undefined;
+ let ele: Opt<HTMLDivElement>;
if (this._pdfViewer?.selectionContent()) {
ele = document.createElement('div');
ele.append(this._pdfViewer.selectionContent()!);
@@ -451,7 +454,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
!options && ContextMenu.Instance.addItem({ description: 'Options...', subitems: optionItems, icon: 'asterisk' });
const help = cm.findByDescription('Help...');
const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
- helpItems.push({ description: 'Copy path', event: () => this.pdfUrl && Utils.CopyText(Utils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' });
+ helpItems.push({ description: 'Copy path', event: () => this.pdfUrl && ClientUtils.CopyText(ClientUtils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' });
!help && ContextMenu.Instance.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'asterisk' });
};
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 1f976f926..40199cce1 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -11,17 +11,18 @@ import { Upload } from '../../../../server/SharedMediaTypes';
import { DocumentType } from '../../../documents/DocumentTypes';
import { Docs } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../../util/DragManager';
+import { DragManager } from '../../../util/DragManager';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { Presentation } from '../../../util/TrackMovements';
import { undoBatch } from '../../../util/UndoManager';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm/CollectionFreeFormView';
-import { media_state } from '../AudioBox';
+import { mediaState } from '../AudioBox';
import { FieldView, FieldViewProps } from '../FieldView';
import { VideoBox } from '../VideoBox';
import { RecordingView } from './RecordingView';
import { DocData } from '../../../../fields/DocSymbols';
+import { dropActionType } from '../../../util/DropActionTypes';
@observer
export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -78,7 +79,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
}, 100);
//could break if recording takes too long to turn into videobox. If so, either increase time on setTimeout below or find diff place to do this
setTimeout(() => Doc.RemFromMyOverlay(remDoc), 1000);
- Doc.UserDoc().workspaceRecordingState = media_state.Paused;
+ Doc.UserDoc().workspaceRecordingState = mediaState.Paused;
Doc.AddDocToList(Doc.UserDoc(), 'workspaceRecordings', remDoc);
}
}
@@ -110,7 +111,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
RecordingBox.screengrabber = docView.ComponentView as RecordingBox;
RecordingBox.screengrabber.Record?.();
});
- Doc.UserDoc().workspaceRecordingState = media_state.Recording;
+ Doc.UserDoc().workspaceRecordingState = mediaState.Recording;
}
/**
@@ -150,7 +151,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (docView?.ComponentView instanceof VideoBox) {
docView.ComponentView.Play();
}
- Doc.UserDoc().workspaceReplayingState = media_state.Playing;
+ Doc.UserDoc().workspaceReplayingState = mediaState.Playing;
}
public static pauseWorkspaceReplaying(doc: Doc) {
@@ -159,7 +160,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (videoBox) {
videoBox.Pause();
}
- Doc.UserDoc().workspaceReplayingState = media_state.Paused;
+ Doc.UserDoc().workspaceReplayingState = mediaState.Paused;
}
public static stopWorkspaceReplaying(value: Doc) {
@@ -224,7 +225,7 @@ ScriptingGlobals.add(function getWorkspaceRecordings() {
return new List<any>(['Record Workspace', `Record Webcam`, ...DocListCast(Doc.UserDoc().workspaceRecordings)]);
});
ScriptingGlobals.add(function isWorkspaceRecording() {
- return Doc.UserDoc().workspaceRecordingState === media_state.Recording;
+ return Doc.UserDoc().workspaceRecordingState === mediaState.Recording;
});
ScriptingGlobals.add(function isWorkspaceReplaying() {
return Doc.UserDoc().workspaceReplayingState;
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index f7ed82643..9c05a3e94 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -4,7 +4,7 @@ import { IconContext } from 'react-icons';
import { FaCheckCircle } from 'react-icons/fa';
import { MdBackspace } from 'react-icons/md';
import { Upload } from '../../../../server/SharedMediaTypes';
-import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
+import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils';
import { Networking } from '../../../Network';
import { Presentation, TrackMovements } from '../../../util/TrackMovements';
import { ProgressBar } from './ProgressBar';
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 1e3933ac3..e29e47514 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -4,30 +4,31 @@ import * as React from 'react';
import { computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
// import { BufferAttribute, Camera, Vector2, Vector3 } from 'three';
+import { returnFalse, returnOne, returnZero } from '../../../ClientUtils';
+import { emptyFunction } from '../../../Utils';
import { DateField } from '../../../fields/DateField';
import { Doc } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { ComputedField } from '../../../fields/ScriptField';
import { Cast, DocCast, NumCast } from '../../../fields/Types';
import { AudioField, VideoField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils';
-import { DocUtils } from '../../documents/Documents';
-import { DocumentType } from '../../documents/DocumentTypes';
import { Networking } from '../../Network';
+import { DocumentType } from '../../documents/DocumentTypes';
+import { DocUtils } from '../../documents/Documents';
import { CaptureManager } from '../../util/CaptureManager';
import { SettingsManager } from '../../util/SettingsManager';
import { TrackMovements } from '../../util/TrackMovements';
-import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
-import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline';
import { ContextMenu } from '../ContextMenu';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
-import { media_state } from './AudioBox';
+import { CollectionStackedTimeline } from '../collections/CollectionStackedTimeline';
+import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
+import { mediaState } from './AudioBox';
import { FieldView, FieldViewProps } from './FieldView';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
import './ScreenshotBox.scss';
import { VideoBox } from './VideoBox';
-import { DocData } from '../../../fields/DocSymbols';
declare class MediaRecorder {
constructor(e: any, options?: any); // whatever MediaRecorder has
@@ -175,7 +176,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
ref={r => {
this._videoRef = r;
setTimeout(() => {
- if (this.layoutDoc.mediaState === media_state.PendingRecording && this._videoRef) {
+ if (this.layoutDoc.mediaState === mediaState.PendingRecording && this._videoRef) {
this.toggleRecording();
}
}, 100);
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 8c65fd34e..60d7e4b00 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -2,7 +2,7 @@ let ReactTextareaAutocomplete = require('@webscopeio/react-textarea-autocomplete
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnAlways, returnEmptyString } from '../../../Utils';
+import { returnAlways, returnEmptyString } from '../../../ClientUtils';
import { Doc } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { listSpec } from '../../../fields/Schema';
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 4773a21c9..60141b2a6 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -3,6 +3,7 @@ import { action, computed, IReactionDisposer, makeObservable, observable, Observ
import { observer } from 'mobx-react';
import { basename } from 'path';
import * as React from 'react';
+import { ClientUtils, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, Opt, StrListCast } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { InkTool } from '../../../fields/InkField';
@@ -10,11 +11,11 @@ import { List } from '../../../fields/List';
import { ObjectField } from '../../../fields/ObjectField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { AudioField, ImageField, VideoField } from '../../../fields/URLField';
-import { emptyFunction, formatTime, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils';
+import { emptyFunction, formatTime } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
-import { dropActionType } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
import { FollowLinkScript } from '../../util/LinkFollower';
import { LinkManager } from '../../util/LinkManager';
import { ReplayMovements } from '../../util/ReplayMovements';
@@ -23,14 +24,14 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec
import { CollectionStackedTimeline, TrimScope } from '../collections/CollectionStackedTimeline';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { AnchorMenu } from '../pdf/AnchorMenu';
import { StyleProp } from '../StyleProvider';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView';
import { RecordingBox } from './RecordingBox';
-import { PinProps, PresBox } from './trails';
+import { PresBox } from './trails';
import './VideoBox.scss';
/**
@@ -303,7 +304,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
const retitled = StrCast(this.Document.title).replace(/[ -\.:]/g, '');
const encodedFilename = encodeURIComponent(('snapshot' + retitled + '_' + (this.layoutDoc._layout_currentTimecode || 0).toString()).replace(/[\.\/\?\=]/g, '_'));
const filename = basename(encodedFilename);
- Utils.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && (cb ?? this.createSnapshotLink)(returnedFilename, downX, downY));
+ ClientUtils.convertDataUri(dataUrl, filename).then((returnedFilename: string) => returnedFilename && (cb ?? this.createSnapshotLink)(returnedFilename, downX, downY));
}
};
@@ -318,7 +319,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
// creates link for snapshot
createSnapshotLink = (imagePath: string, downX?: number, downY?: number) => {
- const url = !imagePath.startsWith('/') ? Utils.CorsProxy(imagePath) : imagePath;
+ const url = !imagePath.startsWith('/') ? ClientUtils.CorsProxy(imagePath) : imagePath;
const width = NumCast(this.layoutDoc._width) || 1;
const height = NumCast(this.layoutDoc._height);
const imageSnapshot = Docs.Create.ImageDocument(url, {
@@ -399,7 +400,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
canvas.getContext('2d')?.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, 100, 100);
const retitled = StrCast(this.Document.title).replace(/[ -\.:]/g, '');
const encodedFilename = encodeURIComponent('thumbnail' + retitled + '_' + video.currentTime.toString().replace(/\./, '_'));
- thumbnailPromises?.push(Utils.convertDataUri(canvas.toDataURL(), basename(encodedFilename), true));
+ thumbnailPromises?.push(ClientUtils.convertDataUri(canvas.toDataURL(), basename(encodedFilename), true));
const newTime = video.currentTime + video.duration / (VideoBox.numThumbnails - 1);
if (newTime < video.duration) {
video.currentTime = newTime;
@@ -480,7 +481,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
subitems.push({
description: 'Copy path',
event: () => {
- Utils.CopyText(url);
+ ClientUtils.CopyText(url);
},
icon: 'expand-arrows-alt',
});
@@ -644,7 +645,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
playFrom = (seekTimeInSeconds: number, endTime?: number, fullPlay: boolean = false) => {
clearTimeout(this._playRegionTimer);
this._playRegionTimer = undefined;
- if (Number.isNaN(this.player?.duration)) {
+ if (isNaN(this.player?.duration)) {
setTimeout(() => this.playFrom(seekTimeInSeconds, endTime), 500);
} else if (this.player) {
// trimBounds override requested playback bounds
@@ -806,7 +807,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() impl
marqueeOffset = () => [((this.panelWidth() / 2) * (1 - this.heightPercent / 100)) / (this.heightPercent / 100), 0];
- timelineDocFilter = () => [`_isTimelineLabel:true,${Utils.noRecursionHack}:x`];
+ timelineDocFilter = () => [`_isTimelineLabel:true,${ClientUtils.noRecursionHack}:x`];
// renders video controls
componentUI = (boundsLeft: number, boundsTop: number) => {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 033b01d24..446e83dd3 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -4,7 +4,8 @@ import { action, computed, IReactionDisposer, makeObservable, observable, Observ
import { observer } from 'mobx-react';
import * as React from 'react';
import * as WebRequest from 'web-request';
-import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, DivHeight, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils';
+import { Doc, DocListCast, Field, FieldType, Opt } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { HtmlField } from '../../../fields/HtmlField';
import { InkTool } from '../../../fields/InkField';
@@ -14,7 +15,7 @@ import { listSpec } from '../../../fields/Schema';
import { Cast, NumCast, StrCast, WebCast } from '../../../fields/Types';
import { ImageField, WebField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
-import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, emptyFunction, getWordAtPoint, lightOrDark, returnFalse, returnOne, returnZero, setupMoveUpEvents, smoothScroll, stringHash, Utils } from '../../../Utils';
+import { emptyFunction, stringHash, Utils } from '../../../Utils';
import { Docs, DocUtils } from '../../documents/Documents';
import { DocumentManager } from '../../util/DocumentManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
@@ -24,7 +25,7 @@ import { MarqueeOptionsMenu } from '../collections/collectionFreeForm';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { Colors } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { MarqueeAnnotator } from '../MarqueeAnnotator';
@@ -36,7 +37,7 @@ import { StyleProp } from '../StyleProvider';
import { DocumentView, OpenWhere } from './DocumentView';
import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView';
import { LinkInfo } from './LinkDocPreview';
-import { PinProps, PresBox } from './trails';
+import { PresBox } from './trails';
import './WebBox.scss';
const { CreateImage } = require('./WebBoxRenderer');
const _global = (window /* browser */ || global) /* node */ as any;
@@ -143,7 +144,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const nativeHeight = (nativeWidth * this._props.PanelHeight()) / this._props.PanelWidth();
var htmlString = this._iframe.contentDocument && new XMLSerializer().serializeToString(this._iframe.contentDocument);
if (!htmlString) {
- htmlString = await (await fetch(Utils.CorsProxy(this.webField!.href))).text();
+ htmlString = await (await fetch(ClientUtils.CorsProxy(this.webField!.href))).text();
}
this.layoutDoc.thumb = undefined;
this.Document.thumbLockout = true; // lock to prevent multiple thumb updates.
@@ -219,7 +220,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
}
} // else it's an HTMLfield
} else if (this.webField && !this.dataDoc.text) {
- WebRequest.get(Utils.CorsProxy(this.webField.href)) //
+ WebRequest.get(ClientUtils.CorsProxy(this.webField.href)) //
.then(result => result && (this.dataDoc.text = htmlToText(result.content)));
}
@@ -254,7 +255,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const clientRects = selRange.getClientRects();
for (let i = 0; i < clientRects.length; i++) {
const rect = clientRects.item(i);
- const mainrect = this._url ? { translateX: 0, translateY: 0, scale: 1 } : Utils.GetScreenTransform(this._mainCont.current);
+ const mainrect = this._url ? { translateX: 0, translateY: 0, scale: 1 } : ClientUtils.GetScreenTransform(this._mainCont.current);
if (rect && rect.width !== this._mainCont.current.clientWidth) {
const annoBox = document.createElement('div');
annoBox.className = 'marqueeAnnotator-annotationBox';
@@ -283,7 +284,14 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
focus = (anchor: Doc, options: FocusViewOptions) => {
if (anchor !== this.Document && this._outerRef.current) {
const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
- const scrollTo = Utils.scrollIntoView(NumCast(anchor.y), NumCast(anchor._height), NumCast(this.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, Math.max(NumCast(anchor.y) + NumCast(anchor._height), this._scrollHeight));
+ const scrollTo = ClientUtils.scrollIntoView(
+ NumCast(anchor.y),
+ NumCast(anchor._height),
+ NumCast(this.layoutDoc._layout_scrollTop),
+ windowHeight,
+ windowHeight * 0.1,
+ Math.max(NumCast(anchor.y) + NumCast(anchor._height), this._scrollHeight)
+ );
if (scrollTo !== undefined) {
if (this._initialScroll === undefined) {
const focusTime = options.zoomTime ?? 500;
@@ -356,7 +364,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
this._textAnnotationCreator = undefined;
this.DocumentView?.()?.cleanupPointerEvents(); // pointerup events aren't generated on containing document view, so we have to invoke it here.
if (this._iframe?.contentWindow && this._iframe.contentDocument && !this._iframe.contentWindow.getSelection()?.isCollapsed) {
- const mainContBounds = Utils.GetScreenTransform(this._mainCont.current!);
+ const mainContBounds = ClientUtils.GetScreenTransform(this._mainCont.current!);
const scale = (this._props.NativeDimScaling?.() || 1) * mainContBounds.scale;
const sel = this._iframe.contentWindow.getSelection();
if (sel) {
@@ -491,7 +499,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
runInAction(() => this._warning++);
href = undefined;
}
- let requrlraw = decodeURIComponent(href?.replace(Utils.prepend('') + '/corsProxy/', '') ?? this._url.toString());
+ let requrlraw = decodeURIComponent(href?.replace(ClientUtils.prepend('') + '/corsProxy/', '') ?? this._url.toString());
if (requrlraw !== this._url.toString()) {
if (requrlraw.match(/q=.*&/)?.length && this._url.toString().match(/q=.*&/)?.length) {
const matches = requrlraw.match(/[^a-zA-z]q=[^&]*/g);
@@ -553,7 +561,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
const batch = UndoManager.StartBatch('webclick');
e.stopPropagation();
setTimeout(() => {
- this.setData(href.replace(Utils.prepend(''), origin));
+ this.setData(href.replace(ClientUtils.prepend(''), origin));
batch.end();
});
if (this._outerRef.current) {
@@ -698,7 +706,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
};
@action
- setData = (data: Field | Promise<RefField | undefined>) => {
+ setData = (data: FieldType | Promise<RefField | undefined>) => {
if (!(typeof data === 'string') && !(data instanceof WebField)) return false;
if (Field.toString(data) === this._url) return false;
this._scrollHeight = 0;
@@ -816,7 +824,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
);
}
if (field instanceof WebField) {
- const url = this.layoutDoc[this.fieldKey + '_useCors'] ? Utils.CorsProxy(this._webUrl) : this._webUrl;
+ const url = this.layoutDoc[this.fieldKey + '_useCors'] ? ClientUtils.CorsProxy(this._webUrl) : this._webUrl;
const scripts = this.dataDoc[this.fieldKey + '_allowScripts'] || this._webUrl.includes('wikipedia.org') || this._webUrl.includes('google.com') || this._webUrl.startsWith('https://bing');
//if (!scripts) console.log('No scripts for: ' + url);
return (
@@ -1081,8 +1089,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implem
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
scrollXf = () => this.ScreenToLocalBoxXf().translate(0, NumCast(this.layoutDoc._layout_scrollTop));
anchorMenuClick = () => this._sidebarRef.current?.anchorMenuClick;
- transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter];
- opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [Utils.OpaqueBackgroundFilter])];
+ transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter];
+ opaqueFilter = () => [...this._props.childFilters(), ClientUtils.noDragDocsFilter, ...(SnappingManager.CanEmbed ? [] : [ClientUtils.OpaqueBackgroundFilter])];
childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
if (doc instanceof Doc && property === StyleProp.PointerEvents) {
if (this.inlineTextAnnotations.includes(doc)) return 'none';
diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx
index 748c3322e..8577510e3 100644
--- a/src/client/views/nodes/calendarBox/CalendarBox.tsx
+++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx
@@ -4,7 +4,7 @@ import multiMonthPlugin from '@fullcalendar/multimonth';
import { makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { dateRangeStrToDates } from '../../../../Utils';
+import { dateRangeStrToDates } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { StrCast } from '../../../../fields/Types';
import { ViewBoxBaseComponent } from '../../DocComponent';
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 7335c9286..dee7d70bb 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -3,10 +3,11 @@ import { observer } from 'mobx-react';
import { NodeSelection } from 'prosemirror-state';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
+import { Utils } from '../../../../Utils';
+import { returnFalse } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { Height, Width } from '../../../../fields/DocSymbols';
import { NumCast } from '../../../../fields/Types';
-import { emptyFunction, returnFalse, Utils } from '../../../../Utils';
import { DocServer } from '../../../DocServer';
import { Docs, DocUtils } from '../../../documents/Documents';
import { Transform } from '../../../util/Transform';
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 439d4785e..eaa8fffaa 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -1,15 +1,17 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
-import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, trace } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
+import { NodeSelection } from 'prosemirror-state';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
+import { returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils';
import { Doc, DocListCast, Field } from '../../../../fields/Doc';
import { List } from '../../../../fields/List';
import { listSpec } from '../../../../fields/Schema';
import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
import { Cast, DocCast } from '../../../../fields/Types';
-import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction } from '../../../../Utils';
import { DocServer } from '../../../DocServer';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { Transform } from '../../../util/Transform';
@@ -21,8 +23,6 @@ import { ObservableReactComponent } from '../../ObservableReactComponent';
import { OpenWhere } from '../DocumentView';
import './DashFieldView.scss';
import { FormattedTextBox } from './FormattedTextBox';
-import { DocData } from '../../../../fields/DocSymbols';
-import { NodeSelection } from 'prosemirror-state';
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index a2db2a1cc..31252e0ab 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
@@ -12,8 +13,9 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from '
import { EditorView } from 'prosemirror-view';
import * as React from 'react';
import { BsMarkdownFill } from 'react-icons/bs';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, DivWidth, returnFalse, returnZero, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
import { DateField } from '../../../../fields/DateField';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkTool } from '../../../../fields/InkField';
@@ -23,14 +25,15 @@ import { RichTextField } from '../../../../fields/RichTextField';
import { ComputedField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, DateCast, DocCast, FieldValue, NumCast, RTFCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
-import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivWidth, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
+import { emptyFunction, numberRange, unimplementedFunction, Utils } from '../../../../Utils';
import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT';
import { DocServer } from '../../../DocServer';
import { Docs, DocUtils } from '../../../documents/Documents';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { DictationManager } from '../../../util/DictationManager';
import { DocumentManager } from '../../../util/DocumentManager';
-import { DragManager, dropActionType } from '../../../util/DragManager';
+import { DragManager } from '../../../util/DragManager';
+import { dropActionType } from '../../../util/DropActionTypes';
import { MakeTemplate } from '../../../util/DropConverter';
import { LinkManager } from '../../../util/LinkManager';
import { RTFMarkup } from '../../../util/RTFMarkup';
@@ -42,18 +45,18 @@ import { CollectionStackingView } from '../../collections/CollectionStackingView
import { CollectionTreeView } from '../../collections/CollectionTreeView';
import { ContextMenu } from '../../ContextMenu';
import { ContextMenuProps } from '../../ContextMenuItem';
-import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
+import { PinProps, ViewBoxAnnotatableComponent, ViewBoxInterface } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { LightboxView } from '../../LightboxView';
import { AnchorMenu } from '../../pdf/AnchorMenu';
import { GPTPopup } from '../../pdf/GPTPopup/GPTPopup';
import { SidebarAnnos } from '../../SidebarAnnos';
-import { StyleProp } from '../../StyleProvider';
-import { media_state } from '../AudioBox';
+import { styleFromLayoutString, StyleProp } from '../../StyleProvider';
+import { mediaState } from '../AudioBox';
import { DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView';
import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView';
import { LinkInfo } from '../LinkDocPreview';
-import { PinProps, PresBox } from '../trails';
+import { PresBox } from '../trails';
import { DashDocCommentView } from './DashDocCommentView';
import { DashDocView } from './DashDocView';
import { DashFieldView } from './DashFieldView';
@@ -152,10 +155,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
return this.titleHeight + NumCast(this.layoutDoc._layout_autoHeightMargins);
}
@computed get _recordingDictation() {
- return this.dataDoc?.mediaState === media_state.Recording;
+ return this.dataDoc?.mediaState === mediaState.Recording;
}
set _recordingDictation(value) {
- !this.dataDoc[`${this.fieldKey}_recordingSource`] && (this.dataDoc.mediaState = value ? media_state.Recording : undefined);
+ !this.dataDoc[`${this.fieldKey}_recordingSource`] && (this.dataDoc.mediaState = value ? mediaState.Recording : undefined);
}
@computed get config() {
this._keymap = buildKeymap(schema, this._props);
@@ -275,7 +278,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
anchor.followLinkAudio = true;
let stopFunc: any;
const targetData = target[DocData];
- targetData.mediaState = media_state.Recording;
+ targetData.mediaState = mediaState.Recording;
DocumentViewInternal.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => (stopFunc = stop));
const reactionDisposer = reaction(
() => target.mediaState,
@@ -313,7 +316,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
});
const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
this._props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom);
- let ele: Opt<HTMLDivElement> = undefined;
+ let ele: Opt<HTMLDivElement>;
try {
const contents = window.getSelection()?.getRangeAt(0).cloneContents();
if (contents) {
@@ -330,7 +333,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const fieldKey = StrCast(node.attrs.fieldKey);
return (
(node.attrs.hideKey ? '' : fieldKey + ':') + //
- (node.attrs.hideValue ? '' : Field.toJavascriptString(refDoc[fieldKey] as Field))
+ (node.attrs.hideValue ? '' : Field.toJavascriptString(refDoc[fieldKey] as FieldType))
);
}
return '';
@@ -345,8 +348,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
tryUpdateDoc = (force: boolean) => {
if (this._editorView && (this._editorView as any).docView) {
- const state = this._editorView.state;
- const dataDoc = this.dataDoc;
+ const { state } = this._editorView;
+ const { dataDoc } = this;
const newText = state.doc.textBetween(0, state.doc.content.size, ' \n', this.leafText);
const newJson = JSON.stringify(state.toJSON());
const prevData = Cast(this.layoutDoc[this.fieldKey], RichTextField, null); // the actual text in the text box
@@ -386,7 +389,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
} else {
// if we've deleted all the text in a note driven by a template, then restore the template data
dataDoc[this.fieldKey] = undefined;
- this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(((layoutData !== prevData ? layoutData : undefined) ?? protoData).Data)));
+ this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(((layoutData !== prevData ? layoutData : undefined) ?? protoData)?.Data)));
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, text: newText });
unchanged = false;
}
@@ -417,7 +420,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
let link;
LinkManager.Links(this.dataDoc).forEach((l, i) => {
const anchor = (l.link_anchor_1 as Doc).annotationOn ? (l.link_anchor_1 as Doc) : (l.link_anchor_2 as Doc).annotationOn ? (l.link_anchor_2 as Doc) : undefined;
- if (anchor && (anchor.annotationOn as Doc).mediaState === media_state.Recording) {
+ if (anchor && (anchor.annotationOn as Doc).mediaState === mediaState.Recording) {
linkTime = NumCast(anchor._timecodeToShow /* audioStart */);
linkAnchor = anchor;
link = l;
@@ -426,7 +429,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
if (this._editorView && linkTime) {
const state = this._editorView.state;
const now = Date.now();
- let mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(now / 1000) });
+ let mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(now / 1000) });
if (!this._break && state.selection.to !== state.selection.from) {
for (let i = state.selection.from; i <= state.selection.to; i++) {
const pos = state.doc.resolve(i);
@@ -507,7 +510,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
hyperlinkTerm = (tr: any, target: Doc, newAutoLinks: Set<Doc>) => {
const editorView = this._editorView;
if (editorView && (editorView as any).docView && !Doc.AreProtosEqual(target, this.Document)) {
- const autoLinkTerm = Field.toString(target.title as Field).replace(/^@/, '');
+ const autoLinkTerm = Field.toString(target.title as FieldType).replace(/^@/, '');
var alink: Doc | undefined;
this.findInNode(editorView, editorView.state.doc, autoLinkTerm).forEach(sel => {
if (
@@ -587,7 +590,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
};
adoptAnnotation = (start: number, end: number, mark: Mark) => {
const view = this._editorView!;
- const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: Doc.CurrentUserEmail });
+ const nmark = view.state.schema.marks.user_mark.create({ ...mark.attrs, userid: ClientUtils.CurrentUserEmail });
view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark));
};
protected createDropTarget = (ele: HTMLDivElement) => {
@@ -726,7 +729,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-remote', { background: 'yellow' });
}
if (highlights.includes('My Text')) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + Doc.CurrentUserEmail.replace(/\./g, '').replace(/@/g, ''), { background: 'moccasin' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail.replace(/\./g, '').replace(/@/g, ''), { background: 'moccasin' });
}
if (highlights.includes('Todo Items')) {
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-todo', { outline: 'black solid 1px' });
@@ -745,12 +748,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UT-ignore', { 'font-size': '1' });
}
if (highlights.includes('By Recent Minute')) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + Doc.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
const min = Math.round(Date.now() / 1000 / 60);
numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-min-' + (min - i), { opacity: ((10 - i - 1) / 10).toString() }));
}
if (highlights.includes('By Recent Hour')) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + Doc.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-' + ClientUtils.CurrentUserEmail.replace('.', '').replace('@', ''), { opacity: '0.1' });
const hr = Math.round(Date.now() / 1000 / 60 / 60);
numberRange(10).map(i => addStyleSheetRule(FormattedTextBox._userStyleSheet, 'UM-hr-' + (hr - i), { opacity: ((10 - i - 1) / 10).toString() }));
}
@@ -1214,18 +1217,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
width => this.tryUpdateScrollHeight()
);
this._disposers.scrollHeight = reaction(
- () => ({ scrollHeight: this.scrollHeight, layout_autoHeight: this.layout_autoHeight, width: NumCast(this.layoutDoc._width) }),
- ({ width, scrollHeight, layout_autoHeight }) => width && layout_autoHeight && this.resetNativeHeight(scrollHeight),
+ () => ({ scrollHeight: this.scrollHeight, layoutAutoHeight: this.layout_autoHeight, width: NumCast(this.layoutDoc._width) }),
+ ({ width, scrollHeight, layoutAutoHeight }) => width && layoutAutoHeight && this.resetNativeHeight(scrollHeight),
{ fireImmediately: true }
);
this._disposers.componentHeights = reaction(
// set the document height when one of the component heights changes and layout_autoHeight is on
- () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layout_autoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }),
- ({ sidebarHeight, textHeight, layout_autoHeight, marginsHeight }) => {
+ () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, layoutAutoHeight: this.layout_autoHeight, marginsHeight: this.layout_autoHeightMargins }),
+ ({ sidebarHeight, textHeight, layoutAutoHeight, marginsHeight }) => {
const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight));
if (
(!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this._props.isSelected()) && //
- layout_autoHeight &&
+ layoutAutoHeight &&
newHeight &&
newHeight !== this.layoutDoc.height &&
!this._props.dontRegisterView
@@ -1273,14 +1276,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this._disposers.search = reaction(
() => Doc.IsSearchMatch(this.Document),
search => (search ? this.highlightSearchTerms([Doc.SearchQuery()], search.searchMatch < 0) : this.unhighlightSearchTerms()),
- { fireImmediately: Doc.IsSearchMatchUnmemoized(this.Document) ? true : false }
+ { fireImmediately: !!Doc.IsSearchMatchUnmemoized(this.Document) }
);
this._disposers.selected = reaction(
() => this._props.rootSelected?.(),
action(selected => {
- //selected && setTimeout(() => this.prepareForTyping());
+ // selected && setTimeout(() => this.prepareForTyping());
if (FormattedTextBox._globalHighlights.has('Bold Text')) {
+ // eslint-disable-next-line operator-assignment
this.layoutDoc[DocCss] = this.layoutDoc[DocCss] + 1; // css change happens outside of mobx/react, so this will notify anyone interested in the layout that it has changed
}
if (RichTextMenu.Instance?.view === this._editorView && !selected) {
@@ -1321,10 +1325,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
clipboardTextSerializer = (slice: Slice): string => {
- let text = '',
- separated = true;
- const from = 0,
- to = slice.content.size;
+ let text = '';
+ let separated = true;
+ const from = 0;
+ const to = slice.content.size;
slice.content.nodesBetween(
from,
to,
@@ -1346,7 +1350,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
handlePaste = (view: EditorView, event: Event, slice: Slice): boolean => {
const pdfAnchorId = (event as ClipboardEvent).clipboardData?.getData('dash/pdfAnchor');
- return pdfAnchorId && this.addPdfReference(pdfAnchorId) ? true : false;
+ return !!(pdfAnchorId && this.addPdfReference(pdfAnchorId));
};
addPdfReference = (pdfAnchorId: string) => {
@@ -1389,7 +1393,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const self = this;
return new Plugin({
view(newView) {
- runInAction(() => self._props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView));
+ runInAction(() => {
+ self._props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView);
+ });
return new RichTextMenuPlugin({ editorProps: this._props });
},
});
@@ -1414,7 +1420,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const shift = Math.min(topOff ?? Number.MAX_VALUE, botOff ?? Number.MAX_VALUE);
const scrollPos = scrollRef.scrollTop + shift * self.ScreenToLocalBoxXf().Scale;
if (this._focusSpeed !== undefined) {
- setTimeout(() => scrollPos && (this._scrollStopper = smoothScroll(this._focusSpeed || 0, scrollRef, scrollPos, 'ease', this._scrollStopper)));
+ setTimeout(() => {
+ scrollPos && (this._scrollStopper = smoothScroll(this._focusSpeed || 0, scrollRef, scrollPos, 'ease', this._scrollStopper));
+ });
} else {
scrollRef.scrollTo({ top: scrollPos });
}
@@ -1424,25 +1432,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
},
dispatchTransaction: this.dispatchTransaction,
nodeViews: {
- dashComment(node: any, view: any, getPos: any) {
- return new DashDocCommentView(node, view, getPos);
- },
- dashDoc(node: any, view: any, getPos: any) {
- return new DashDocView(node, view, getPos, self);
- },
- dashField(node: any, view: any, getPos: any) {
- return new DashFieldView(node, view, getPos, self);
- },
- equation(node: any, view: any, getPos: any) {
- return new EquationView(node, view, getPos, self);
- },
- summary(node: any, view: any, getPos: any) {
- return new SummaryView(node, view, getPos);
- },
- //ordered_list(node: any, view: any, getPos: any) { return new OrderedListView(); },
- footnote(node: any, view: any, getPos: any) {
- return new FootnoteView(node, view, getPos);
- },
+ dashComment(node: any, view: any, getPos: any) { return new DashDocCommentView(node, view, getPos); }, // prettier-ignore
+ dashDoc(node: any, view: any, getPos: any) { return new DashDocView(node, view, getPos, self); }, // prettier-ignore
+ dashField(node: any, view: any, getPos: any) { return new DashFieldView(node, view, getPos, self); }, // prettier-ignore
+ equation(node: any, view: any, getPos: any) { return new EquationView(node, view, getPos, self); }, // prettier-ignore
+ summary(node: any, view: any, getPos: any) { return new SummaryView(node, view, getPos); }, // prettier-ignore
+ footnote(node: any, view: any, getPos: any) { return new FootnoteView(node, view, getPos); }, // prettier-ignore
},
clipboardTextSerializer: this.clipboardTextSerializer,
handlePaste: this.handlePaste,
@@ -1450,7 +1445,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const { state, dispatch } = this._editorView;
if (!rtfField) {
const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
- const startupText = Field.toString(dataDoc[fieldKey] as Field);
+ const startupText = Field.toString(dataDoc[fieldKey] as FieldType);
if (startupText) {
dispatch(state.tr.insertText(startupText));
}
@@ -1474,7 +1469,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this._props.select(false);
if (selLoadChar) {
const $from = this._editorView.state.selection.anchor ? this._editorView.state.doc.resolve(this._editorView.state.selection.anchor - 1) : undefined;
- const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
+ const mark = schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
const curMarks = this._editorView.state.storedMarks ?? $from?.marksAcross(this._editorView.state.selection.$head) ?? [];
const storedMarks = [...curMarks.filter(m => m.type !== mark.type), mark];
const tr1 = this._editorView.state.tr.setStoredMarks(storedMarks);
@@ -1510,7 +1505,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily) })] : []),
...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize) })] : []),
...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []),
- ...[schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })],
+ ...[schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })],
];
this._editorView?.dispatch(this._editorView?.state.tr.setStoredMarks(docDefaultMarks));
};
@@ -1761,7 +1756,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
let stopPropagation = true;
for (var i = state.selection.from; i <= state.selection.to; i++) {
const node = state.doc.resolve(i);
- if (state.doc.content.size - 1 > i && node?.marks?.().some(mark => mark.type === schema.marks.user_mark && mark.attrs.userid !== Doc.CurrentUserEmail) && [AclAugment, AclSelfEdit].includes(GetEffectiveAcl(this.Document))) {
+ if (state.doc.content.size - 1 > i && node?.marks?.().some(mark => mark.type === schema.marks.user_mark && mark.attrs.userid !== ClientUtils.CurrentUserEmail) && [AclAugment, AclSelfEdit].includes(GetEffectiveAcl(this.Document))) {
e.preventDefault();
}
}
@@ -1781,11 +1776,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
this._editorView?.state.selection.empty && (stopPropagation = false);
break;
default:
- if (this._lastTimedMark?.attrs.userid === Doc.CurrentUserEmail) break;
+ if (this._lastTimedMark?.attrs.userid === ClientUtils.CurrentUserEmail) break;
case ' ':
if (e.code !== 'Space' && e.code !== 'Backspace') {
[AclEdit, AclAugment, AclAdmin].includes(GetEffectiveAcl(this.Document)) &&
- this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark).addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })));
+ this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark).addStoredMark(schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })));
}
break;
}
@@ -1892,7 +1887,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
Document={this.Document}
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
- usePanelWidth={true}
+ usePanelWidth
nativeWidth={NumCast(this.layoutDoc._nativeWidth)}
showSidebar={this.SidebarShown}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
@@ -2000,11 +1995,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
// if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
if (this._props.isContentActive()) {
const scale = this._props.NativeDimScaling?.() || 1;
- const styleFromLayoutString = Doc.styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._header_height}px' >
- const height = Number(styleFromLayoutString.height?.replace('px', ''));
+ const styleFromLayout = styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._header_height}px' >
+ const height = Number(styleFromLayout.height?.replace('px', ''));
// prevent default if selected || child is active but this doc isn't scrollable
if (
- !Number.isNaN(height) &&
+ !isNaN(height) &&
(this._scrollRef?.scrollHeight ?? 0) <= Math.ceil((height ? height : this._props.PanelHeight()) / scale) && //
(this._props.rootSelected?.() || this.isAnyChildContentActive())
) {
@@ -2033,15 +2028,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
setTimeout(() => !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide);
const paddingX = NumCast(this.layoutDoc._xMargin, this._props.xPadding || 0);
const paddingY = NumCast(this.layoutDoc._yMargin, this._props.yPadding || 0);
- const styleFromLayoutString = Doc.styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._header_height}px' >
- return styleFromLayoutString?.height === '0px' ? null : (
+ const styleFromLayout = styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._header_height}px' >
+ return styleFromLayout?.height === '0px' ? null : (
<div
className="formattedTextBox"
onPointerEnter={action(() => {
this._isHovering = true;
this.layoutDoc[`_${this._props.fieldKey}_usePath`] && (this.Document.isHovering = true);
})}
- onPointerLeave={action(() => (this.Document.isHovering = this._isHovering = false))}
+ onPointerLeave={action(() => { this.Document.isHovering = this._isHovering = false; })} // prettier-ignore
ref={r => {
this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel);
this._oldWheel = r;
@@ -2061,7 +2056,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
fontSize: this.fontSize,
fontFamily: this.fontFamily,
fontWeight: this.fontWeight,
- ...styleFromLayoutString,
+ ...styleFromLayout,
}}>
<div
className="formattedTextBox-cont"
@@ -2083,7 +2078,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
onDoubleClick={this.onDoubleClick}>
<div
className="formattedTextBox-outer"
- ref={r => (this._scrollRef = r)}
+ ref={r => {
+ this._scrollRef = r;
+ }}
style={{
width: this.noSidebar ? '100%' : `calc(100% - ${this.layout_sidebarWidthPercent})`,
overflow: this.layoutDoc._createDocOnCR ? 'hidden' : this.layoutDoc._layout_autoHeight ? 'visible' : undefined,
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index ce17af6ca..c0cb60c6d 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -1,15 +1,16 @@
import { Mark, ResolvedPos } from 'prosemirror-model';
-import { EditorState, NodeSelection } from 'prosemirror-state';
+import { EditorState } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
+import { ClientUtils } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { DocServer } from '../../../DocServer';
-import { LinkDocPreview, LinkInfo } from '../LinkDocPreview';
+import { LinkInfo } from '../LinkDocPreview';
import { FormattedTextBox } from './FormattedTextBox';
import './FormattedTextBoxComment.scss';
import { schema } from './schema_rts';
export function findOtherUserMark(marks: readonly Mark[]): Mark | undefined {
- return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
+ return marks.find(m => m.attrs.userid && m.attrs.userid !== ClientUtils.CurrentUserEmail);
}
export function findUserMark(marks: readonly Mark[]): Mark | undefined {
return marks.find(m => m.attrs.userid);
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index 03c902580..e9ed2549e 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -1,28 +1,28 @@
import { chainCommands, deleteSelection, exitCode, joinBackward, joinDown, joinUp, lift, newlineInCode, selectNodeBackward, setBlockType, splitBlockKeepMarks, toggleMark, wrapIn } from 'prosemirror-commands';
import { redo, undo } from 'prosemirror-history';
import { Schema } from 'prosemirror-model';
-import { splitListItem, wrapInList, sinkListItem, liftListItem } from 'prosemirror-schema-list';
+import { liftListItem, sinkListItem, splitListItem, wrapInList } from 'prosemirror-schema-list';
import { EditorState, NodeSelection, TextSelection, Transaction } from 'prosemirror-state';
import { liftTarget } from 'prosemirror-transform';
+import { EditorView } from 'prosemirror-view';
+import { ClientUtils } from '../../../../ClientUtils';
+import { Utils } from '../../../../Utils';
import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols';
import { GetEffectiveAcl } from '../../../../fields/util';
-import { Utils } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { RTFMarkup } from '../../../util/RTFMarkup';
import { SelectionManager } from '../../../util/SelectionManager';
import { OpenWhere } from '../DocumentView';
-import { Doc } from '../../../../fields/Doc';
-import { EditorView } from 'prosemirror-view';
const mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false;
export type KeyMap = { [key: string]: any };
-export let updateBullets = (tx2: Transaction, schema: Schema, assignedMapStyle?: string, from?: number, to?: number) => {
+export const updateBullets = (tx2: Transaction, schema: Schema, assignedMapStyle?: string, from?: number, to?: number) => {
let mapStyle = assignedMapStyle;
- tx2.doc.descendants((node: any, offset: any, index: any) => {
+ tx2.doc.descendants((node: any, offset: any /* , index: any */) => {
if ((from === undefined || to === undefined || (from <= offset + node.nodeSize && to >= offset)) && (node.type === schema.nodes.ordered_list || node.type === schema.nodes.list_item)) {
- const path = (tx2.doc.resolve(offset) as any).path;
+ const { path } = tx2.doc.resolve(offset) as any;
let depth = Array.from(path).reduce((p: number, c: any) => p + (c.hasOwnProperty('type') && c.type === schema.nodes.ordered_list ? 1 : 0), 0);
if (node.type === schema.nodes.ordered_list) {
if (depth === 0 && !assignedMapStyle) mapStyle = node.attrs.mapStyle;
@@ -49,23 +49,27 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
const canEdit = (state: any) => {
switch (GetEffectiveAcl(props.TemplateDataDocument)) {
case AclAugment:
- const prevNode = state.selection.$cursor.nodeBefore;
- const prevUser = !prevNode ? Doc.CurrentUserEmail : prevNode.marks[prevNode.marks.length - 1].attrs.userid;
- if (prevUser != Doc.CurrentUserEmail) {
- return false;
+ {
+ const prevNode = state.selection.$cursor.nodeBefore;
+ const prevUser = !prevNode ? ClientUtils.CurrentUserEmail : prevNode.marks[prevNode.marks.length - 1].attrs.userid;
+ if (prevUser !== ClientUtils.CurrentUserEmail) {
+ return false;
+ }
}
+ break;
+ default:
}
return true;
};
const toggleEditableMark = (mark: any) => (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && toggleMark(mark)(state, dispatch);
- //History commands
+ // History commands
bind('Mod-z', undo);
bind('Shift-Mod-z', redo);
!mac && bind('Mod-y', redo);
- //Commands to modify Mark
+ // Commands to modify Mark
bind('Mod-b', toggleEditableMark(schema.marks.strong));
bind('Mod-B', toggleEditableMark(schema.marks.strong));
@@ -77,7 +81,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
bind('Mod-u', toggleEditableMark(schema.marks.underline));
bind('Mod-U', toggleEditableMark(schema.marks.underline));
- //Commands for lists
+ // Commands for lists
bind('Ctrl-i', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && wrapInList(schema.nodes.ordered_list)(state as any, dispatch as any));
bind('Ctrl-Tab', () => (props.onKey?.(event, props) ? true : true));
@@ -103,8 +107,8 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
if (
!wrapInList(schema.nodes.ordered_list)(newstate.state as any, (tx2: Transaction) => {
const tx25 = updateBullets(tx2, schema);
- const ol_node = tx25.doc.nodeAt(range!.start)!;
- const tx3 = tx25.setNodeMarkup(range!.start, ol_node.type, ol_node.attrs, marks);
+ const olNode = tx25.doc.nodeAt(range!.start)!;
+ const tx3 = tx25.setNodeMarkup(range!.start, olNode.type, olNode.attrs, marks);
// when promoting to a list, assume list will format things so don't copy the stored marks.
marks && tx3.ensureMarks([...marks]);
marks && tx3.setStoredMarks([...marks]);
@@ -134,13 +138,13 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
}
});
- //Command to create a new Tab with a PDF of all the command shortcuts
+ // Command to create a new Tab with a PDF of all the command shortcuts
bind('Mod-/', (state: EditorState, dispatch: (tx: Transaction) => void) => {
- const newDoc = Docs.Create.PdfDocument(Utils.prepend('/assets/cheat-sheet.pdf'), { _width: 300, _height: 300 });
+ const newDoc = Docs.Create.PdfDocument(ClientUtils.prepend('/assets/cheat-sheet.pdf'), { _width: 300, _height: 300 });
props.addDocTab(newDoc, OpenWhere.addRight);
});
- //Commands to modify BlockType
+ // Commands to modify BlockType
bind('Ctrl->', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state && wrapIn(schema.nodes.blockquote)(state as any, dispatch as any)));
bind('Alt-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.paragraph)(state as any, dispatch as any));
bind('Shift-Ctrl-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.code_block)(state as any, dispatch as any));
@@ -156,11 +160,11 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
bind('Shift-Ctrl-' + i, (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && setBlockType(schema.nodes.heading, { level: i })(state as any, dispatch as any));
}
- //Command to create a horizontal break line
+ // Command to create a horizontal break line
const hr = schema.nodes.horizontal_rule;
bind('Mod-_', (state: EditorState, dispatch: (tx: Transaction) => void) => canEdit(state) && dispatch(state.tr.replaceSelectionWith(hr.create()).scrollIntoView()));
- //Command to unselect all
+ // Command to unselect all
bind('Escape', (state: EditorState, dispatch: (tx: Transaction) => void) => {
dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from)));
(document.activeElement as any).blur?.();
@@ -189,7 +193,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
});
bind('Cmd-]', (state: EditorState, dispatch: (tx: Transaction) => void) => {
const resolved = state.doc.resolve(state.selection.from) as any;
- const tr = state.tr;
+ const { tr } = state;
if (resolved?.parent.type.name === 'paragraph') {
tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks);
} else {
@@ -204,7 +208,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
});
bind('Cmd-\\', (state: EditorState, dispatch: (tx: Transaction) => void) => {
const resolved = state.doc.resolve(state.selection.from) as any;
- const tr = state.tr;
+ const { tr } = state;
if (resolved?.parent.type.name === 'paragraph') {
tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks);
} else {
@@ -219,7 +223,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
});
bind('Cmd-[', (state: EditorState, dispatch: (tx: Transaction) => void) => {
const resolved = state.doc.resolve(state.selection.from) as any;
- const tr = state.tr;
+ const { tr } = state;
if (resolved?.parent.type.name === 'paragraph') {
tr.setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks);
} else {
@@ -236,7 +240,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
bind('Cmd-f', (state: EditorState, dispatch: (tx: Transaction) => void) => {
const content = state.tr.selection.empty ? undefined : state.tr.selection.content().content.textBetween(0, state.tr.selection.content().size + 1);
const newNode = schema.nodes.footnote.create({}, content ? state.schema.text(content) : undefined);
- const tr = state.tr;
+ const { tr } = state;
tr.replaceSelectionWith(newNode); // replace insertion with a footnote.
dispatch(
tr.setSelection(
@@ -288,8 +292,8 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
};
bind('Backspace', backspace);
- //newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock
- //command to break line
+ // newlineInCode, createParagraphNear, liftEmptyBlock, splitBlock
+ // command to break line
const enter = (state: EditorState, dispatch: (tx: Transaction) => void, view: EditorView, once = true) => {
if (props.onKey?.(event, props)) return true;
@@ -356,7 +360,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
};
bind('Enter', enter);
- //Command to create a blank space
+ // Command to create a blank space
bind('Space', (state: EditorState, dispatch: (tx: Transaction) => void) => {
if (props.TemplateDataDocument && GetEffectiveAcl(props.TemplateDataDocument) != AclEdit && GetEffectiveAcl(props.TemplateDataDocument) != AclAugment && GetEffectiveAcl(props.TemplateDataDocument) != AclAdmin) return true;
return false;
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index cecf106a3..ec9c1a15d 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -3,7 +3,7 @@ import { Tooltip } from '@mui/material';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { lift, wrapIn } from 'prosemirror-commands';
-import { Mark, MarkType, Node as ProsNode, ResolvedPos } from 'prosemirror-model';
+import { Mark, MarkType } from 'prosemirror-model';
import { wrapInList } from 'prosemirror-schema-list';
import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 42665830f..78ea99592 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -1,5 +1,6 @@
import { ellipsis, emDash, InputRule, smartQuotes, textblockTypeInputRule } from 'prosemirror-inputrules';
import { NodeSelection, TextSelection } from 'prosemirror-state';
+import { ClientUtils } from '../../../../ClientUtils';
import { Doc, DocListCast, FieldResult, StrListCast } from '../../../../fields/Doc';
import { DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
@@ -48,13 +49,9 @@ export class RichTextRules {
/^A\.\s$/,
schema.nodes.ordered_list,
// match => {
- () => {
- return { mapStyle: 'multi', bulletStyle: 1 };
- // return ({ order: +match[1] })
- },
- (match: any, node: any) => {
- return node.childCount + node.attrs.order === +match[1];
- },
+ () => ({ mapStyle: 'multi', bulletStyle: 1 }),
+ // return ({ order: +match[1] })
+ (match: any, node: any) => node.childCount + node.attrs.order === +match[1],
((type: any) => ({ type: type, attrs: { mapStyle: 'multi', bulletStyle: 1 } })) as any
),
@@ -70,7 +67,7 @@ export class RichTextRules {
// ``` create code block
new InputRule(/^```$/, (state, match, start, end) => {
- let $start = state.doc.resolve(start);
+ const $start = state.doc.resolve(start);
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), schema.nodes.code_block)) return null;
// this enables text with code blocks to be used as a 'paint' function via a styleprovider button that is added to Docs that have an onPaint script
@@ -86,13 +83,13 @@ export class RichTextRules {
}),
// %<font-size> set the font size
- new InputRule(new RegExp(/%([0-9]+)\s$/), (state, match, start, end) => {
+ new InputRule(/%([0-9]+)\s$/, (state, match, start, end) => {
const size = Number(match[1]);
return state.tr.deleteRange(start, end).addStoredMark(schema.marks.pFontSize.create({ fontSize: size }));
}),
- //Create annotation to a field on the text document
- new InputRule(new RegExp(/>::$/), (state, match, start, end) => {
+ // Create annotation to a field on the text document
+ new InputRule(/>::$/, (state, match, start, end) => {
const creator = (doc: Doc) => {
const textDoc = this.Document[DocData];
const numInlines = NumCast(textDoc.inlineTextCount);
@@ -107,7 +104,7 @@ export class RichTextRules {
.insert(start, newNode)
.replaceRangeWith(start + 1, end + 2, dashDoc)
.insertText(' ', start + 2)
- .setStoredMarks([...node.marks, ...(sm ? sm : [])])
+ .setStoredMarks([...node.marks, ...(sm || [])])
: this.TextBox.EditorView.state.tr
);
};
@@ -117,8 +114,8 @@ export class RichTextRules {
return null;
}),
- //Create annotation to a field on the text document
- new InputRule(new RegExp(/>>$/), (state, match, start, end) => {
+ // Create annotation to a field on the text document
+ new InputRule(/>>$/, (state, match, start, end) => {
const textDoc = this.Document[DocData];
const numInlines = NumCast(textDoc.inlineTextCount);
textDoc.inlineTextCount = numInlines + 1;
@@ -150,13 +147,13 @@ export class RichTextRules {
.insert(start, newNode)
.replaceRangeWith(start + 1, end + 1, dashDoc)
.insertText(' ', start + 2)
- .setStoredMarks([...node.marks, ...(sm ? sm : [])])
+ .setStoredMarks([...node.marks, ...(sm || [])])
: state.tr;
return replaced;
}),
// set the First-line indent node type for the selection's paragraph (assumes % was used to initiate an EnteringStyle mode)
- new InputRule(new RegExp(/(%d|d)$/), (state, match, start, end) => {
+ new InputRule(/(%d|d)$/, (state, match, start, end) => {
if (!match[0].startsWith('%') && !this.EnteringStyle) return null;
const pos = state.doc.resolve(start) as any;
for (let depth = pos.path.length / 3 - 1; depth >= 0; depth--) {
@@ -171,7 +168,7 @@ export class RichTextRules {
}),
// set the Hanging indent node type for the current selection's paragraph (assumes % was used to initiate an EnteringStyle mode)
- new InputRule(new RegExp(/(%h|h)$/), (state, match, start, end) => {
+ new InputRule(/(%h|h)$/, (state, match, start, end) => {
if (!match[0].startsWith('%') && !this.EnteringStyle) return null;
const pos = state.doc.resolve(start) as any;
for (let depth = pos.path.length / 3 - 1; depth >= 0; depth--) {
@@ -186,11 +183,11 @@ export class RichTextRules {
}),
// set the Quoted indent node type for the current selection's paragraph (assumes % was used to initiate an EnteringStyle mode)
- new InputRule(new RegExp(/(%q|q)$/), (state, match, start, end) => {
+ new InputRule(/(%q|q)$/, (state, match, start, end) => {
if (!match[0].startsWith('%') && !this.EnteringStyle) return null;
const pos = state.doc.resolve(start) as any;
if (state.selection instanceof NodeSelection && state.selection.node.type === schema.nodes.ordered_list) {
- const node = state.selection.node;
+ const { node } = state.selection;
return state.tr.setNodeMarkup(pos.pos, node.type, { ...node.attrs, indent: node.attrs.indent === 30 ? undefined : 30 });
}
for (let depth = pos.path.length / 3 - 1; depth >= 0; depth--) {
@@ -205,46 +202,43 @@ export class RichTextRules {
}),
// center justify text
- new InputRule(new RegExp(/%\^/), (state, match, start, end) => {
+ new InputRule(/%\^/, (state, match, start, end) => {
const resolved = state.doc.resolve(start) as any;
if (resolved?.parent.type.name === 'paragraph') {
return state.tr.deleteRange(start, end).setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks);
- } else {
- const node = resolved.nodeAfter;
- const sm = state.storedMarks || undefined;
- const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: 'center' })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr;
- return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2)));
}
+ const node = resolved.nodeAfter;
+ const sm = state.storedMarks || undefined;
+ const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: 'center' })).setStoredMarks([...node.marks, ...(sm || [])]) : state.tr;
+ return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2)));
}),
// left justify text
- new InputRule(new RegExp(/%\[/), (state, match, start, end) => {
+ new InputRule(/%\[/, (state, match, start, end) => {
const resolved = state.doc.resolve(start) as any;
if (resolved?.parent.type.name === 'paragraph') {
return state.tr.deleteRange(start, end).setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks);
- } else {
- const node = resolved.nodeAfter;
- const sm = state.storedMarks || undefined;
- const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: 'left' })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr;
- return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2)));
}
+ const node = resolved.nodeAfter;
+ const sm = state.storedMarks || undefined;
+ const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: 'left' })).setStoredMarks([...node.marks, ...(sm || [])]) : state.tr;
+ return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2)));
}),
// right justify text
- new InputRule(new RegExp(/%\]/), (state, match, start, end) => {
+ new InputRule(/%\]/, (state, match, start, end) => {
const resolved = state.doc.resolve(start) as any;
if (resolved?.parent.type.name === 'paragraph') {
return state.tr.deleteRange(start, end).setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks);
- } else {
- const node = resolved.nodeAfter;
- const sm = state.storedMarks || undefined;
- const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: 'right' })).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr;
- return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2)));
}
+ const node = resolved.nodeAfter;
+ const sm = state.storedMarks || undefined;
+ const replaced = node ? state.tr.replaceRangeWith(start, end, schema.nodes.paragraph.create({ align: 'right' })).setStoredMarks([...node.marks, ...(sm || [])]) : state.tr;
+ return replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2)));
}),
// activate a style by name using prefix '%<color name>'
- new InputRule(new RegExp(/%[a-zA-Z_]+$/), (state, match, start, end) => {
+ new InputRule(/%[a-zA-Z_]+$/, (state, match, start, end) => {
const color = match[0].substring(1, match[0].length);
const marks = RichTextMenu.Instance?._brushMap.get(color);
@@ -276,13 +270,13 @@ export class RichTextRules {
}),
// toggle alternate text UI %/
- new InputRule(new RegExp(/%\//), (state, match, start, end) => {
+ new InputRule(/%\//, (state, match, start, end) => {
setTimeout(() => this.TextBox.cycleAlternateText(true));
return state.tr.deleteRange(start, end);
}),
// stop using active style
- new InputRule(new RegExp(/%%$/), (state, match, start, end) => {
+ new InputRule(/%%$/, (state, match, start, end) => {
const tr = state.tr.deleteRange(start, end);
const marks = state.tr.selection.$anchor.nodeBefore?.marks;
@@ -295,7 +289,7 @@ export class RichTextRules {
// create a hyperlink to a titled document
// @(<doctitle>)
- new InputRule(new RegExp(/@\(([a-zA-Z_@\.\? \-0-9]+)\)/), (state, match, start, end) => {
+ new InputRule(/@\(([a-zA-Z_@.? \-0-9]+)\)/, (state, match, start, end) => {
const docTitle = match[1];
const prefixLength = '@('.length;
if (docTitle) {
@@ -335,7 +329,7 @@ export class RichTextRules {
// [@{this,doctitle,}.fieldKey{:,=,:=,=:=}value]
// [@{this,doctitle,}.fieldKey]
new InputRule(
- new RegExp(/\[(@|@this\.|@[a-zA-Z_\? \-0-9]+\.)([a-zA-Z_\?\-0-9]+)((:|=|:=|=:=)([a-zA-Z,_\(\)\.@\?\+\-\*\/\ 0-9\(\)]*))?\]/),
+ /\[(@|@this\.|@[a-zA-Z_? \-0-9]+\.)([a-zA-Z_?\-0-9]+)((:|=|:=|=:=)([a-zA-Z,_().@?+\-*/ 0-9()]*))?\]/,
(state, match, start, end) => {
const docTitle = match[1].substring(1).replace(/\.$/, '');
const fieldKey = match[2];
@@ -349,8 +343,17 @@ export class RichTextRules {
const strs = values.some(v => !v.match(/^[-]?[0-9.]$/));
this.Document[DocData][fieldKey] = strs ? new List<string>(values) : new List<number>(values.map(v => Number(v)));
} else if (value) {
- KeyValueBox.SetField(this.Document, fieldKey, assign + value, Doc.IsDataProto(this.Document) ? true : undefined, assign.includes(":=") ? undefined:
- (gptval: FieldResult) => (dataDoc ? this.Document[DocData]:this.Document)[fieldKey] = gptval as string ); // prettier-ignore
+ KeyValueBox.SetField(
+ this.Document,
+ fieldKey,
+ assign + value,
+ Doc.IsDataProto(this.Document) ? true : undefined,
+ assign.includes(':=')
+ ? undefined
+ : (gptval: FieldResult) => {
+ (dataDoc ? this.Document[DocData] : this.Document)[fieldKey] = gptval as string;
+ }
+ );
if (fieldKey === this.TextBox.fieldKey) return this.TextBox.EditorView!.state.tr;
}
const target = docTitle ? getTitledDoc(docTitle) : undefined;
@@ -361,8 +364,8 @@ export class RichTextRules {
),
// pass the contents between '((' and '))' to chatGPT and append the result
- new InputRule(new RegExp(/(^|[^=])(\(\(.*\)\))$/), (state, match, start, end) => {
- var count = 0; // ignore first return value which will be the notation that chat is pending a result
+ new InputRule(/(^|[^=])(\(\(.*\)\))$/, (state, match, start, end) => {
+ let count = 0; // ignore first return value which will be the notation that chat is pending a result
KeyValueBox.SetField(this.Document, '', match[2], false, (gptval: FieldResult) => {
if (count) {
const tr = this.TextBox.EditorView?.state.tr.insertText(' ' + (gptval as string));
@@ -376,7 +379,7 @@ export class RichTextRules {
// create a text display of a metadata field on this or another document, or create a hyperlink portal to another document
// @(wiki:title)
- new InputRule(new RegExp(/@\(wiki:([a-zA-Z_@:\.\?\-0-9 ]+)\)$/), (state, match, start, end) => {
+ new InputRule(/@\(wiki:([a-zA-Z_@:.?\-0-9 ]+)\)$/, (state, match, start, end) => {
const title = match[1].trim().replace(/ /g, '_');
this.TextBox.EditorView?.dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))));
@@ -392,7 +395,7 @@ export class RichTextRules {
// create an inline equation node
// %eq
- new InputRule(new RegExp(/%eq/), (state, match, start, end) => {
+ new InputRule(/%eq/, (state, match, start, end) => {
const fieldKey = 'math' + Utils.GenerateGuid();
this.TextBox.dataDoc[fieldKey] = 'y=';
const tr = state.tr.setSelection(new TextSelection(state.tr.doc.resolve(end - 3), state.tr.doc.resolve(end))).replaceSelectionWith(schema.nodes.equation.create({ fieldKey }));
@@ -400,10 +403,10 @@ export class RichTextRules {
}),
// create an inline view of a tag stored under the '#' field
- new InputRule(new RegExp(/#([a-zA-Z_\-]+[a-zA-Z_\-0-9]*)\s$/), (state, match, start, end) => {
+ new InputRule(/#([a-zA-Z_-]+[a-zA-Z_\-0-9]*)\s$/, (state, match, start, end) => {
const tag = match[1];
if (!tag) return state.tr;
- //this.Document[DocData]['#' + tag] = '#' + tag;
+ // this.Document[DocData]['#' + tag] = '#' + tag;
const tags = StrListCast(this.Document[DocData].tags);
if (!tags.includes(tag)) {
tags.push(tag);
@@ -417,29 +420,25 @@ export class RichTextRules {
}),
// # heading
- textblockTypeInputRule(new RegExp(/^(#{1,6})\s$/), schema.nodes.heading, match => {
- return { level: match[1].length };
- }),
+ textblockTypeInputRule(/^(#{1,6})\s$/, schema.nodes.heading, match => ({ level: match[1].length })),
// set the Todo user-tag on the current selection (assumes % was used to initiate an EnteringStyle mode)
- new InputRule(new RegExp(/[ti!x]$/), (state, match, start, end) => {
+ new InputRule(/[ti!x]$/, (state, match, start, end) => {
if (state.selection.to === state.selection.from || !this.EnteringStyle) return null;
const tag = match[0] === 't' ? 'todo' : match[0] === 'i' ? 'ignore' : match[0] === 'x' ? 'disagree' : match[0] === '!' ? 'important' : '??';
const node = (state.doc.resolve(start) as any).nodeAfter;
if (node?.marks.findIndex((m: any) => m.type === schema.marks.user_tag) !== -1) return state.tr.removeMark(start, end, schema.marks.user_tag);
- if (node?.marks.findIndex((m: any) => m.type === schema.marks.user_mark) !== -1) {
- }
return node
? state.tr
.removeMark(start, end, schema.marks.user_mark)
- .addMark(start, end, schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))
- .addMark(start, end, schema.marks.user_tag.create({ userid: Doc.CurrentUserEmail, tag: tag, modified: Math.round(Date.now() / 1000 / 60) }))
+ .addMark(start, end, schema.marks.user_mark.create({ userid: ClientUtils.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))
+ .addMark(start, end, schema.marks.user_tag.create({ userid: ClientUtils.CurrentUserEmail, tag: tag, modified: Math.round(Date.now() / 1000 / 60) }))
: state.tr;
}),
- new InputRule(new RegExp(/%\(/), (state, match, start, end) => {
+ new InputRule(/%\(/, (state, match, start, end) => {
const node = (state.doc.resolve(start) as any).nodeAfter;
const sm = state.storedMarks?.slice() || [];
const mark = state.schema.marks.summarizeInclusive.create();
@@ -452,9 +451,7 @@ export class RichTextRules {
return replaced.setSelection(new TextSelection(replaced.doc.resolve(end))).setStoredMarks([...node.marks, ...sm]);
}),
- new InputRule(new RegExp(/%\)/), (state, match, start, end) => {
- return state.tr.deleteRange(start, end).removeStoredMark(state.schema.marks.summarizeInclusive.create());
- }),
+ new InputRule(/%\)/, (state, match, start, end) => state.tr.deleteRange(start, end).removeStoredMark(state.schema.marks.summarizeInclusive.create())),
],
};
}
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index ccf7de4a1..8f716ad7a 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -1,6 +1,5 @@
-import * as React from 'react';
-import { DOMOutputSpec, Fragment, MarkSpec, Node, NodeSpec, Schema, Slice } from 'prosemirror-model';
-import { Doc } from '../../../../fields/Doc';
+import { DOMOutputSpec, MarkSpec } from 'prosemirror-model';
+import { ClientUtils } from '../../../../ClientUtils';
import { Utils } from '../../../../Utils';
const emDOM: DOMOutputSpec = ['em', 0];
@@ -336,7 +335,7 @@ export const marks: { [index: string]: MarkSpec } = {
const min = Math.round(node.attrs.modified / 60);
const hr = Math.round(min / 60);
const day = Math.round(hr / 60 / 24);
- const remote = node.attrs.userid !== Doc.CurrentUserEmail ? ' UM-remote' : '';
+ const remote = node.attrs.userid !== ClientUtils.CurrentUserEmail ? ' UM-remote' : '';
return ['span', { class: 'UM-' + uid + remote + ' UM-min-' + min + ' UM-hr-' + hr + ' UM-day-' + day }, 0];
},
},
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 62b8b03d6..70b6604ab 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -2,7 +2,7 @@ import { DOMOutputSpec, Node, NodeSpec } from 'prosemirror-model';
import { listItem, orderedList } from 'prosemirror-schema-list';
import { ParagraphNodeSpec, toParagraphDOM, getParagraphNodeAttrs } from './ParagraphNodeSpec';
import { DocServer } from '../../../DocServer';
-import { Doc, Field } from '../../../../fields/Doc';
+import { Doc, Field, FieldType } from '../../../../fields/Doc';
const blockquoteDOM: DOMOutputSpec = ['blockquote', 0],
hrDOM: DOMOutputSpec = ['hr'],
@@ -266,7 +266,7 @@ export const nodes: { [index: string]: NodeSpec } = {
hideValue: { default: false },
editable: { default: true },
},
- leafText: node => Field.toString((DocServer.GetCachedRefField(node.attrs.docId as string) as Doc)?.[node.attrs.fieldKey as string] as Field),
+ leafText: node => Field.toString((DocServer.GetCachedRefField(node.attrs.docId as string) as Doc)?.[node.attrs.fieldKey as string] as FieldType),
group: 'inline',
draggable: false,
toDOM(node) {
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
index a485ea4c3..95eb86720 100644
--- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx
+++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx
@@ -1,27 +1,31 @@
+/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
+/* eslint-disable jsx-a11y/img-redundant-alt */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable react/function-component-definition */
import { Checkbox, FormControlLabel, Slider, TextField } from '@mui/material';
import { IconButton } from 'browndash-components';
+import * as React from 'react';
import { useEffect, useRef, useState } from 'react';
import { CgClose } from 'react-icons/cg';
import { IoMdRedo, IoMdUndo } from 'react-icons/io';
+import { ClientUtils } from '../../../../ClientUtils';
import { Doc, DocListCast } from '../../../../fields/Doc';
import { List } from '../../../../fields/List';
import { NumCast } from '../../../../fields/Types';
-import { Utils } from '../../../../Utils';
-import { Docs, DocUtils } from '../../../documents/Documents';
import { Networking } from '../../../Network';
+import { DocUtils, Docs } from '../../../documents/Documents';
import { DocumentManager } from '../../../util/DocumentManager';
import { CollectionDockingView } from '../../collections/CollectionDockingView';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
import { OpenWhereMod } from '../DocumentView';
-import { ImageBox, ImageEditorData } from '../ImageBox';
+import { ImageEditorData } from '../ImageBox';
import './GenerativeFill.scss';
import Buttons from './GenerativeFillButtons';
import { BrushHandler } from './generativeFillUtils/BrushHandler';
-import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
-import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces';
import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler';
import { PointerHandler } from './generativeFillUtils/PointerHandler';
-import * as React from 'react';
+import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants';
+import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces';
enum BrushStyle {
ADD,
@@ -332,7 +336,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
const startY = NumCast(parentDoc.current.y);
const children = DocListCast(parentDoc.current.gen_fill_children);
const len = children.length;
- let initialYPositions: number[] = [];
+ const initialYPositions: number[] = [];
for (let i = 0; i < len; i++) {
initialYPositions.push(startY + i * offsetDistanceY);
}
@@ -348,9 +352,9 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
// creates a new image document and returns its reference
const createNewImgDoc = async (img: HTMLImageElement, firstDoc: boolean): Promise<Doc | undefined> => {
if (!imageRootDoc) return;
- const src = img.src;
+ const { src } = img;
const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [src] });
- const source = Utils.prepend(result.accessPaths.agnostic.client);
+ const source = ClientUtils.prepend(result.accessPaths.agnostic.client);
if (firstDoc) {
const x = 0;
@@ -370,51 +374,51 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
}
parentDoc.current = newImg;
return newImg;
- } else {
- if (!parentDoc.current) return;
- const x = NumCast(parentDoc.current.x) + freeformRenderSize + offsetX;
- const initialY = 0;
-
- const newImg = Docs.Create.ImageDocument(source, {
- x: x,
- y: initialY,
- _height: freeformRenderSize,
- _width: freeformRenderSize,
- data_nativeWidth: result.nativeWidth,
- data_nativeHeight: result.nativeHeight,
- });
+ }
+ if (!parentDoc.current) return;
+ const x = NumCast(parentDoc.current.x) + freeformRenderSize + offsetX;
+ const initialY = 0;
+
+ const newImg = Docs.Create.ImageDocument(source, {
+ x: x,
+ y: initialY,
+ _height: freeformRenderSize,
+ _width: freeformRenderSize,
+ data_nativeWidth: result.nativeWidth,
+ data_nativeHeight: result.nativeHeight,
+ });
- const parentList = DocListCast(parentDoc.current.gen_fill_children);
- if (parentList.length > 0) {
- parentList.push(newImg);
- parentDoc.current.gen_fill_children = new List<Doc>(parentList);
- } else {
- parentDoc.current.gen_fill_children = new List<Doc>([newImg]);
- }
+ const parentList = DocListCast(parentDoc.current.gen_fill_children);
+ if (parentList.length > 0) {
+ parentList.push(newImg);
+ parentDoc.current.gen_fill_children = new List<Doc>(parentList);
+ } else {
+ parentDoc.current.gen_fill_children = new List<Doc>([newImg]);
+ }
- DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}`, link_displayLine: true });
- adjustImgPositions();
+ DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}`, link_displayLine: true });
+ adjustImgPositions();
- if (isNewCollection && newCollectionRef.current) {
- Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
- } else {
- addDoc?.(newImg);
- }
- return newImg;
+ if (isNewCollection && newCollectionRef.current) {
+ Doc.AddDocToList(newCollectionRef.current, undefined, newImg);
+ } else {
+ addDoc?.(newImg);
}
+ return newImg;
};
// Saves an image to the collection
const onSave = async (src: string) => {
const img = new Image();
img.src = src;
- if (!currImg.current || !originalImg.current || !imageRootDoc) return;
+ if (!currImg.current || !originalImg.current || !imageRootDoc) return undefined;
try {
const res = await createNewImgDoc(img, false);
return res;
} catch (err) {
console.log(err);
}
+ return undefined;
};
// Closes the editor view
@@ -443,12 +447,12 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
}}
/>
}
- label={'Create New Collection'}
+ label="Create New Collection"
labelPlacement="end"
sx={{ whiteSpace: 'nowrap' }}
/>
<Buttons getEdit={getEdit} loading={loading} onReset={handleReset} />
- <IconButton color={activeColor} tooltip="close" icon={<CgClose size={'16px'} />} onClick={handleViewClose} />
+ <IconButton color={activeColor} tooltip="close" icon={<CgClose size="16px" />} onClick={handleViewClose} />
</div>
</div>
{/* Main canvas for editing */}
@@ -469,7 +473,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
width: cursorData.width,
height: cursorData.width,
}}>
- <div className="innerPointer"></div>
+ <div className="innerPointer" />
</div>
{/* Icons */}
<div className="iconContainer">
@@ -519,11 +523,13 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
/>
</div>
</div>
- {/* Edits thumbnails*/}
+ {/* Edits thumbnails */}
<div className="editsBox">
{edits.map((edit, i) => (
<img
+ // eslint-disable-next-line react/no-array-index-key
key={i}
+ alt="image edits"
width={75}
src={edit[0] as string}
style={{ cursor: 'pointer' }}
@@ -552,6 +558,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD
Original
</label>
<img
+ alt="image stuff"
width={75}
src={originalImg.current?.src}
style={{ cursor: 'pointer' }}
diff --git a/src/client/views/nodes/importBox/ImportElementBox.tsx b/src/client/views/nodes/importBox/ImportElementBox.tsx
index 6e7c3e612..dec9a5019 100644
--- a/src/client/views/nodes/importBox/ImportElementBox.tsx
+++ b/src/client/views/nodes/importBox/ImportElementBox.tsx
@@ -1,7 +1,7 @@
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnFalse } from '../../../../Utils';
+import { returnFalse } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { ViewBoxBaseComponent } from '../../DocComponent';
import { DocumentView } from '../DocumentView';
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 91fdb90fc..518bf66cd 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -3,7 +3,8 @@ import { Tooltip } from '@mui/material';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCast, Field, FieldResult, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
+import { lightOrDark, returnFalse, returnOne, setupMoveUpEvents, StopEvent } from '../../../../ClientUtils';
+import { Doc, DocListCast, Field, FieldType, FieldResult, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
import { Animation, DocData, TransitionTimer } from '../../../../fields/DocSymbols';
import { Copy, Id } from '../../../../fields/FieldSymbols';
import { InkField } from '../../../../fields/InkField';
@@ -13,23 +14,23 @@ import { listSpec } from '../../../../fields/Schema';
import { ComputedField, ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
import { AudioField } from '../../../../fields/URLField';
-import { emptyFunction, emptyPath, lightOrDark, returnFalse, returnOne, setupMoveUpEvents, StopEvent, stringHash } from '../../../../Utils';
+import { emptyFunction, emptyPath, stringHash } from '../../../../Utils';
import { DocServer } from '../../../DocServer';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { DocumentManager } from '../../../util/DocumentManager';
-import { dropActionType } from '../../../util/DragManager';
+import { dropActionType } from '../../../util/DropActionTypes';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { SelectionManager } from '../../../util/SelectionManager';
import { SerializationHelper } from '../../../util/SerializationHelper';
-import { SettingsManager } from '../../../util/SettingsManager';
+import { SnappingManager } from '../../../util/SnappingManager';
import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { CollectionDockingView } from '../../collections/CollectionDockingView';
-import { CollectionFreeFormView, MarqueeViewBounds } from '../../collections/collectionFreeForm';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
import { CollectionStackedTimeline } from '../../collections/CollectionStackedTimeline';
import { CollectionView } from '../../collections/CollectionView';
import { TreeView } from '../../collections/TreeView';
-import { ViewBoxBaseComponent } from '../../DocComponent';
+import { pinDataTypes, PinProps, ViewBoxBaseComponent } from '../../DocComponent';
import { Colors } from '../../global/globalEnums';
import { LightboxView } from '../../LightboxView';
import { DocumentView, OpenWhere, OpenWhereMod } from '../DocumentView';
@@ -37,32 +38,6 @@ import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView';
import { ScriptingBox } from '../ScriptingBox';
import './PresBox.scss';
import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums';
-export interface pinDataTypes {
- scrollable?: boolean;
- dataviz?: number[];
- pannable?: boolean;
- type_collection?: boolean;
- inkable?: boolean;
- filters?: boolean;
- pivot?: boolean;
- temporal?: boolean;
- clippable?: boolean;
- datarange?: boolean;
- dataview?: boolean;
- poslayoutview?: boolean;
- dataannos?: boolean;
- map?: boolean;
-}
-export interface PinProps {
- audioRange?: boolean;
- activeFrame?: number;
- currentFrame?: number;
- hidePresBox?: boolean;
- pinViewport?: MarqueeViewBounds; // pin a specific viewport on a freeform view (use MarqueeView.CurViewBounds to compute if no region has been selected)
- pinDocLayout?: boolean; // pin layout info (width/height/x/y)
- pinAudioPlay?: boolean; // pin audio annotation
- pinData?: pinDataTypes;
-}
@observer
export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@@ -443,7 +418,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
else {
const bestTargetData = bestTarget[DocData];
const current = bestTargetData[fkey];
- const hash = bestTargetData[fkey] ? stringHash(Field.toString(bestTargetData[fkey] as Field)) : undefined;
+ const hash = bestTargetData[fkey] ? stringHash(Field.toString(bestTargetData[fkey] as FieldType)) : undefined;
if (hash) bestTargetData[fkey + '_' + hash] = current instanceof ObjectField ? current[Copy]() : current;
bestTargetData[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data;
}
@@ -623,7 +598,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/// reserved fields on the pinDoc so that those values can be restored to the
/// target doc when navigating to it.
@action
- static pinDocView(pinDoc: Doc, pinProps: PinProps, targetDoc: Doc) {
+ static pinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) {
+ const pinDoc = pinDocIn;
pinDoc.presentation = true;
pinDoc.config = '';
if (pinProps.pinDocLayout) {
@@ -1479,7 +1455,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
max={max}
value={value}
readOnly={true}
- style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
+ style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SnappingManager.userColor, color: SnappingManager.userVariantColor }}
className={`toolbar-slider ${active ? '' : 'none'}`}
onPointerDown={e => {
PresBox._sliderBatch = UndoManager.StartBatch('pres slider');
@@ -1521,7 +1497,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<Tooltip title={<div className="dash-tooltip">Hide before presented</div>}>
<div
className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`}
- style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideBefore ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}`, color: SnappingManager.userColor, background: activeItem.presentation_hideBefore ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor }}
onClick={() => this.updateHideBefore(activeItem)}>
Hide before
</div>
@@ -1529,7 +1505,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<Tooltip title={<div className="dash-tooltip">{'Hide while presented'}</div>}>
<div
className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`}
- style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hide ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}`, color: SnappingManager.userColor, background: activeItem.presentation_hide ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor }}
onClick={() => this.updateHide(activeItem)}>
Hide
</div>
@@ -1538,7 +1514,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<Tooltip title={<div className="dash-tooltip">{'Hide after presented'}</div>}>
<div
className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`}
- style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideAfter ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}`, color: SnappingManager.userColor, background: activeItem.presentation_hideAfter ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor }}
onClick={() => this.updateHideAfter(activeItem)}>
Hide after
</div>
@@ -1548,9 +1524,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div
className="ribbon-toggle"
style={{
- border: `solid 1px ${SettingsManager.userColor}`,
- color: SettingsManager.userColor,
- background: activeItem.presentation_openInLightbox ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+ border: `solid 1px ${SnappingManager.userColor}`,
+ color: SnappingManager.userColor,
+ background: activeItem.presentation_openInLightbox ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor,
}}
onClick={() => this.updateOpenDoc(activeItem)}>
Lightbox
@@ -1559,7 +1535,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<Tooltip title={<div className="dash-tooltip">Transition movement style</div>}>
<div
className="ribbon-toggle"
- style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presEaseFunc === 'ease' ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}`, color: SnappingManager.userColor, background: activeItem.presEaseFunc === 'ease' ? SnappingManager.userVariantColor : SnappingManager.userBackgroundColor }}
onClick={() => this.updateEaseFunc(activeItem)}>
{`${StrCast(activeItem.presEaseFunc, 'ease')}`}
</div>
@@ -1569,10 +1545,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<>
<div className="ribbon-doubleButton">
<div className="presBox-subheading">Slide Duration</div>
- <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
- <input className="presBox-input" type="number" readOnly={true} value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
+ <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
+ <input className="presBox-input" type="number" readOnly value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
</div>
- <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
+ <div className="ribbon-propertyUpDown" style={{ color: SnappingManager.userBackgroundColor, background: SnappingManager.userColor }}>
<div className="ribbon-propertyUpDownItem" onClick={() => this.updateDurationTime(String(duration), 1000)}>
<FontAwesomeIcon icon={'caret-up'} />
</div>
@@ -1611,7 +1587,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="presBox-subheading">Progressivize Collection</div>
<input
className="presBox-checkbox"
- style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
type="checkbox"
onChange={() => {
activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined;
@@ -1634,7 +1610,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="presBox-subheading">Progressivize First Bullet</div>
<input
className="presBox-checkbox"
- style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
type="checkbox"
onChange={() => (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)}
checked={!NumCast(activeItem.presentation_indexedStart)}
@@ -1644,7 +1620,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="presBox-subheading">Expand Current Bullet</div>
<input
className="presBox-checkbox"
- style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
type="checkbox"
onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)}
checked={BoolCast(activeItem.presBulletExpand)}
@@ -1660,16 +1636,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._openBulletEffectDropdown = !this._openBulletEffectDropdown;
})}
style={{
- color: SettingsManager.userColor,
- background: SettingsManager.userVariantColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userVariantColor,
borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5,
- border: this._openBulletEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+ border: this._openBulletEffectDropdown ? `solid 2px ${SnappingManager.userVariantColor}` : `solid 1px ${SnappingManager.userColor}`,
}}>
{effect?.toString()}
<FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openBulletEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
<div
className={'presBox-dropdownOptions'}
- style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}
+ style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none', color: SnappingManager.userColor, background: SnappingManager.userBackgroundColor }}
onPointerDown={e => e.stopPropagation()}>
{Object.values(PresEffect)
.filter(v => isNaN(Number(v)))
@@ -1698,7 +1674,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
);
const presDirection = (direction: PresEffectDirection, icon: string, gridColumn: number, gridRow: number, opts: object) => {
- const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? SettingsManager.userVariantColor : SettingsManager.userColor;
+ const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? SnappingManager.userVariantColor : SnappingManager.userColor;
return (
<Tooltip title={<div className="dash-tooltip">{direction}</div>}>
<div
@@ -1733,10 +1709,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._openMovementDropdown = !this._openMovementDropdown;
})}
style={{
- color: SettingsManager.userColor,
- background: SettingsManager.userVariantColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userVariantColor,
borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5,
- border: this._openMovementDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+ border: this._openMovementDropdown ? `solid 2px ${SnappingManager.userVariantColor}` : `solid 1px ${SnappingManager.userColor}`,
}}>
{this.movementName(activeItem)}
<FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
@@ -1745,8 +1721,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
id={'presBoxMovementDropdown'}
onPointerDown={StopEvent}
style={{
- color: SettingsManager.userColor,
- background: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userBackgroundColor,
display: this._openMovementDropdown ? 'grid' : 'none',
}}>
{presMovement(PresMovement.None)}
@@ -1758,10 +1734,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
<div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
<div className="presBox-subheading">Zoom (% screen filled)</div>
- <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
- <input className="presBox-input" type="number" readOnly={true} value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
+ <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
+ <input className="presBox-input" type="number" readOnly value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
</div>
- <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
+ <div className="ribbon-propertyUpDown" style={{ color: SnappingManager.userBackgroundColor, background: SnappingManager.userColor }}>
<div className="ribbon-propertyUpDownItem" onClick={() => this.updateZoom(String(zoom), 0.1)}>
<FontAwesomeIcon icon={'caret-up'} />
</div>
@@ -1773,10 +1749,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
{PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
<div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
<div className="presBox-subheading">Transition Time</div>
- <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
+ <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
<input className="presBox-input" type="number" readOnly={true} value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
</div>
- <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
+ <div className="ribbon-propertyUpDown" style={{ color: SnappingManager.userBackgroundColor, background: SnappingManager.userColor }}>
<div className="ribbon-propertyUpDownItem" onClick={() => this.updateTransitionTime(String(transitionSpeed), 1000)}>
<FontAwesomeIcon icon={'caret-up'} />
</div>
@@ -1798,7 +1774,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="presBox-subheading">Play Audio Annotation</div>
<input
className="presBox-checkbox"
- style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
type="checkbox"
onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))}
checked={BoolCast(activeItem.presPlayAudio)}
@@ -1808,7 +1784,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="presBox-subheading">Zoom Text Selections</div>
<input
className="presBox-checkbox"
- style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ margin: 10, border: `solid 1px ${SnappingManager.userColor}` }}
type="checkbox"
onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))}
checked={BoolCast(activeItem.presentation_zoomText)}
@@ -1821,10 +1797,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._openEffectDropdown = !this._openEffectDropdown;
})}
style={{
- color: SettingsManager.userColor,
- background: SettingsManager.userVariantColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userVariantColor,
borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5,
- border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+ border: this._openEffectDropdown ? `solid 2px ${SettingsSnappingManagerManager.userVariantColor}` : `solid 1px ${SnappingManager.userColor}`,
}}>
{effect?.toString()}
<FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
@@ -1832,8 +1808,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
className="presBox-dropdownOptions"
id={'presBoxMovementDropdown'}
style={{
- color: SettingsManager.userColor,
- background: SettingsManager.userBackgroundColor,
+ color: SnappingManager.userColor,
+ background: SnappingManager.userBackgroundColor,
display: this._openEffectDropdown ? 'grid' : 'none',
}}
onPointerDown={e => e.stopPropagation()}>
@@ -1844,7 +1820,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
<div className="ribbon-doubleButton" style={{ display: effect === PresEffectDirection.None ? 'none' : 'inline-flex' }}>
<div className="presBox-subheading">Effect direction</div>
- <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
+ <div className="ribbon-property" style={{ border: `solid 1px ${SnappingManager.userColor}` }}>
{StrCast(this.activeItem.presentation_effectDirection)}
</div>
</div>
@@ -1882,7 +1858,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="slider-text" style={{ fontWeight: 500 }}>
Start time (s)
</div>
- <div id="startTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
+ <div id="startTime" className="slider-number" style={{ color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }}>
<input
className="presBox-input"
style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
@@ -1898,7 +1874,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="slider-text" style={{ fontWeight: 500 }}>
Duration (s)
</div>
- <div className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
+ <div className="slider-number" style={{ color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }}>
{Math.round((config_clipEnd - NumCast(activeItem.config_clipStart)) * 10) / 10}
</div>
</div>
@@ -1906,7 +1882,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="slider-text" style={{ fontWeight: 500 }}>
End time (s)
</div>
- <div id="endTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
+ <div id="endTime" className="slider-number" style={{ color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }}>
<input
className="presBox-input"
onKeyDown={e => e.stopPropagation()}
@@ -1926,14 +1902,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
min={clipStart}
max={clipEnd}
value={config_clipEnd}
- style={{ gridColumn: 1, gridRow: 1, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
+ style={{ gridColumn: 1, gridRow: 1, background: SnappingManager.userColor, color: SnappingManager.userVariantColor }}
className={`toolbar-slider ${'end'}`}
id="toolbar-slider"
onPointerDown={e => {
this._batch = UndoManager.StartBatch('config_clipEnd');
const endBlock = document.getElementById('endTime');
if (endBlock) {
- endBlock.style.backgroundColor = SettingsManager.userVariantColor;
+ endBlock.style.backgroundColor = SnappingManager.userVariantColor;
}
e.stopPropagation();
}}
@@ -1941,7 +1917,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._batch?.end();
const endBlock = document.getElementById('endTime');
if (endBlock) {
- endBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
+ endBlock.style.backgroundColor = SnappingManager.userBackgroundColor;
}
}}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1962,7 +1938,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._batch = UndoManager.StartBatch('config_clipStart');
const startBlock = document.getElementById('startTime');
if (startBlock) {
- startBlock.style.backgroundColor = SettingsManager.userVariantColor;
+ startBlock.style.backgroundColor = SnappingManager.userVariantColor;
}
e.stopPropagation();
}}
@@ -1970,7 +1946,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._batch?.end();
const startBlock = document.getElementById('startTime');
if (startBlock) {
- startBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
+ startBlock.style.backgroundColor = SnappingManager.userBackgroundColor;
}
}}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1993,7 +1969,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input
className="presBox-checkbox"
type="checkbox"
- style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}` }}
onChange={() => (activeItem.presentation_mediaStart = 'manual')}
checked={activeItem.presentation_mediaStart === 'manual'}
/>
@@ -2002,7 +1978,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<div className="checkbox-container">
<input
className="presBox-checkbox"
- style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}` }}
type="checkbox"
onChange={() => (activeItem.presentation_mediaStart = 'auto')}
checked={activeItem.presentation_mediaStart === 'auto'}
@@ -2016,7 +1992,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input
className="presBox-checkbox"
type="checkbox"
- style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}` }}
onChange={() => (activeItem.presentation_mediaStop = 'manual')}
checked={activeItem.presentation_mediaStop === 'manual'}
/>
@@ -2026,7 +2002,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
<input
className="presBox-checkbox"
type="checkbox"
- style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+ style={{ border: `solid 1px ${SnappingManager.userColor}` }}
onChange={() => (activeItem.presentation_mediaStop = 'auto')}
checked={activeItem.presentation_mediaStop === 'auto'}
/>
@@ -2270,15 +2246,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
@action
- toggleProperties = () => (SettingsManager.Instance.propertiesWidth = SettingsManager.Instance.propertiesWidth > 0 ? 0 : 250);
+ toggleProperties = () => (SnappingManager.Instance.propertiesWidth = SnappingManager.Instance.propertiesWidth > 0 ? 0 : 250);
@computed get toolbar() {
- const propIcon = SettingsManager.Instance.propertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left';
- const propTitle = SettingsManager.Instance.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
+ const propIcon = SnappingManager.Instance.propertiesWidth > 0 ? 'angle-double-right' : 'angle-double-left';
+ const propTitle = SnappingManager.Instance.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
const mode = StrCast(this.Document._type_collection) as CollectionViewType;
const isMini: boolean = this.toolbarWidth <= 100;
- const activeColor = SettingsManager.userVariantColor;
- const inactiveColor = lightOrDark(SettingsManager.userBackgroundColor) === Colors.WHITE ? Colors.WHITE : SettingsManager.userBackgroundColor;
+ const activeColor = SnappingManager.userVariantColor;
+ const inactiveColor = lightOrDark(SnappingManager.userBackgroundColor) === Colors.WHITE ? Colors.WHITE : SnappingManager.userBackgroundColor;
return mode === CollectionViewType.Carousel3D || Doc.IsInMyOverlay(this.Document) ? null : (
<div id="toolbarContainer" className={'presBox-toolbar'}>
{/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
@@ -2303,7 +2279,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</Tooltip>
<Tooltip title={<div className="dash-tooltip">{propTitle}</div>}>
<div className="toolbar-button" style={{ position: 'absolute', right: 4, fontSize: 16 }} onClick={this.toggleProperties}>
- <FontAwesomeIcon className={'toolbar-thumbtack'} icon={propIcon} style={{ color: SettingsManager.Instance.propertiesWidth > 0 ? activeColor : inactiveColor }} />
+ <FontAwesomeIcon className={'toolbar-thumbtack'} icon={propIcon} style={{ color: SnappingManager.Instance.propertiesWidth > 0 ? activeColor : inactiveColor }} />
</div>
</Tooltip>
</>
@@ -2378,12 +2354,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// Case 1: There are still other frames and should go through all frames before going to next slide
return (
<div className="presPanelOverlay" style={{ display: this.layoutDoc.presentation_status !== 'edit' ? 'inline-flex' : 'none' }}>
- <Tooltip title={<div className="dash-tooltip">{'Loop'}</div>}>
+ <Tooltip title={<div className="dash-tooltip">Loop</div>}>
<div
className="presPanel-button"
style={{ color: this.layoutDoc.presLoop ? Colors.MEDIUM_BLUE : 'white' }}
- onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => (this.layoutDoc.presLoop = !this.layoutDoc.presLoop), false, false)}>
- <FontAwesomeIcon icon={'redo-alt'} />
+ onPointerDown={e =>
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ () => {
+ this.layoutDoc.presLoop = !this.layoutDoc.presLoop;
+ },
+ false,
+ false
+ )
+ }>
+ <FontAwesomeIcon icon="redo-alt" />
</div>
</Tooltip>
<div className="presPanel-divider" />
@@ -2617,12 +2605,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
childXPadding={Doc.IsComicStyle(this.Document) ? 20 : undefined}
filterAddDocument={this.addDocumentFilter}
removeDocument={returnFalse}
- dontRegisterView={true}
+ dontRegisterView
focus={this.focusElement}
ScreenToLocalTransform={this.getTransform}
AddToMap={this.AddToMap}
RemFromMap={this.RemFromMap}
- hierarchyIndex={emptyPath as any as number[]}
+ hierarchyIndex={emptyPath}
/>
) : null}
</div>
diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx
index 28139eb14..fca5a2770 100644
--- a/src/client/views/nodes/trails/PresElementBox.tsx
+++ b/src/client/views/nodes/trails/PresElementBox.tsx
@@ -7,7 +7,8 @@ import { Doc, DocListCast, Opt } from '../../../../fields/Doc';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction } from '../../../../Utils';
+import { returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { DocumentManager } from '../../../util/DocumentManager';
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 59f191af0..9c4080154 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -4,7 +4,8 @@ import { IReactionDisposer, ObservableMap, action, computed, makeObservable, obs
import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorResult } from 'react-color';
-import { Utils, returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../Utils';
+import { ClientUtils, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
+import { unimplementedFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -17,6 +18,7 @@ import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
@observer
export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
+ // eslint-disable-next-line no-use-before-define
static Instance: AnchorMenu;
private _disposer: IReactionDisposer | undefined;
@@ -37,7 +39,9 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
// GPT additions
@observable private selectedText: string = '';
@action
- public setSelectedText = (txt: string) => (this.selectedText = txt);
+ public setSelectedText = (txt: string) => {
+ this.selectedText = txt;
+ };
public onMakeAnchor: () => Opt<Doc> = () => undefined; // Method to get anchor from text search
@@ -64,7 +68,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
componentDidMount() {
this._disposer = reaction(
() => SelectionManager.Views.slice(),
- sel => AnchorMenu.Instance.fadeOut(true)
+ () => AnchorMenu.Instance.fadeOut(true)
);
}
@@ -72,7 +76,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
* Invokes the API with the selected text and stores it in the summarized text.
* @param e pointer down event
*/
- gptSummarize = async (e: React.PointerEvent) => {
+ gptSummarize = async () => {
// move this logic to gptpopup, need to implement generate again
GPTPopup.Instance.setVisible(true);
GPTPopup.Instance.setMode(GPTPopupMode.SUMMARY);
@@ -128,7 +132,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
<Group>
<IconButton
icon={<FontAwesomeIcon icon="highlighter" style={{ transition: 'transform 0.1s', transform: 'rotate(-45deg)' }} />}
- tooltip={'Click to Highlight'}
+ tooltip="Click to Highlight"
onClick={this.highlightClicked}
colorPicker={this.highlightColor}
color={SettingsManager.userColor}
@@ -144,7 +148,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
hsl: { a: 0, h: 0, s: 0, l: 0 },
rgb: { a: 0, r: 0, b: 0, g: 0 },
};
- this.highlightColor = Utils.colorString(col);
+ this.highlightColor = ClientUtils.colorString(col);
};
/**
@@ -167,7 +171,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
color={SettingsManager.userColor}
/>
</div>
- {/* GPT Summarize icon only shows up when text is highlighted, not on marquee selection*/}
+ {/* GPT Summarize icon only shows up when text is highlighted, not on marquee selection */}
{AnchorMenu.Instance.StartCropDrag === unimplementedFunction && this.canSummarize() && (
<IconButton
tooltip="Summarize with AI" //
@@ -187,7 +191,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
<Popup
tooltip="Find document to link to selected text" //
type={Type.PRIM}
- icon={<FontAwesomeIcon icon={'search'} />}
+ icon={<FontAwesomeIcon icon="search" />}
popup={<LinkPopup key="popup" linkCreateAnchor={this.onMakeAnchor} />}
color={SettingsManager.userColor}
/>
@@ -230,7 +234,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
)}
{this.IsTargetToggler !== returnFalse && (
<Toggle
- tooltip={'Make target visibility toggle on click'}
+ tooltip="Make target visibility toggle on click"
type={Type.PRIM}
toggleType={ToggleType.BUTTON}
toggleStatus={this.IsTargetToggler()}
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index da8a88803..cd13d4cbc 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -6,7 +6,7 @@ import * as React from 'react';
import { CgClose } from 'react-icons/cg';
import ReactLoading from 'react-loading';
import { TypeAnimation } from 'react-type-animation';
-import { Utils } from '../../../../Utils';
+import { ClientUtils } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { Networking } from '../../../Network';
@@ -26,6 +26,7 @@ interface GPTPopupProps {}
@observer
export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
+ // eslint-disable-next-line no-use-before-define
static Instance: GPTPopup;
@observable
@@ -71,8 +72,6 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
@observable
public highlightRange: number[] = [];
@action callSummaryApi = () => {};
- @action callEditApi = () => {};
- @action replaceText = (replacement: string) => {};
@observable
private done: boolean = false;
@@ -110,24 +109,25 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
* Generates a Dalle image and uploads it to the server.
*/
generateImage = async () => {
- if (this.imgDesc === '') return;
+ if (this.imgDesc === '') return undefined;
this.setImgUrls([]);
this.setMode(GPTPopupMode.IMAGE);
this.setVisible(true);
this.setLoading(true);
try {
- let image_urls = await gptImageCall(this.imgDesc);
- if (image_urls && image_urls[0]) {
- const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
- const source = Utils.prepend(result.accessPaths.agnostic.client);
- this.setImgUrls([[image_urls[0], source]]);
+ const imageUrls = await gptImageCall(this.imgDesc);
+ if (imageUrls && imageUrls[0]) {
+ const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [imageUrls[0]] });
+ const source = ClientUtils.prepend(result.accessPaths.agnostic.client);
+ this.setImgUrls([[imageUrls[0], source]]);
}
} catch (err) {
console.log(err);
return '';
}
this.setLoading(false);
+ return undefined;
};
/**
@@ -188,55 +188,43 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
}
};
- imageBox = () => {
- return (
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
- {this.heading('GENERATED IMAGE')}
- <div className="image-content-wrapper">
- {this.imgUrls.map(rawSrc => (
- <div className="img-wrapper">
- <div className="img-container">
- <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
- </div>
- <div className="btn-container">
- <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
- </div>
+ imageBox = () => (
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
+ {this.heading('GENERATED IMAGE')}
+ <div className="image-content-wrapper">
+ {this.imgUrls.map(rawSrc => (
+ <div className="img-wrapper">
+ <div className="img-container">
+ <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
</div>
- ))}
- </div>
- {!this.loading && (
- <>
- <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
- </>
- )}
+ <div className="btn-container">
+ <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
+ </div>
+ </div>
+ ))}
</div>
- );
- };
+ {!this.loading && <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />}
+ </div>
+ );
- data = () => {
- return (
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
- {this.heading('GENERATED IMAGE')}
- <div className="image-content-wrapper">
- {this.imgUrls.map(rawSrc => (
- <div className="img-wrapper">
- <div className="img-container">
- <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
- </div>
- <div className="btn-container">
- <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
- </div>
+ data = () => (
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
+ {this.heading('GENERATED IMAGE')}
+ <div className="image-content-wrapper">
+ {this.imgUrls.map(rawSrc => (
+ <div className="img-wrapper">
+ <div className="img-container">
+ <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
</div>
- ))}
- </div>
- {!this.loading && (
- <>
- <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
- </>
- )}
+ <div className="btn-container">
+ <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} />
+ </div>
+ </div>
+ ))}
</div>
- );
- };
+ {!this.loading && <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />}
+ </div>
+ );
summaryBox = () => (
<>
@@ -255,7 +243,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
}, 500);
},
]}
- //cursor={{ hideWhenDone: true }}
+ // cursor={{ hideWhenDone: true }}
/>
) : (
this.text
@@ -294,9 +282,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
<FontAwesomeIcon icon="exclamation-circle" size="sm" style={{ paddingRight: '5px' }} />
AI generated responses can contain inaccurate or misleading content.
</div>
- ) : (
- <></>
- );
+ ) : null;
heading = (headingText: string) => (
<div className="summary-heading">
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index aaff2a342..0ab952e84 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -10,7 +10,8 @@ import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, returnAll, returnFalse, returnNone, returnZero, smoothScroll, Utils } from '../../../Utils';
+import { emptyFunction, Utils } from '../../../Utils';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, returnAll, returnFalse, returnNone, returnZero, smoothScroll } from '../../../ClientUtils';
import { DocUtils } from '../../documents/Documents';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
@@ -98,9 +99,13 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
}
componentDidMount() {
- runInAction(() => (this._showWaiting = true));
+ runInAction(() => {
+ this._showWaiting = true;
+ });
this.setupPdfJsViewer();
- this._mainCont.current?.addEventListener('scroll', e => ((e.target as any).scrollLeft = 0));
+ this._mainCont.current?.addEventListener('scroll', e => {
+ (e.target as any).scrollLeft = 0;
+ });
this._disposers.layout_autoHeight = reaction(
() => this._props.layoutDoc._layout_autoHeight,
@@ -176,7 +181,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
let focusSpeed: Opt<number>;
if (doc !== this._props.Document && mainCont) {
const windowHeight = this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
- const scrollTo = Utils.scrollIntoView(scrollTop, doc[Height](), NumCast(this._props.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, this._scrollHeight);
+ const scrollTo = ClientUtils.scrollIntoView(scrollTop, doc[Height](), NumCast(this._props.layoutDoc._layout_scrollTop), windowHeight, windowHeight * 0.1, this._scrollHeight);
if (scrollTo !== undefined && scrollTo !== this._props.layoutDoc._layout_scrollTop) {
if (!this._pdfViewer) this._initialScroll = { loc: scrollTo, easeFunc: options.easeFunc };
else if (!options.instant) this._scrollStopper = smoothScroll((focusSpeed = options.zoomTime ?? 500), mainCont, scrollTo, options.easeFunc, this._scrollStopper);
@@ -456,7 +461,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
onClick = (e: React.MouseEvent) => {
this._scrollStopper?.();
- if (this._setPreviewCursor && e.button === 0 && Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
+ if (this._setPreviewCursor && e.button === 0 && Math.abs(e.clientX - this._downX) < ClientUtils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < ClientUtils.DRAG_THRESHOLD) {
this._setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Document);
}
// e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks
@@ -496,8 +501,8 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
overlayTransform = () => this.scrollXf().scale(1 / NumCast(this._props.layoutDoc._freeform_scale, 1));
panelWidth = () => this._props.PanelWidth() / (this._props.NativeDimScaling?.() || 1);
panelHeight = () => this._props.PanelHeight() / (this._props.NativeDimScaling?.() || 1);
- transparentFilter = () => [...this._props.childFilters(), Utils.TransparentBackgroundFilter];
- opaqueFilter = () => [...this._props.childFilters(), Utils.noDragDocsFilter, ...(SnappingManager.CanEmbed && this._props.isContentActive() ? [] : [Utils.OpaqueBackgroundFilter])];
+ transparentFilter = () => [...this._props.childFilters(), ClientUtils.TransparentBackgroundFilter];
+ opaqueFilter = () => [...this._props.childFilters(), ClientUtils.noDragDocsFilter, ...(SnappingManager.CanEmbed && this._props.isContentActive() ? [] : [ClientUtils.OpaqueBackgroundFilter])];
childStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
if (doc instanceof Doc && property === StyleProp.PointerEvents) {
if (this.inlineTextAnnotations.includes(doc) || this._props.isContentActive() === false) return 'none';
@@ -532,7 +537,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
PanelWidth={this.panelWidth}
ScreenToLocalTransform={this.overlayTransform}
isAnyChildContentActive={returnFalse}
- isAnnotationOverlayScrollable={true}
+ isAnnotationOverlayScrollable
childFilters={childFilters}
select={emptyFunction}
styleProvider={this.childStyleProvider}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 9f153e86d..af9f05a14 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -2,7 +2,7 @@ import { Tooltip } from '@mui/material';
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCastAsync, Field } from '../../../fields/Doc';
+import { Doc, DocListCastAsync, Field, FieldType } from '../../../fields/Doc';
import { DirectLinks, DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { DocCast, StrCast } from '../../../fields/Types';
@@ -145,7 +145,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
.filter(d => d)
.map(async d => {
const fieldKey = Doc.LayoutFieldKey(d);
- const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView');
+ const annos = !Field.toString(Doc.LayoutField(d) as FieldType).includes('CollectionView');
const data = d[annos ? fieldKey + '_annotations' : fieldKey];
const docs = await DocListCastAsync(data);
docs && newarray.push(...docs);
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index eab33114e..b87e5cdde 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -5,14 +5,14 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { Flip } from 'react-awesome-reveal';
import { FaBug } from 'react-icons/fa';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils';
import { Doc, DocListCast } from '../../../fields/Doc';
import { AclAdmin, DashVersion } from '../../../fields/DocSymbols';
import { StrCast } from '../../../fields/Types';
import { GetEffectiveAcl } from '../../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
+import { emptyFunction } from '../../../Utils';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { DocumentManager } from '../../util/DocumentManager';
-import { dropActionType } from '../../util/DragManager';
import { PingManager } from '../../util/PingManager';
import { ReportManager } from '../../util/reportManager/ReportManager';
import { ServerStats } from '../../util/ServerStats';
@@ -28,6 +28,7 @@ import { DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentV
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DefaultStyleProvider } from '../StyleProvider';
import './TopBar.scss';
+import { dropActionType } from '../../util/DropActionTypes';
/**
* ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user