aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx96
-rw-r--r--src/client/views/collections/CollectionMenu.tsx19
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx85
-rw-r--r--src/client/views/collections/CollectionPileView.tsx13
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx152
-rw-r--r--src/client/views/collections/CollectionSubView.tsx31
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx32
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx79
-rw-r--r--src/client/views/collections/TabDocView.tsx347
-rw-r--r--src/client/views/collections/TreeView.tsx46
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx33
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx38
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx295
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx10
-rw-r--r--src/client/views/collections/collectionSchema/SchemaTableCell.tsx33
15 files changed, 750 insertions, 559 deletions
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 2d906dfe7..8803f6f79 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -1,10 +1,13 @@
+/* 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, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction, numberRange } from '../../../Utils';
-import { Doc, DocListCast } from '../../../fields/Doc';
+import { Doc } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { ScriptField } from '../../../fields/ScriptField';
@@ -52,13 +55,19 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
@observable private collapsed: boolean = false;
@observable private _paletteOn = false;
private set _heading(value: string) {
- runInAction(() => this._props.headingObject && (this._props.headingObject.heading = this.heading = value));
+ runInAction(() => {
+ this._props.headingObject && (this._props.headingObject.heading = this.heading = value);
+ });
}
private set _color(value: string) {
- runInAction(() => this._props.headingObject && (this._props.headingObject.color = this.color = value));
+ runInAction(() => {
+ this._props.headingObject && (this._props.headingObject.color = this.color = value);
+ });
}
private set _collapsed(value: boolean) {
- runInAction(() => this._props.headingObject && (this._props.headingObject.collapsed = this.collapsed = value));
+ runInAction(() => {
+ this._props.headingObject && (this._props.headingObject.collapsed = this.collapsed = value);
+ });
}
private _dropDisposer?: DragManager.DragDropDisposer;
@@ -88,7 +97,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
if (this.collapsed) {
this._props.setDocHeight(this.heading, 20);
} else {
- const rawHeight = this._contRef.current!.getBoundingClientRect().height + 15; //+ 15 accounts for the group header
+ const rawHeight = this._contRef.current!.getBoundingClientRect().height + 15; // +15 accounts for the group header
const transformScale = this._props.screenToLocalTransform().Scale;
const trueHeight = rawHeight * transformScale;
this._props.setDocHeight(this.heading, trueHeight);
@@ -102,7 +111,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
const key = this._props.pivotField;
const castedValue = this.getValue(this.heading);
if (this._props.parent.onInternalDrop(e, de)) {
- key && de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, castedValue, !this.onLayoutDoc(key)));
+ key && de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, castedValue, true));
}
return true;
}
@@ -118,7 +127,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
};
@action
- headingChanged = (value: string, shiftDown?: boolean) => {
+ headingChanged = (value: string /* , shiftDown?: boolean */) => {
this._createEmbeddingSelected = false;
const key = this._props.pivotField;
const castedValue = this.getValue(value);
@@ -141,7 +150,9 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
this._color = color;
};
- pointerEnteredRow = action(() => SnappingManager.IsDragging && (this._background = '#b4b4b4'));
+ pointerEnteredRow = action(() => {
+ SnappingManager.IsDragging && (this._background = '#b4b4b4');
+ });
@action
pointerLeaveRow = () => {
@@ -153,13 +164,13 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
addDocument = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
if (!value && !forceEmptyNote) return false;
this._createEmbeddingSelected = false;
- const key = this._props.pivotField;
+ const { pivotField } = this._props;
const newDoc = Docs.Create.TextDocument('', { _layout_autoHeight: true, _width: 200, _layout_fitWidth: true, title: value });
FormattedTextBox.SetSelectOnLoad(newDoc);
FormattedTextBox.SelectOnLoadChar = value;
- key && ((this.onLayoutDoc(key) ? newDoc : newDoc[DocData])[key] = this.getValue(this._props.heading));
+ pivotField && (newDoc[DocData][pivotField] = this.getValue(this._props.heading));
const docs = this._props.parent.childDocList;
- return docs ? (docs.splice(0, 0, newDoc) ? true : false) : this._props.parent._props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list)
+ return docs ? !!docs.splice(0, 0, newDoc) : this._props.parent._props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list)
};
deleteRow = undoBatch(
@@ -198,21 +209,11 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
@action
headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
if (e.button === 0 && !e.ctrlKey) {
- setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => !this._props.chromeHidden && this.collapseSection(e));
+ setupMoveUpEvents(this, e, this.headerMove, emptyFunction, clickEv => !this._props.chromeHidden && this.collapseSection(clickEv));
this._createEmbeddingSelected = false;
}
};
- /**
- * Returns true if a key is on the layout doc of the documents in the collection.
- */
- onLayoutDoc = (key: string): boolean => {
- DocListCast(this._props.parent.Document.data).forEach(doc => {
- if (Doc.Get(doc, key, true)) return true;
- });
- return false;
- };
-
renderColorPicker = () => {
const selected = this.color;
@@ -229,27 +230,29 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
return (
<div className="collectionStackingView-colorPicker">
<div className="colorOptions">
- <div className={'colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div>
- <div className={'colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div>
- <div className={'colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div>
- <div className={'colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div>
- <div className={'colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div>
- <div className={'colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div>
- <div className={'colorPicker' + (selected === green ? ' active' : '')} style={{ backgroundColor: green }} onClick={() => this.changeColumnColor(green!)}></div>
- <div className={'colorPicker' + (selected === cyan ? ' active' : '')} style={{ backgroundColor: cyan }} onClick={() => this.changeColumnColor(cyan!)}></div>
- <div className={'colorPicker' + (selected === orange ? ' active' : '')} style={{ backgroundColor: orange }} onClick={() => this.changeColumnColor(orange!)}></div>
+ <div className={'colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)} />
+ <div className={'colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)} />
+ <div className={'colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)} />
+ <div className={'colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)} />
+ <div className={'colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)} />
+ <div className={'colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)} />
+ <div className={'colorPicker' + (selected === green ? ' active' : '')} style={{ backgroundColor: green }} onClick={() => this.changeColumnColor(green!)} />
+ <div className={'colorPicker' + (selected === cyan ? ' active' : '')} style={{ backgroundColor: cyan }} onClick={() => this.changeColumnColor(cyan!)} />
+ <div className={'colorPicker' + (selected === orange ? ' active' : '')} style={{ backgroundColor: orange }} onClick={() => this.changeColumnColor(orange!)} />
</div>
</div>
);
};
- toggleEmbedding = action(() => (this._createEmbeddingSelected = true));
- toggleVisibility = () => (this._collapsed = !this.collapsed);
+ toggleEmbedding = action(() => {
+ this._createEmbeddingSelected = true;
+ });
+ toggleVisibility = () => {
+ this._collapsed = !this.collapsed;
+ };
@action
- textCallback = (char: string) => {
- return this.addDocument('', false);
- };
+ textCallback = (/* char: string */) => this.addDocument('', false);
@computed get contentLayout() {
const rows = Math.max(1, Math.min(this._props.docList.length, Math.floor((this._props.parent._props.PanelWidth() - 2 * this._props.parent.xMargin) / (this._props.parent.columnWidth + this._props.parent.gridGap))));
@@ -263,22 +266,22 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
className="collectionStackingView-addDocumentButton"
style={
{
- //width: style.columnWidth / style.numGroupColumns,
- //padding: `${NumCast(this._props.parent.layoutDoc._yPadding, this._props.parent.yMargin)}px 0px 0px 0px`,
+ // width: style.columnWidth / style.numGroupColumns,
+ // padding: `${NumCast(this._props.parent.layoutDoc._yPadding, this._props.parent.yMargin)}px 0px 0px 0px`,
}
}>
- <EditableView GetValue={returnEmptyString} SetValue={this.addDocument} textCallback={this.textCallback} contents={'+ NEW'} />
+ <EditableView GetValue={returnEmptyString} SetValue={this.addDocument} textCallback={this.textCallback} contents="+ NEW" />
</div>
) : null}
<div
- className={`collectionStackingView-masonryGrid`}
+ className="collectionStackingView-masonryGrid"
ref={this._contRef}
style={{
padding: stackPad,
minHeight: this._props.showHandle && this._props.parent._props.isContentActive() ? '10px' : undefined,
width: this._props.parent.NodeWidth,
gridGap: this._props.parent.gridGap,
- gridTemplateColumns: numberRange(rows).reduce((list: string, i: any) => list + ` ${this._props.parent.columnWidth}px`, ''),
+ gridTemplateColumns: numberRange(rows).reduce(list => list + ` ${this._props.parent.columnWidth}px`, ''),
}}>
{this._props.parent.children(this._props.docList)}
</div>
@@ -290,7 +293,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
const noChrome = this._props.chromeHidden;
const key = this._props.pivotField;
const evContents = this.heading ? this.heading : this._props.type && this._props.type === 'number' ? '0' : `NO ${key.toUpperCase()} VALUE`;
- const editableHeaderView = <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />;
+ const editableHeaderView = <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine />;
return this._props.Document.miniHeaders ? (
<div className="collectionStackingView-miniHeader">{editableHeaderView}</div>
) : !this._props.headingObject ? null : (
@@ -304,6 +307,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
{noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? null : (
<div className="collectionStackingView-sectionColor">
<button
+ type="button"
className="collectionStackingView-sectionColorButton"
onPointerDown={e =>
setupMoveUpEvents(
@@ -311,7 +315,9 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
e,
returnFalse,
emptyFunction,
- action(e => (this._paletteOn = !this._paletteOn))
+ action(() => {
+ this._paletteOn = !this._paletteOn;
+ })
)
}>
<FontAwesomeIcon icon="palette" size="lg" />
@@ -320,13 +326,13 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
</div>
)}
{noChrome ? null : (
- <button className="collectionStackingView-sectionDelete" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, noChrome ? emptyFunction : this.collapseSection)}>
+ <button type="button" className="collectionStackingView-sectionDelete" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, noChrome ? emptyFunction : this.collapseSection)}>
<FontAwesomeIcon icon={this.collapsed ? 'chevron-down' : 'chevron-up'} size="lg" />
</button>
)}
{noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? null : (
<div className="collectionStackingView-sectionOptions" onPointerDown={e => e.stopPropagation()}>
- <button className="collectionStackingView-sectionOptionButton" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.deleteRow)}>
+ <button type="button" className="collectionStackingView-sectionOptionButton" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.deleteRow)}>
<FontAwesomeIcon icon="trash" size="lg" />
</button>
</div>
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index a23725348..5a509128d 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -36,6 +36,7 @@ interface CollectionMenuProps {
@observer
export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
+ // eslint-disable-next-line no-use-before-define
@observable static Instance: CollectionMenu;
@observable SelectedCollection: DocumentView | undefined = undefined;
@@ -63,7 +64,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
}
@action
- toggleMenuPin = (e: React.MouseEvent) => {
+ toggleMenuPin = () => {
Doc.UserDoc()['menuCollections-pinned'] = this.Pinned = !this.Pinned;
if (!this.Pinned && this._left < 0) {
this.jumpTo(300, 300);
@@ -165,7 +166,9 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
}
interface CollectionViewMenuProps {
+ // eslint-disable-next-line react/no-unused-prop-types
type: CollectionViewType;
+ // eslint-disable-next-line react/no-unused-prop-types
fieldKey: string;
docView: DocumentView;
}
@@ -377,16 +380,18 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
setupMoveUpEvents(
this,
e,
- (e, down, delta) => {
+ moveEv => {
const vtype = this.props.type;
const c = {
params: ['target'],
title: vtype,
script: `this.target._type_collection = '${StrCast(this.props.type)}'`,
- immediate: (source: Doc[]) => (this.document._type_collection = Doc.getDocTemplate(source?.[0])),
+ immediate: (source: Doc[]) => {
+ this.document._type_collection = Doc.getDocTemplate(source?.[0]);
+ },
initialize: emptyFunction,
};
- DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title), { target: this.document }, c.params, c.initialize, e.clientX, e.clientY);
+ DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title), { target: this.document }, c.params, c.initialize, moveEv.clientX, moveEv.clientY);
return true;
},
emptyFunction,
@@ -397,8 +402,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
setupMoveUpEvents(
this,
e,
- (e, down, delta) => {
- this._buttonizableCommands?.filter(c => c.title === this._currentKey).map(c => DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title, { target: this.document }, c.params, c.initialize, e.clientX, e.clientY));
+ moveEv => {
+ this._buttonizableCommands
+ ?.filter(c => c.title === this._currentKey)
+ .map(c => DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title, { target: this.document }, c.params, c.initialize, moveEv.clientX, moveEv.clientY));
return true;
},
emptyFunction,
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 4ceeb631d..2ba6f5bf4 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -59,7 +59,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
}
@computed get chromeHidden() {
- return BoolCast(this.layoutDoc.chromeHidden) || this._props.onBrowseClickScript?.() ? true : false;
+ return !!(BoolCast(this.layoutDoc.chromeHidden) || this._props.onBrowseClickScript?.());
}
// columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns
@computed get colHeaderData() {
@@ -68,7 +68,6 @@ export class CollectionNoteTakingView extends CollectionSubView() {
if (needsUnsetCategory || colHeaderData === undefined || colHeaderData.length === 0) {
setTimeout(() => {
const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null) ?? []);
- const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
if (needsUnsetCategory || columnHeaders.length === 0) {
columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
this.resizeColumns(columnHeaders);
@@ -112,12 +111,12 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// to render the docs you see within an individual column.
children = (docs: Doc[]) => {
TraceMobx();
- return docs.map((d, i) => {
+ return docs.map(d => {
const height = () => this.getDocHeight(d);
const width = () => this.getDocWidth(d);
const style = { width: width(), marginTop: this.gridGap, height: height() };
return (
- <div className={`collectionNoteTakingView-columnDoc`} key={d[Id]} style={style}>
+ <div className="collectionNoteTakingView-columnDoc" key={d[Id]} style={style}>
{this.getDisplayDoc(d, width)}
</div>
);
@@ -136,7 +135,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
const rowCol = this.docsDraggedRowCol;
// this will sort the docs into the correct columns (minus the ones you're currently dragging)
- docs.map(d => {
+ docs.forEach(d => {
const sectionValue = (d[this.notetakingCategoryField] as object) ?? `unset`;
// look for if header exists already
const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString());
@@ -154,7 +153,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
removeDocDragHighlight = () => {
setTimeout(
- action(() => (this.docsDraggedRowCol.length = 0)),
+ action(() => {
+ this.docsDraggedRowCol.length = 0;
+ }),
100
);
};
@@ -192,13 +193,11 @@ export class CollectionNoteTakingView extends CollectionSubView() {
Object.keys(this._disposers).forEach(key => this._disposers[key]());
}
- moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => {
- return this._props.removeDocument?.(doc) && addDocument?.(doc) ? true : false;
- };
+ moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean) => !!(this._props.removeDocument?.(doc) && addDocument?.(doc));
createRef = (ele: HTMLDivElement | null) => {
this._masonryGridRef = ele;
- this.createDashEventsTarget(ele!); //so the whole grid is the drop target?
+ this.createDashEventsTarget(ele!);
};
@computed get onChildClickHandler() {
@@ -218,14 +217,15 @@ export class CollectionNoteTakingView extends CollectionSubView() {
Doc.BrushDoc(doc);
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 && Math.ceil(this._props.PanelHeight()) < (this._mainCont?.scrollHeight || 0)) {
- let focusSpeed = options.zoomTime ?? 500;
+ const focusSpeed = options.zoomTime ?? 500;
smoothScroll(focusSpeed, this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc);
return focusSpeed;
}
}
+ return undefined;
};
styleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
@@ -240,6 +240,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
return this._props.childOpacity();
}
break;
+ default:
}
return this._props.styleProvider?.(doc, props, property);
};
@@ -255,7 +256,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const noteTakingDocTransform = () => this.getDocTransform(doc, dref);
return (
<DocumentView
- ref={r => (dref = r || undefined)}
+ ref={r => {
+ dref = r || undefined;
+ }}
Document={doc}
TemplateDataDocument={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)}
pointerEvents={this.blockPointerEventsWhenDragging}
@@ -267,8 +270,8 @@ export class CollectionNoteTakingView extends CollectionSubView() {
layout_fitWidth={this._props.childLayoutFitWidth}
isContentActive={emptyFunction}
onKey={this.onKeyDown}
- //TODO: change this from a prop to a parameter passed into a function
- dontHideOnDrag={true}
+ // TODO: change this from a prop to a parameter passed into a function
+ dontHideOnDrag
isDocumentActive={this.isContentActive}
LayoutTemplate={this._props.childLayoutTemplate}
LayoutTemplateString={this._props.childLayoutString}
@@ -302,7 +305,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
+ this._scroll; // required for document decorations to update when the text box container is scrolled
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);
@@ -347,7 +350,6 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// Adding example: column widths are [0.6, 0.4] --> user adds column at end --> column widths are [0.4, 0.267, 0.33]
@action
resizeColumns = (headers: SchemaHeaderField[]) => {
- const n = headers.length;
const curWidths = headers.reduce((sum, hdr) => sum + Math.abs(hdr.width), 0);
const scaleFactor = 1 / curWidths;
this.dataDoc[this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>(
@@ -385,7 +387,11 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// we alter the pivot fields of the docs in case they are moved to a new column.
const colIndex = this.getColumnFromXCoord(xCoord);
const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading);
- DragManager.docsBeingDragged.map(doc => doc[DocData]).forEach(d => (d[this.notetakingCategoryField] = colHeader));
+ DragManager.docsBeingDragged
+ .map(doc => doc[DocData])
+ .forEach(d => {
+ d[this.notetakingCategoryField] = colHeader;
+ });
// used to notify sections to re-render
this.docsDraggedRowCol.length = 0;
const columnFromCoord = this.getColumnFromXCoord(xCoord);
@@ -396,7 +402,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// getColumnFromXCoord returns the column index for a given x-coordinate (currently always the client's mouse coordinate).
// This function is used to know which document a column SHOULD be in while it is being dragged.
getColumnFromXCoord = (xCoord: number): number | undefined => {
- let colIndex: number | undefined = undefined;
+ let colIndex: number | undefined;
const numColumns = this.colHeaderData.length;
const coords = [];
let colStartXCoord = 0;
@@ -419,10 +425,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const docsMatchingHeader: Doc[] = [];
const colIndex = this.getColumnFromXCoord(xCoord);
const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading);
- this.childDocs?.map(d => {
+ this.childDocs?.forEach(d => {
if (d instanceof Promise) return;
const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset';
- if (sectionValue.toString() == colHeader) {
+ if (sectionValue.toString() === colHeader) {
docsMatchingHeader.push(d);
}
});
@@ -438,6 +444,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
FormattedTextBox.SetSelectOnLoad(newDoc);
return this.addDocument?.(newDoc);
}
+ return undefined;
};
// onInternalDrop is used when dragging and dropping a document within the view, such as dragging
@@ -575,6 +582,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
alert('You cannot use an existing column name. Please try a new column name');
return value;
}
+ return undefined;
});
const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
const newColWidth = 1 / (this.numGroupColumns + 1);
@@ -593,17 +601,33 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const subItems: ContextMenuProps[] = [];
subItems.push({
description: `${this.layoutDoc._notetaking_columns_autoCreate ? 'Manually' : 'Automatically'} Create columns`,
- event: () => (this.layoutDoc._notetaking_columns_autoCreate = !this.layoutDoc._notetaking_columns_autoCreate),
+ event: () => {
+ this.layoutDoc._notetaking_columns_autoCreate = !this.layoutDoc._notetaking_columns_autoCreate;
+ },
icon: 'computer',
});
subItems.push({ description: 'Remove Empty Columns', event: this.removeEmptyColumns, icon: 'computer' });
subItems.push({
description: `${this.layoutDoc._notetaking_columns_autoSize ? 'Variable Size' : 'Autosize'} Columns`,
- event: () => (this.layoutDoc._notetaking_columns_autoSize = !this.layoutDoc._notetaking_columns_autoSize),
+ event: () => {
+ this.layoutDoc._notetaking_columns_autoSize = !this.layoutDoc._notetaking_columns_autoSize;
+ },
icon: 'plus',
});
- subItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' });
- subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' });
+ subItems.push({
+ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`,
+ event: () => {
+ this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight;
+ },
+ icon: 'plus',
+ });
+ subItems.push({
+ description: 'Clear All',
+ event: () => {
+ this.dataDoc.data = new List([]);
+ },
+ icon: 'times',
+ });
ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' });
}
};
@@ -628,6 +652,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
const sections = Array.from(this.Sections.entries());
return sections.reduce((list, sec, i) => {
list.push(this.sectionNoteTaking(sec[0], sec[1]));
+ // eslint-disable-next-line react/no-array-index-key
i !== sections.length - 1 && list.push(<CollectionNoteTakingViewDivider key={`divider${i}`} isContentActive={this.isContentActive} index={i} setColumnStartXCoords={this.setColumnStartXCoords} xMargin={this.xMargin} />);
return list;
}, [] as JSX.Element[]);
@@ -661,14 +686,18 @@ export class CollectionNoteTakingView extends CollectionSubView() {
background: this.backgroundColor(),
pointerEvents: this.backgroundEvents,
}}
- onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
- onPointerLeave={action(e => (this.docsDraggedRowCol.length = 0))}
+ onScroll={action(e => {
+ this._scroll = e.currentTarget.scrollTop;
+ })}
+ onPointerLeave={action(() => {
+ this.docsDraggedRowCol.length = 0;
+ })}
onPointerMove={e => e.buttons && this.onPointerMove(false, e.clientX, e.clientY)}
onDragOver={e => this.onPointerMove(true, e.clientX, e.clientY)}
onDrop={this.onExternalDrop.bind(this)}
onContextMenu={this.onContextMenu}
onWheel={e => this._props.isContentActive() && e.stopPropagation()}>
- <>{this.renderedSections}</>
+ {this.renderedSections}
<div className="collectionNotetaking-pivotField" style={{ right: 0, top: 0, position: 'absolute' }}>
<FieldsDropdown
Document={this.Document}
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index e39f1c700..6dfc38e2e 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -1,3 +1,5 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, IReactionDisposer, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -67,6 +69,7 @@ export class CollectionPileView extends CollectionSubView() {
return (
<div className="collectionPileView-innards" style={{ pointerEvents: this.contentEvents }}>
<CollectionFreeFormView
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props} //
layoutEngine={this.layoutEngine}
addDocument={this.addPileDoc}
@@ -117,16 +120,16 @@ export class CollectionPileView extends CollectionSubView() {
setupMoveUpEvents(
this,
e,
- (e: PointerEvent, down: number[], delta: number[]) => {
- if (this.layoutEngine() === 'pass' && this.childDocs.length && e.shiftKey) {
+ (moveEv: PointerEvent, down: number[], delta: number[]) => {
+ if (this.layoutEngine() === 'pass' && this.childDocs.length && moveEv.shiftKey) {
dist += Math.sqrt(delta[0] * delta[0] + delta[1] * delta[1]);
if (dist > 100) {
if (!this._undoBatch) {
this._undoBatch = UndoManager.StartBatch('layout pile');
}
const doc = this.childDocs[0];
- doc.x = e.clientX;
- doc.y = e.clientY;
+ doc.x = moveEv.clientX;
+ doc.y = moveEv.clientY;
this._props.addDocTab(doc, OpenWhere.inParentFromScreen) && (this._props.removeDocument?.(doc) || false);
dist = 0;
}
@@ -155,7 +158,7 @@ export class CollectionPileView extends CollectionSubView() {
render() {
return (
- <div className={`collectionPileView`} onClick={this.onClick} onPointerDown={this.pointerDown} style={{ width: this._props.PanelWidth(), height: '100%' }}>
+ <div className="collectionPileView" onClick={this.onClick} onPointerDown={this.pointerDown} style={{ width: this._props.PanelWidth(), height: '100%' }}>
{this.contents}
</div>
);
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index 3f6638b25..7adf44a5c 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -1,3 +1,8 @@
+/* eslint-disable react/jsx-props-no-spreading */
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable no-use-before-define */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
@@ -22,7 +27,7 @@ import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from '../../util/UndoManager';
-import { CollectionSubView } from '../collections/CollectionSubView';
+import { CollectionSubView } from './CollectionSubView';
import { LightboxView } from '../LightboxView';
import { AudioWaveform } from '../nodes/audio/AudioWaveform';
import { DocumentView, OpenWhere } from '../nodes/DocumentView';
@@ -58,9 +63,14 @@ export enum TrimScope {
@observer
export class CollectionStackedTimeline extends CollectionSubView<CollectionStackedTimelineProps>() {
+ // eslint-disable-next-line no-use-before-define
public static SelectingRegions: Set<CollectionStackedTimeline> = new Set();
public static StopSelecting() {
- this.SelectingRegions.forEach(action(region => (region._selectingRegion = false)));
+ this.SelectingRegions.forEach(
+ action(region => {
+ region._selectingRegion = false;
+ })
+ );
this.SelectingRegions.clear();
}
constructor(props: any) {
@@ -131,7 +141,9 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
componentWillUnmount() {
document.removeEventListener('keydown', this.keyEvents, true);
if (this._selectingRegion) {
- runInAction(() => (this._selectingRegion = false));
+ runInAction(() => {
+ this._selectingRegion = false;
+ });
CollectionStackedTimeline.SelectingRegions.delete(this);
}
}
@@ -175,9 +187,9 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
anchorEnd = (anchor: Doc, val: any = null) => NumCast(anchor._timecodeToHide, NumCast(anchor[this._props.endTag], val) ?? null);
// converts screen pixel offset to time
- toTimeline = (screen_delta: number, width: number) => {
- return Math.max(this.clipStart, Math.min(this.clipEnd, (screen_delta / width) * this.clipDuration + this.clipStart));
- };
+ // prettier-ignore
+ toTimeline = (screenDelta: number, width: number) => //
+ Math.max(this.clipStart, Math.min(this.clipEnd, (screenDelta / width) * this.clipDuration + this.clipStart));
@computed get rangeClick() {
// prettier-ignore
@@ -235,6 +247,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
this._props.setTime(Math.min(Math.max(this.clipStart, this.currentTime + jump), this.clipEnd));
e.stopPropagation();
break;
+ default:
}
}
};
@@ -254,17 +267,15 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
@action
onPointerDownTimeline = (e: React.PointerEvent): void => {
const rect = this._timeline?.getBoundingClientRect();
- const clientX = e.clientX;
- const diff = rect ? clientX - rect?.x : null;
- const shiftKey = e.shiftKey;
+ const { clientX, shiftKey } = e;
if (rect && this._props.isContentActive()) {
const wasPlaying = this._props.playing();
if (wasPlaying) this._props.Pause();
- var wasSelecting = this._markerEnd !== undefined;
+ let wasSelecting = this._markerEnd !== undefined;
setupMoveUpEvents(
this,
e,
- action(e => {
+ action(() => {
if (!wasSelecting) {
this._markerStart = this._markerEnd = this.toTimeline(clientX - rect.x, rect.width);
wasSelecting = true;
@@ -273,8 +284,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
this._markerEnd = this.toTimeline(e.clientX - rect.x, rect.width);
return false;
}),
- action((e, movement, isClick) => {
- this._markerEnd = this.toTimeline(e.clientX - rect.x, rect.width);
+ action((upEvent, movement, isClick) => {
+ this._markerEnd = this.toTimeline(upEvent.clientX - rect.x, rect.width);
if (this._markerEnd < this._markerStart) {
const tmp = this._markerStart;
this._markerStart = this._markerEnd;
@@ -287,8 +298,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
(!isClick || !wasSelecting) && (this._markerEnd = undefined);
this._timelineWrapper && (this._timelineWrapper.style.cursor = '');
}),
- (e, doubleTap) => {
- if (e.button !== 2) {
+ (clickEv, doubleTap) => {
+ if (clickEv.button !== 2) {
this._props.select(false);
!wasPlaying && doubleTap && this._props.Play();
}
@@ -310,7 +321,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
onHover = (e: React.MouseEvent): void => {
e.stopPropagation();
const rect = this._timeline?.getBoundingClientRect();
- const clientX = e.clientX;
+ const { clientX } = e;
if (rect) {
this._hoverTime = this.toTimeline(clientX - rect.x, rect.width);
if (this.thumbnails) {
@@ -328,14 +339,14 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
setupMoveUpEvents(
this,
e,
- action((e, [], []) => {
+ action(moveEv => {
if (rect && this._props.isContentActive()) {
- this._trimStart = Math.min(Math.max(this.trimStart + (e.movementX / rect.width) * this.clipDuration, this.clipStart), this.trimEnd - this.minTrimLength);
+ this._trimStart = Math.min(Math.max(this.trimStart + (moveEv.movementX / rect.width) * this.clipDuration, this.clipStart), this.trimEnd - this.minTrimLength);
}
return false;
}),
emptyFunction,
- action((e, doubleTap) => {
+ action((clickEv, doubleTap) => {
doubleTap && (this._trimStart = this.clipStart);
})
);
@@ -348,14 +359,14 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
setupMoveUpEvents(
this,
e,
- action((e, [], []) => {
+ action(moveEv => {
if (rect && this._props.isContentActive()) {
- this._trimEnd = Math.max(Math.min(this.trimEnd + (e.movementX / rect.width) * this.clipDuration, this.clipEnd), this.trimStart + this.minTrimLength);
+ this._trimEnd = Math.max(Math.min(this.trimEnd + (moveEv.movementX / rect.width) * this.clipDuration, this.clipEnd), this.trimStart + this.minTrimLength);
}
return false;
}),
emptyFunction,
- action((e, doubleTap) => {
+ action((clickEv, doubleTap) => {
doubleTap && (this._trimEnd = this.clipEnd);
})
);
@@ -384,7 +395,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
// handles dragging and dropping markers in timeline
@action
- internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData, xp: number) {
+ internalDocDrop(e: Event, de: DragManager.DropEvent, docDragData: DragManager.DocumentDragData) {
if (super.onInternalDrop(e, de)) {
// determine x coordinate of drop and assign it to the documents being dragged --- see internalDocDrop of collectionFreeFormView.tsx for how it's done when dropping onto a 2D freeform view
const localPt = this.ScreenToLocalBoxXf().transformPoint(de.x, de.y);
@@ -404,7 +415,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
}
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
- if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData, 0);
+ if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData);
return false;
};
@@ -442,7 +453,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
}
@action
- playOnClick = (anchorDoc: Doc, clientX: number) => {
+ playOnClick = (anchorDoc: Doc /* , clientX: number */) => {
const seekTimeInSeconds = this.anchorStart(anchorDoc) - 0.05;
const endTime = this.anchorEnd(anchorDoc);
if (this.layoutDoc.autoPlayAnchors) {
@@ -451,17 +462,15 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
this._props.playFrom(seekTimeInSeconds, endTime);
this.scrollToTime(seekTimeInSeconds);
}
- } else {
- if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) && endTime > NumCast(this.layoutDoc._layout_currentTimecode)) {
- if (!this.layoutDoc.autoPlayAnchors && this._props.playing()) {
- this._props.Pause();
- } else {
- this._props.Play();
- }
+ } else if (seekTimeInSeconds < NumCast(this.layoutDoc._layout_currentTimecode) && endTime > NumCast(this.layoutDoc._layout_currentTimecode)) {
+ if (!this.layoutDoc.autoPlayAnchors && this._props.playing()) {
+ this._props.Pause();
} else {
- this._props.playFrom(seekTimeInSeconds, endTime);
- this.scrollToTime(seekTimeInSeconds);
+ this._props.Play();
}
+ } else {
+ this._props.playFrom(seekTimeInSeconds, endTime);
+ this.scrollToTime(seekTimeInSeconds);
}
return { select: true };
};
@@ -480,19 +489,17 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
const rect = this._timeline?.getBoundingClientRect();
rect && this._props.setTime(this.toTimeline(clientX - rect.x, rect.width));
}
+ } else if (this.layoutDoc.autoPlayAnchors) {
+ this._props.playFrom(seekTimeInSeconds, endTime);
} else {
- if (this.layoutDoc.autoPlayAnchors) {
- this._props.playFrom(seekTimeInSeconds, endTime);
- } else {
- this._props.setTime(seekTimeInSeconds);
- }
+ this._props.setTime(seekTimeInSeconds);
}
return { select: true };
};
// makes sure no anchors overlaps each other by setting the correct position and width
getLevel = (m: Doc, placed: { anchorStartTime: number; anchorEndTime: number; level: number }[]) => {
- const timelineContentWidth = this.timelineContentWidth;
+ const { timelineContentWidth } = this;
const x1 = this.anchorStart(m);
const x2 = this.anchorEnd(m, x1 + (10 / timelineContentWidth) * this.clipDuration);
let max = 0;
@@ -504,6 +511,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
max = Math.max(max, p.level);
return p.level;
}
+ return undefined;
})
);
let level = max + 1;
@@ -565,10 +573,14 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
onWheel={e => this.isContentActive() && e.stopPropagation()}
onScroll={this.setScroll}
onMouseMove={e => this.isContentActive() && this.onHover(e)}
- ref={wrapper => (this._timelineWrapper = wrapper)}>
+ ref={wrapper => {
+ this._timelineWrapper = wrapper;
+ }}>
<div
className="collectionStackedTimeline"
- ref={(timeline: HTMLDivElement | null) => (this._timeline = timeline)}
+ ref={(timeline: HTMLDivElement | null) => {
+ this._timeline = timeline;
+ }}
onClick={e => this.isContentActive() && StopEvent(e)}
onPointerDown={e => this.isContentActive() && this.onPointerDownTimeline(e)}
style={{ width: this.timelineContentWidth }}>
@@ -583,7 +595,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
const height = this._props.PanelHeight() / maxLevel;
return this.Document.hideAnchors ? null : (
<div
- className={'collectionStackedTimeline-marker-timeline'}
+ className="collectionStackedTimeline-marker-timeline"
key={d.anchor[Id]}
style={{
left,
@@ -593,6 +605,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
pointerEvents: 'none',
}}>
<StackedTimelineAnchor
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
mark={d.anchor}
containerViewPath={this._props.containerViewPath}
@@ -647,7 +660,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
{this.IsTrimming !== TrimScope.None && (
<>
- <div className="collectionStackedTimeline-trim-shade" style={{ width: `${((this.trimStart - this.clipStart) / this.clipDuration) * 100}%` }}></div>
+ <div className="collectionStackedTimeline-trim-shade" style={{ width: `${((this.trimStart - this.clipStart) / this.clipDuration) * 100}%` }} />
<div
className="collectionStackedTimeline-trim-controls"
@@ -655,8 +668,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
left: `${((this.trimStart - this.clipStart) / this.clipDuration) * 100}%`,
width: `${((this.trimEnd - this.trimStart) / this.clipDuration) * 100}%`,
}}>
- <div className="collectionStackedTimeline-trim-handle" onPointerDown={this.trimLeft}></div>
- <div className="collectionStackedTimeline-trim-handle" onPointerDown={this.trimRight}></div>
+ <div className="collectionStackedTimeline-trim-handle" onPointerDown={this.trimLeft} />
+ <div className="collectionStackedTimeline-trim-handle" onPointerDown={this.trimRight} />
</div>
<div
@@ -664,7 +677,8 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
style={{
left: `${((this.trimEnd - this.clipStart) / this.clipDuration) * 100}%`,
width: `${((this.clipEnd - this.trimEnd) / this.clipDuration) * 100}%`,
- }}></div>
+ }}
+ />
</>
)}
</div>
@@ -686,7 +700,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
interface StackedTimelineAnchorProps {
mark: Doc;
whenChildContentsActiveChanged: (isActive: boolean) => void;
- addDocTab: (doc: Doc, where: OpenWhere) => boolean;
+ addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean;
rangeClickScript: () => ScriptField;
rangePlayScript: () => ScriptField;
left: number;
@@ -736,13 +750,13 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
this._disposer = reaction(
() => this._props.currentTimecode(),
time => {
- const dictationDoc = Cast(this._props.layoutDoc.data_dictation, Doc, null);
- const isDictation = dictationDoc && LinkManager.Links(this._props.mark).some(link => Cast(link.link_anchor_1, Doc, null)?.annotationOn === dictationDoc);
+ // const dictationDoc = Cast(this._props.layoutDoc.data_dictation, Doc, null);
+ // const isDictation = dictationDoc && LinkManager.Links(this._props.mark).some(link => Cast(link.link_anchor_1, Doc, null)?.annotationOn === dictationDoc);
if (
!LightboxView.LightboxDoc &&
// bcz: when should links be followed? we don't want to move away from the video to follow a link but we can open it in a sidebar/etc. But we don't know that upfront.
// for now, we won't follow any links when the lightbox is oepn to avoid "losing" the video.
- /*(isDictation || !Doc.AreProtosEqual(LightboxView.LightboxDoc, this._props.layoutDoc))*/
+ /* (isDictation || !Doc.AreProtosEqual(LightboxView.LightboxDoc, this._props.layoutDoc)) */
!this._props.layoutDoc.dontAutoFollowLinks &&
LinkManager.Links(this._props.mark).length &&
time > NumCast(this._props.mark[this._props.startTag]) &&
@@ -764,34 +778,33 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
// starting the drag event for anchor resizing
@action
onAnchorDown = (e: React.PointerEvent, anchor: Doc, left: boolean): void => {
- //this._props._timeline?.setPointerCapture(e.pointerId);
- const newTime = (e: PointerEvent) => {
- const rect = (e.target as any).getBoundingClientRect();
- return this._props.toTimeline(e.clientX - rect.x, rect.width);
+ const newTime = (timeDownEv: PointerEvent) => {
+ const rect = (timeDownEv.target as any).getBoundingClientRect();
+ return this._props.toTimeline(timeDownEv.clientX - rect.x, rect.width);
};
- const changeAnchor = (anchor: Doc, left: boolean, time: number | undefined) => {
+ const changeAnchor = (time: number | undefined) => {
const timelineOnly = Cast(anchor[this._props.startTag], 'number', null) !== undefined;
if (timelineOnly) {
- if (!left && time !== undefined && time <= NumCast(anchor[this._props.startTag])) time = undefined;
- Doc.SetInPlace(anchor, left ? this._props.startTag : this._props.endTag, time, true);
- if (!left) Doc.SetInPlace(anchor, 'layout_borderRounding', time !== undefined ? undefined : '100%', true);
+ const timeMod = !left && time !== undefined && time <= NumCast(anchor[this._props.startTag]) ? undefined : time;
+ Doc.SetInPlace(anchor, left ? this._props.startTag : this._props.endTag, timeMod, true);
+ if (!left) Doc.SetInPlace(anchor, 'layout_borderRounding', timeMod !== undefined ? undefined : '100%', true);
} else {
anchor[left ? '_timecodeToShow' : '_timecodeToHide'] = time;
}
return false;
};
this.noEvents = true;
- var undo: UndoManager.Batch | undefined;
+ let undo: UndoManager.Batch | undefined;
setupMoveUpEvents(
this,
e,
- e => {
+ moveEv => {
if (!undo) undo = UndoManager.StartBatch('drag anchor');
- this._props.setTime(newTime(e));
- return changeAnchor(anchor, left, newTime(e));
+ this._props.setTime(newTime(moveEv));
+ return changeAnchor(newTime(moveEv));
},
- action(e => {
- this._props.setTime(newTime(e));
+ action(upEv => {
+ this._props.setTime(newTime(upEv));
undo?.end();
this.noEvents = false;
}),
@@ -829,7 +842,9 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
{...this._props}
NativeWidth={returnZero}
NativeHeight={returnZero}
- ref={action((r: DocumentView | null) => (anchor.view = r))}
+ ref={action((r: DocumentView | null) => {
+ anchor.view = r;
+ })}
Document={mark}
TemplateDataDocument={undefined}
containerViewPath={this._props.containerViewPath}
@@ -852,7 +867,7 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
onClickScript={script}
onDoubleClickScript={this._props.layoutDoc.autoPlayAnchors ? undefined : doublescript}
ignoreAutoHeight={false}
- hideResizeHandles={true}
+ hideResizeHandles
contextMenuItems={this.contextMenuItems}
/>
),
@@ -878,12 +893,15 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
);
}
}
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function formatToTime(time: number): any {
return formatTime(time);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function min(num1: number, num2: number): number {
return Math.min(num1, num2);
});
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function max(num1: number, num2: number): number {
return Math.max(num1, num2);
});
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 7d93f4074..f3dedaedf 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -3,11 +3,12 @@ import * as React from 'react';
import * as rp from 'request-promise';
import { ClientUtils, returnFalse } from '../../../ClientUtils';
import CursorField from '../../../fields/CursorField';
-import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, 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';
+import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, ScriptCast, StrCast } from '../../../fields/Types';
import { WebField } from '../../../fields/URLField';
import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
@@ -61,8 +62,8 @@ export interface SubCollectionViewProps extends CollectionViewProps {
isAnyChildContentActive: () => boolean;
}
-export function CollectionSubView<X>(moreProps?: X) {
- class CollectionSubView extends ViewBoxBaseComponent<X & SubCollectionViewProps>() {
+export function CollectionSubView<X>() {
+ class CollectionSubViewInternal extends ViewBoxBaseComponent<X & SubCollectionViewProps>() {
private dropDisposer?: DragManager.DragDropDisposer;
private gestureDisposer?: GestureUtils.GestureEventDisposer;
protected _mainCont?: HTMLDivElement;
@@ -167,23 +168,24 @@ export function CollectionSubView<X>(moreProps?: X) {
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 FieldType).includes(CollectionView.name);
- const data = d[annos ? fieldKey + '_annotations' : fieldKey];
- const side = annos && d[fieldKey + '_sidebar'];
- if (data !== undefined || side !== undefined) {
- let subDocs = [...DocListCast(data), ...DocListCast(side)];
+ const isAnnotatableDoc = d[fieldKey] instanceof List && !(d[fieldKey] as List<Doc>)?.some(ele => !(ele instanceof Doc));
+ const docChildDocs = d[isAnnotatableDoc ? fieldKey + '_annotations' : fieldKey];
+ const sidebarDocs = isAnnotatableDoc && d[fieldKey + '_sidebar'];
+ if (docChildDocs !== undefined || sidebarDocs !== undefined) {
+ let subDocs = [...DocListCast(docChildDocs), ...DocListCast(sidebarDocs)];
if (subDocs.length > 0) {
let newarray: Doc[] = [];
notFiltered = notFiltered || (!searchDocs.length && DocUtils.FilterDocs(subDocs, childDocFilters, childFiltersByRanges, d).length);
while (subDocs.length > 0 && !notFiltered) {
newarray = [];
+ // eslint-disable-next-line no-loop-func
subDocs.forEach(t => {
- const fieldKey = Doc.LayoutFieldKey(t);
- const annos = !Field.toString(Doc.LayoutField(t) as FieldType).includes(CollectionView.name);
+ const docFieldKey = Doc.LayoutFieldKey(t);
+ const isSubDocAnnotatable = t[docFieldKey] instanceof List && !(t[docFieldKey] as List<Doc>)?.some(ele => !(ele instanceof Doc));
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));
- annos && DocListCast(t[fieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc));
+ DocListCast(t[isSubDocAnnotatable ? docFieldKey + '_annotations' : docFieldKey]).forEach(newdoc => newarray.push(newdoc));
+ isSubDocAnnotatable && DocListCast(t[docFieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc));
});
subDocs = newarray;
}
@@ -227,6 +229,7 @@ export function CollectionSubView<X>(moreProps?: X) {
}
@undoBatch
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {}
protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetDropAction: dropActionType) {
@@ -245,7 +248,7 @@ export function CollectionSubView<X>(moreProps?: X) {
addDocument = (doc: Doc | Doc[], annotationKey?: string) => this._props.addDocument?.(doc, annotationKey) || false;
removeDocument = (doc: Doc | Doc[], annotationKey?: string) => this._props.removeDocument?.(doc, annotationKey) || false;
- moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string) => this._props.moveDocument?.(doc, targetCollection, addDocument) || false;
+ moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean) => this._props.moveDocument?.(doc, targetCollection, addDocument) || false;
protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
const { docDragData } = de.complete;
@@ -531,5 +534,5 @@ export function CollectionSubView<X>(moreProps?: X) {
};
}
- return CollectionSubView;
+ return CollectionSubViewInternal;
}
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 7f234ffe9..e1d2e3c40 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -1,3 +1,5 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -16,7 +18,6 @@ import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { FieldsDropdown } from '../FieldsDropdown';
import { DocumentView } from '../nodes/DocumentView';
-import { FocusViewOptions } from '../nodes/FieldView';
import { PresBox } from '../nodes/trails';
import { CollectionSubView } from './CollectionSubView';
import './CollectionTimeView.scss';
@@ -68,7 +69,7 @@ export class CollectionTimeView extends CollectionSubView() {
};
@action
- scrollPreview = (docView: DocumentView, anchor: Doc, focusSpeed: number, options: FocusViewOptions) => {
+ scrollPreview = (docView: DocumentView, anchor: Doc /* , focusSpeed: number, options: FocusViewOptions */) => {
// if in preview, then override document's fields with view spec
this._focusFilters = StrListCast(anchor.config_docFilters);
this._focusRangeFilters = StrListCast(anchor.config_docRangeFilters);
@@ -77,13 +78,15 @@ export class CollectionTimeView extends CollectionSubView() {
};
layoutEngine = () => this._layoutEngine;
- toggleVisibility = action(() => (this._collapsed = !this._collapsed));
+ toggleVisibility = action(() => {
+ this._collapsed = !this._collapsed;
+ });
onMinDown = (e: React.PointerEvent) => {
setupMoveUpEvents(
this,
e,
- action((e: PointerEvent, down: number[], delta: number[]) => {
+ action((moveEv: PointerEvent, down: number[], delta: number[]) => {
const minReq = NumCast(this.Document[this._props.fieldKey + '-timelineMinReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMin'], 0));
const maxReq = NumCast(this.Document[this._props.fieldKey + '-timelineMaxReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMax'], 10));
this.Document[this._props.fieldKey + '-timelineMinReq'] = minReq + ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
@@ -99,7 +102,7 @@ export class CollectionTimeView extends CollectionSubView() {
setupMoveUpEvents(
this,
e,
- action((e: PointerEvent, down: number[], delta: number[]) => {
+ action((moveEv, down: number[], delta: number[]) => {
const minReq = NumCast(this.Document[this._props.fieldKey + '-timelineMinReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMin'], 0));
const maxReq = NumCast(this.Document[this._props.fieldKey + '-timelineMaxReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMax'], 10));
this.Document[this._props.fieldKey + '-timelineMaxReq'] = maxReq + ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
@@ -114,7 +117,7 @@ export class CollectionTimeView extends CollectionSubView() {
setupMoveUpEvents(
this,
e,
- action((e: PointerEvent, down: number[], delta: number[]) => {
+ action((moveEv: PointerEvent, down: number[], delta: number[]) => {
const minReq = NumCast(this.Document[this._props.fieldKey + '-timelineMinReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMin'], 0));
const maxReq = NumCast(this.Document[this._props.fieldKey + '-timelineMaxReq'], NumCast(this.Document[this._props.fieldKey + '-timelineMax'], 10));
this.Document[this._props.fieldKey + '-timelineMinReq'] = minReq - ((maxReq - minReq) * delta[0]) / this._props.PanelWidth();
@@ -134,7 +137,7 @@ export class CollectionTimeView extends CollectionSubView() {
};
@action
- contentsDown = (e: React.MouseEvent) => {
+ contentsDown = () => {
const prevFilterIndex = NumCast(this.layoutDoc._prevFilterIndex);
if (prevFilterIndex > 0) {
this.goTo(prevFilterIndex - 1);
@@ -147,6 +150,7 @@ export class CollectionTimeView extends CollectionSubView() {
return (
<div className="collectionTimeView-innards" key="timeline" style={{ pointerEvents: this._props.isContentActive() ? undefined : 'none' }} onClick={this.contentsDown}>
<CollectionFreeFormView
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
engineProps={{ pivotField: this.pivotField, childFilters: this.childDocFilters, childFiltersByRanges: this.childDocRangeFilters }}
fitContentsToBox={returnTrue}
@@ -162,7 +166,7 @@ export class CollectionTimeView extends CollectionSubView() {
const fieldKey = Doc.LayoutFieldKey(doc);
doc[fieldKey + '-timelineCur'] = ComputedField.MakeFunction("(activePresentationItem()[this._pivotField || 'year'] || 0)");
}
- specificMenu = (e: React.MouseEvent) => {
+ specificMenu = () => {
const layoutItems: ContextMenuProps[] = [];
const doc = this.layoutDoc;
@@ -194,7 +198,7 @@ export class CollectionTimeView extends CollectionSubView() {
render() {
let nonNumbers = 0;
- this.childDocs.map(doc => {
+ this.childDocs.forEach(doc => {
const num = NumCast(doc[this.pivotField], Number(StrCast(doc[this.pivotField])));
if (isNaN(num)) {
nonNumbers++;
@@ -226,13 +230,20 @@ export class CollectionTimeView extends CollectionSubView() {
</>
)}
<div style={{ right: 0, top: 0, position: 'absolute' }}>
- <FieldsDropdown Document={this.Document} selectFunc={fieldKey => (this.layoutDoc._pivotField = fieldKey)} placeholder={StrCast(this.layoutDoc._pivotField)} />
+ <FieldsDropdown
+ Document={this.Document}
+ selectFunc={fieldKey => {
+ this.layoutDoc._pivotField = fieldKey;
+ }}
+ placeholder={StrCast(this.layoutDoc._pivotField)}
+ />
</div>
</div>
);
}
}
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBounds) {
const pivotField = StrCast(pivotDoc._pivotField, 'author');
let prevFilterIndex = NumCast(pivotDoc._prevFilterIndex);
@@ -249,6 +260,7 @@ ScriptingGlobals.add(function pivotColumnClick(pivotDoc: Doc, bounds: ViewDefBou
const pivotView = DocumentManager.Instance.getDocumentView(pivotDoc);
if (pivotDoc && pivotView?.ComponentView instanceof CollectionTimeView && filterVals.length === 1) {
if (pivotView?.ComponentView.childDocs.length && pivotView.ComponentView.childDocs[0][filterVals[0]]) {
+ // eslint-disable-next-line prefer-destructuring
pivotDoc._pivotField = filterVals[0];
}
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 32473f20b..538a6fd5e 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,3 +1,5 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -23,13 +25,13 @@ import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { EditableView } from '../EditableView';
import { DocumentView } from '../nodes/DocumentView';
-import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { StyleProp } from '../StyleProvider';
import { CollectionFreeFormView } from './collectionFreeForm';
import { CollectionSubView } from './CollectionSubView';
import './CollectionTreeView.scss';
import { TreeView } from './TreeView';
+
const _global = (window /* browser */ || global) /* node */ as any;
export type collectionTreeViewProps = {
@@ -94,8 +96,10 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
// these should stay in synch with counterparts in DocComponent.ts ViewBoxAnnotatableComponent
@observable _isAnyChildContentActive = false;
- whenChildContentsActiveChanged = action((isActive: boolean) => this._props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive)));
- isContentActive = (outsideReaction?: boolean) => (this._isAnyChildContentActive ? true : this._props.isContentActive() ? true : false);
+ whenChildContentsActiveChanged = action((isActive: boolean) => {
+ this._props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive));
+ });
+ isContentActive = () => (this._isAnyChildContentActive ? true : !!this._props.isContentActive());
componentWillUnmount() {
this._isDisposing = true;
@@ -105,7 +109,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
}
componentDidMount() {
- //this._props.setContentView?.(this);
+ // this._props.setContentView?.(this);
this._disposers.autoheight = reaction(
() => this.layoutDoc.layout_autoHeight,
auto => auto && this.computeHeight(),
@@ -128,20 +132,19 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
observeHeight = (ref: any) => {
if (ref) {
this.refList.add(ref);
- this.observer = new _global.ResizeObserver(
- action((entries: any) => {
- if (this.layoutDoc.layout_autoHeight && ref && this.refList.size && !SnappingManager.IsDragging) {
- this.computeHeight();
- }
- })
- );
+ this.observer = new _global.ResizeObserver(() => {
+ if (this.layoutDoc.layout_autoHeight && ref && this.refList.size && !SnappingManager.IsDragging) {
+ this.computeHeight();
+ }
+ });
this.layoutDoc.layout_autoHeight && this.computeHeight();
this.observer.observe(ref);
}
};
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer?.();
- if ((this._mainEle = ele)) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.Document, this.onInternalPreDrop.bind(this));
+ this._mainEle = ele;
+ if (ele) this._treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.Document, this.onInternalPreDrop.bind(this));
};
protected onInternalDrop(e: Event, de: DragManager.DropEvent) {
@@ -169,7 +172,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
}
};
- dragConfig = (dragData: DragManager.DocumentDragData) => (dragData.treeViewDoc = this.Document);
+ dragConfig = (dragData: DragManager.DocumentDragData) => { dragData.treeViewDoc = this.Document; }; // prettier-ignore
screenToLocalTransform = () => this.ScreenToLocalBoxXf().translate(0, -this._headerHeight);
@@ -198,10 +201,10 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
@action
addDoc = (docs: Doc | Doc[], relativeTo: Opt<Doc>, before?: boolean): boolean => {
- const doclist = docs instanceof Doc ? [docs] : docs;
- const addDocRelativeTo = (doc: Doc | Doc[]) => doclist.reduce((flg, doc) => flg && Doc.AddDocToList(this.Document[DocData], this._props.fieldKey, doc, relativeTo, before), true);
+ const addDocRelativeTo = (adocs: Doc | Doc[]) => (adocs as Doc[]).reduce((flg, doc) => flg && Doc.AddDocToList(this.Document[DocData], this._props.fieldKey, doc, relativeTo, before), true);
if (this.Document.resolvedDataDoc instanceof Promise) return false;
- const res = relativeTo === undefined ? this._props.addDocument?.(docs) || false : addDocRelativeTo(docs);
+ const doclist = docs instanceof Doc ? [docs] : docs;
+ const res = relativeTo === undefined ? this._props.addDocument?.(doclist) || false : addDocRelativeTo(doclist);
res &&
doclist.forEach(doc => {
Doc.SetContainer(doc, this.Document);
@@ -209,7 +212,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
});
return res;
};
- onContextMenu = (e: React.MouseEvent): void => {
+ onContextMenu = (): void => {
// need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
const layoutItems: ContextMenuProps[] = [];
const menuDoc = ScriptCast(Cast(this.layoutDoc.layout_headerButton, Doc, null)?.onClick).script.originalScript === CollectionTreeView.AddTreeFunc;
@@ -217,11 +220,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
if (!Doc.noviceMode) {
layoutItems.push({
description: 'Make tree state ' + (this.Document.treeView_OpenIsTransient ? 'persistent' : 'transient'),
- event: () => (this.Document.treeView_OpenIsTransient = !this.Document.treeView_OpenIsTransient),
+ event: () => { this.Document.treeView_OpenIsTransient = !this.Document.treeView_OpenIsTransient; }, // prettier-ignore
icon: 'paint-brush',
});
- layoutItems.push({ description: (this.Document.treeView_HideHeaderFields ? 'Show' : 'Hide') + ' Header Fields', event: () => (this.Document.treeView_HideHeaderFields = !this.Document.treeView_HideHeaderFields), icon: 'paint-brush' });
- layoutItems.push({ description: (this.Document.treeView_HideTitle ? 'Show' : 'Hide') + ' Title', event: () => (this.Document.treeView_HideTitle = !this.Document.treeView_HideTitle), icon: 'paint-brush' });
+ layoutItems.push({ description: (this.Document.treeView_HideHeaderFields ? 'Show' : 'Hide') + ' Header Fields', event: () => { this.Document.treeView_HideHeaderFields = !this.Document.treeView_HideHeaderFields; }, icon: 'paint-brush' }); // prettier-ignore
+ layoutItems.push({ description: (this.Document.treeView_HideTitle ? 'Show' : 'Hide') + ' Title', event: () => { this.Document.treeView_HideTitle = !this.Document.treeView_HideTitle; }, icon: 'paint-brush' }); // prettier-ignore
}
ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' });
if (!Doc.noviceMode) {
@@ -240,9 +243,9 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return (
<EditableView
contents={this.dataDoc.title}
- display={'block'}
+ display="block"
maxHeight={72}
- height={'auto'}
+ height="auto"
GetValue={() => StrCast(this.dataDoc.title)}
SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
if (enter && this.Document.treeView_Type === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
@@ -253,22 +256,24 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
);
}
- onKey = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
+ onKey = (e: React.KeyboardEvent /* , fieldProps: FieldViewProps */) => {
if (this.outlineMode && e.key === 'Enter') {
e.stopPropagation();
this.makeTextCollection(this.treeChildren);
return true;
}
+ return undefined;
};
get documentTitle() {
return (
<FormattedTextBox
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
fieldKey="text"
renderDepth={this._props.renderDepth + 1}
isContentActive={this.isContentActive}
isDocumentActive={this.isContentActive}
- forceAutoHeight={true} // needed to make the title resize even if the rest of the tree view is not layout_autoHeight
+ forceAutoHeight // needed to make the title resize even if the rest of the tree view is not layout_autoHeight
PanelWidth={this.documentTitleWidth}
PanelHeight={this.documentTitleHeight}
NativeDimScaling={returnOne}
@@ -296,7 +301,12 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
const dragAction = StrCast(this.Document.childDragAction) as any as dropActionType;
const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this._props.moveDocument?.(d, target, addDoc) || false;
- if (this._renderCount < this.treeChildren.length) setTimeout(action(() => (this._renderCount = Math.min(this.treeChildren.length, this._renderCount + 20))));
+ if (this._renderCount < this.treeChildren.length)
+ setTimeout(
+ action(() => {
+ this._renderCount = Math.min(this.treeChildren.length, this._renderCount + 20);
+ })
+ );
return TreeView.GetChildElements(
this.treeChildren,
this,
@@ -326,7 +336,6 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
this.observeHeight,
this.unobserveHeight,
this.childContextMenuItems(),
- //TODO: [AL] add these
this._props.AddToMap,
this._props.RemFromMap,
this._props.hierarchyIndex,
@@ -337,7 +346,9 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return this.dataDoc === null ? null : (
<div
className="collectionTreeView-titleBar"
- ref={action((r: any) => (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.ScreenToLocalBoxXf().Scale))}
+ ref={action((r: any) => {
+ (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.ScreenToLocalBoxXf().Scale);
+ })}
key={this.Document[Id]}
style={!this.outlineMode ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
{this.outlineMode ? this.documentTitle : this.editableTitle}
@@ -420,7 +431,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%', pointerEvents: 'all' }}>
{!this.buttonMenu && !this.noviceExplainer ? null : (
- <div className="documentButtonMenu" ref={action((r: HTMLDivElement | null) => r && (this._headerHeight = DivHeight(r)))}>
+ <div
+ className="documentButtonMenu"
+ ref={action((r: HTMLDivElement | null) => {
+ r && (this._headerHeight = DivHeight(r));
+ })}>
{this.buttonMenu}
{this.noviceExplainer}
</div>
@@ -453,7 +468,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
minHeight: '100%',
}}
onWheel={e => e.stopPropagation()}
- onClick={e => (!this.layoutDoc.forceActive ? this._props.select(false) : SelectionManager.DeselectAll())}
+ onClick={() => (!this.layoutDoc.forceActive ? this._props.select(false) : SelectionManager.DeselectAll())}
onDrop={this.onTreeDrop}>
<ul className={`no-indent${this.outlineMode ? '-outline' : ''}`}>{this.treeViewElements}</ul>
</div>
@@ -470,13 +485,14 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
<div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%` }}>
{!(this.Document instanceof Doc) || !this.treeChildren ? null : this.Document.treeView_HasOverlay ? (
<CollectionFreeFormView
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
setContentViewBox={emptyFunction}
NativeWidth={returnZero}
NativeHeight={returnZero}
pointerEvents={this._props.isContentActive() && SnappingManager.IsDragging ? returnAll : returnNone}
- isAnnotationOverlay={true}
- isAnnotationOverlayScrollable={true}
+ isAnnotationOverlay
+ isAnnotationOverlayScrollable
childDocumentsActive={this._props.isContentActive}
fieldKey={this._props.fieldKey + '_annotations'}
dropAction={dropActionType.move}
@@ -500,6 +516,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
}
}
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function addTreeFolder(doc: Doc) {
CollectionTreeView.addTreeFolder(doc);
});
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 8a2e83ed9..a661cf6a2 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -32,7 +32,7 @@ import { ObservableReactComponent } from '../ObservableReactComponent';
import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
import { Colors } from '../global/globalEnums';
import { DocumentView, OpenWhere, OpenWhereMod, returnEmptyDocViewList } from '../nodes/DocumentView';
-import { FieldViewProps, FocusViewOptions } from '../nodes/FieldView';
+import { FieldViewProps } from '../nodes/FieldView';
import { KeyValueBox } from '../nodes/KeyValueBox';
import { PresBox, PresMovement } from '../nodes/trails';
import { CollectionDockingView } from './CollectionDockingView';
@@ -42,6 +42,146 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
const _global = (window /* browser */ || global) /* node */ as any;
+interface TabMinimapViewProps {
+ document: Doc;
+ tabView: () => DocumentView | undefined;
+ addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean;
+ PanelWidth: () => number;
+ PanelHeight: () => number;
+ background: () => string;
+}
+interface TabMiniThumbProps {
+ miniWidth: () => number;
+ miniHeight: () => number;
+ miniTop: () => number;
+ miniLeft: () => number;
+}
+
+@observer
+class TabMiniThumb extends React.Component<TabMiniThumbProps> {
+ render() {
+ const { miniWidth, miniHeight, miniLeft, miniTop } = this.props;
+ return <div className="miniThumb" style={{ width: `${miniWidth()}%`, height: `${miniHeight()}%`, left: `${miniLeft()}%`, top: `${miniTop()}%` }} />;
+ }
+}
+@observer
+export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps> {
+ static miniStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string): any => {
+ if (doc) {
+ switch (property.split(':')[0]) {
+ 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';
+ case DocumentType.IMG: return 'blue';
+ case DocumentType.MAP: return 'orange';
+ case DocumentType.VID: return 'purple';
+ case DocumentType.RTF: return 'yellow';
+ case DocumentType.COL: return undefined;
+ default: return 'gray';
+ } // 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
+ }
+ return undefined;
+ };
+
+ @computed get renderBounds() {
+ const compView = this._props.tabView()?.ComponentView as CollectionFreeFormView;
+ const bounds = compView?.freeformData?.(true)?.bounds;
+ if (!bounds) return undefined;
+ const xbounds = bounds.r - bounds.x;
+ const ybounds = bounds.b - bounds.y;
+ const dim = Math.max(xbounds, ybounds);
+ return { l: bounds.x + xbounds / 2 - dim / 2, t: bounds.y + ybounds / 2 - dim / 2, cx: bounds.x + xbounds / 2, cy: bounds.y + ybounds / 2, dim };
+ }
+ @computed get xPadding() {
+ return !this.renderBounds ? 0 : Math.max(0, this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) - 2 * (this.renderBounds.cx - this.renderBounds.l));
+ }
+ @computed get yPadding() {
+ return !this.renderBounds ? 0 : Math.max(0, this._props.PanelHeight() / NumCast(this._props.document._freeform_scale, 1) - 2 * (this.renderBounds.cy - this.renderBounds.l));
+ }
+ childLayoutTemplate = () => Cast(this._props.document.childLayoutTemplate, Doc, null);
+ returnMiniSize = () => NumCast(this._props.document._miniMapSize, 150);
+ miniDown = (e: React.PointerEvent) => {
+ const doc = this._props.document;
+ const miniSize = this.returnMiniSize();
+ doc &&
+ setupMoveUpEvents(
+ this,
+ e,
+ action((moveEv, down: number[], delta: number[]) => {
+ const renderBounds = this.renderBounds ?? { l: 0, r: 0, t: 0, b: 0, dim: 1 };
+ doc._freeform_panX = clamp(NumCast(doc._freeform_panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
+ doc._freeform_panY = clamp(NumCast(doc._freeform_panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
+ return false;
+ }),
+ emptyFunction,
+ emptyFunction
+ );
+ };
+ popup = () => {
+ if (!this.renderBounds) return <div />;
+ const { renderBounds } = this;
+ const miniWidth = () => (this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100;
+ const miniHeight = () => (this._props.PanelHeight() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100;
+ const miniLeft = () => 50 + ((NumCast(this._props.document._freeform_panX) - renderBounds.cx) / renderBounds.dim) * 100 - miniWidth() / 2;
+ const miniTop = () => 50 + ((NumCast(this._props.document._freeform_panY) - renderBounds.cy) / renderBounds.dim) * 100 - miniHeight() / 2;
+ const miniSize = this.returnMiniSize();
+ return (
+ <div className="miniMap" style={{ width: miniSize, height: miniSize, background: this._props.background() }}>
+ <CollectionFreeFormView
+ Document={this._props.document}
+ docViewPath={returnEmptyDocViewList}
+ childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this.
+ noOverlay // don't render overlay Docs since they won't scale
+ isContentActive={emptyFunction}
+ isAnyChildContentActive={returnFalse}
+ select={emptyFunction}
+ isSelected={returnFalse}
+ dontRegisterView
+ fieldKey={Doc.LayoutFieldKey(this._props.document)}
+ addDocument={returnFalse}
+ moveDocument={returnFalse}
+ removeDocument={returnFalse}
+ PanelWidth={this.returnMiniSize}
+ PanelHeight={this.returnMiniSize}
+ ScreenToLocalTransform={Transform.Identity}
+ renderDepth={0}
+ whenChildContentsActiveChanged={emptyFunction}
+ focus={emptyFunction}
+ styleProvider={TabMinimapView.miniStyleProvider}
+ addDocTab={this._props.addDocTab}
+ // eslint-disable-next-line no-use-before-define
+ pinToPres={TabDocView.PinDoc}
+ childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
+ childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
+ searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
+ fitContentsToBox={returnTrue}
+ xPadding={this.xPadding}
+ yPadding={this.yPadding}
+ />
+ <div className="miniOverlay" onPointerDown={this.miniDown}>
+ <TabMiniThumb miniLeft={miniLeft} miniTop={miniTop} miniWidth={miniWidth} miniHeight={miniHeight} />
+ </div>
+ </div>
+ );
+ };
+ 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={SnappingManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement="top-end" popup={this.popup} />
+ </div>
+ );
+ }
+}
+
interface TabDocViewProps {
documentId: FieldId;
keyValue?: boolean;
@@ -92,7 +232,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
@action
init = (tab: any, doc: Opt<Doc>) => {
if (tab.contentItem === tab.header.parent.getActiveContentItem()) this._activated = true;
- if (tab.DashDoc !== doc && doc && tab.hasOwnProperty('contentItem') && tab.contentItem.config.type !== 'stack') {
+ if (tab.DashDoc !== doc && doc && tab.contentItem?.config.type !== 'stack') {
tab._disposers = {} as { [name: string]: IReactionDisposer };
tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true);
tab.DashDoc = doc;
@@ -130,17 +270,17 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
setupMoveUpEvents(
this,
e,
- e =>
- !e.defaultPrevented &&
- DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY, undefined, () => {
+ moveEv =>
+ !moveEv.defaultPrevented &&
+ DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), moveEv.clientX, moveEv.clientY, undefined, () => {
CollectionDockingView.CloseSplit(doc);
}),
returnFalse,
- action(e => {
+ action(clickEv => {
if (this.view) {
SelectionManager.SelectView(this.view, false);
const child = getChild();
- simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ simulateMouseClick(child, clickEv.clientX, clickEv.clientY + 30, clickEv.screenX, clickEv.screenY + 30);
} else {
this._activated = true;
setTimeout(() => this.view && SelectionManager.SelectView(this.view, false));
@@ -160,7 +300,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
({ variant, degree, highlight }) => {
const color = highlight?.highlightIndex === Doc.DocBrushStatus.highlighted ? highlight.highlightColor : degree ? ['transparent', variant, variant, 'orange'][degree] : variant;
- const textColor = color === variant ? SnappingManager.userColor : lightOrDark(color);
+ const textColor = color === variant ? SnappingManager.userColor ?? '' : lightOrDark(color);
titleEle.style.color = textColor;
iconWrap.style.color = textColor;
closeWrap.style.color = textColor;
@@ -186,19 +326,19 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
);
}
// shifts the focus to this tab when another tab is dragged over it
- tab.element[0].onmouseenter = (e: MouseEvent) => {
+ tab.element[0].onmouseenter = () => {
if (SnappingManager.IsDragging && tab.contentItem !== tab.header.parent.getActiveContentItem()) {
tab.header.parent.setActiveContentItem(tab.contentItem);
tab.setActive(true);
}
this._document && Doc.BrushDoc(this._document);
};
- tab.element[0].onmouseleave = (e: MouseEvent) => {
+ tab.element[0].onmouseleave = () => {
this._document && Doc.UnBrushDoc(this._document);
};
tab.element[0].oncontextmenu = (e: MouseEvent) => {
- let child = getChild();
+ const child = getChild();
if (child) {
simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
e.stopPropagation();
@@ -220,12 +360,9 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
() => SelectionManager.IsSelected(this._document),
action(selected => {
if (selected) this._activated = true;
- const toggle = tab.element[0].children[2].children[0] as HTMLInputElement;
if (selected && tab.contentItem !== tab.header.parent.getActiveContentItem()) {
undoable(() => tab.header.parent.setActiveContentItem(tab.contentItem), 'tab switch')();
}
- //toggle.style.fontWeight = selected ? 'bold' : '';
- // toggle.style.textTransform = selected ? "uppercase" : "";
}),
{ fireImmediately: true }
);
@@ -233,14 +370,16 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
// highlight the tab when the tab document is brushed in any part of the UI
tab._disposers.reactionDisposer = reaction(
() => doc?.title,
- title => (titleEle.value = title),
+ title => {
+ titleEle.value = title;
+ },
{ fireImmediately: true }
);
// clean up the tab when it is closed
tab.closeElement
- .off('click') //unbind the current click handler
- .click(function () {
+ .off('click') // unbind the current click handler
+ .click(() => {
Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
SelectionManager.DeselectAll();
UndoManager.RunInBatch(() => tab.contentItem.remove(), 'delete tab');
@@ -250,7 +389,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
/**
* Adds a document to the presentation view
- **/
+ * */
@action
public static PinDoc(docs: Doc | Doc[], pinProps: PinProps) {
const docList = docs instanceof Doc ? [docs] : docs;
@@ -310,7 +449,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
if (curPres.expandBoolean) pinDoc.presentation_expandInlineButton = true;
Doc.AddDocToList(curPres, 'data', pinDoc, PresBox.Instance?.sortArray()?.lastElement());
PresBox.Instance?.clearSelectedArray();
- pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); //Update selected array
+ pinDoc && PresBox.Instance?.addToSelectedArray(pinDoc); // Update selected array
});
if (
// open the presentation trail if it's not already opened
@@ -328,6 +467,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
componentDidMount() {
new _global.ResizeObserver(
action((entries: any) => {
+ // eslint-disable-next-line no-restricted-syntax
for (const entry of entries) {
this._panelWidth = entry.contentRect.width;
this._panelHeight = entry.contentRect.height;
@@ -374,29 +514,30 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
// "replace:right" - will replace the stack on the right named "right" if it exists, or create a stack on the right with that name,
// "replace:monkeys" - will replace any tab that has the label 'monkeys', or a tab with that label will be created by default on the right
// lightbox - will add the document to any collection along the path from the document to the docking view that has a field isLightbox. if none is found, it adds to the full screen lightbox
- addDocTab = (doc: Doc, location: OpenWhere) => {
+ addDocTab = (docsIn: Doc | Doc[], location: OpenWhere) => {
+ const docs = docsIn instanceof Doc ? [docsIn] : docsIn;
SelectionManager.DeselectAll();
const whereFields = location.split(':');
const keyValue = whereFields.includes(OpenWhereMod.keyvalue);
const whereMods = whereFields.length > 1 ? (whereFields[1] as OpenWhereMod) : OpenWhereMod.none;
const panelName = whereFields.length > 1 ? whereFields.lastElement() : '';
- if (doc.dockingConfig && !keyValue) return DashboardView.openDashboard(doc);
+ if (docs[0]?.dockingConfig && !keyValue) return DashboardView.openDashboard(docs[0]);
// prettier-ignore
switch (whereFields[0]) {
case undefined:
case OpenWhere.lightbox: if (this.layoutDoc?._isLightbox) {
- const lightboxView = !doc.annotationOn && DocCast(doc.embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(doc.embedContainer)) : undefined;
+ const lightboxView = !docs[0].annotationOn && DocCast(docs[0].embedContainer) ? DocumentManager.Instance.getFirstDocumentView(DocCast(docs[0].embedContainer)) : undefined;
const data = lightboxView?.dataDoc[Doc.LayoutFieldKey(lightboxView.Document)];
if (lightboxView && (!data || data instanceof List)) {
- lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.Document)] = new List<Doc>([doc]);
+ lightboxView.layoutDoc[Doc.LayoutFieldKey(lightboxView.Document)] = new List<Doc>(docs);
return true;
}
}
- return LightboxView.Instance.AddDocTab(doc, OpenWhere.lightbox);
- case OpenWhere.close: return CollectionDockingView.CloseSplit(doc, whereMods);
- case OpenWhere.replace: return CollectionDockingView.ReplaceTab(doc, whereMods, this.stack, panelName, undefined, keyValue);
- case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, TabDocView.DontSelectOnActivate, keyValue);
- case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, this.stack, undefined, keyValue);
+ return LightboxView.Instance.AddDocTab(docs[0], OpenWhere.lightbox);
+ case OpenWhere.close: return CollectionDockingView.CloseSplit(docs[0], whereMods);
+ case OpenWhere.replace: return CollectionDockingView.ReplaceTab(docs[0], whereMods, this.stack, panelName, undefined, keyValue);
+ case OpenWhere.toggle: return CollectionDockingView.ToggleSplit(docs[0], whereMods, this.stack, TabDocView.DontSelectOnActivate, keyValue);
+ case OpenWhere.add:default:return CollectionDockingView.AddSplit(docs[0], whereMods, this.stack, undefined, keyValue);
}
};
remDocTab = (doc: Doc | Doc[]) => {
@@ -410,12 +551,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
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);
+ const tab = Array.from(CollectionDockingView.Instance?.tabMap!).find(findTab => findTab.DashDoc === tabDoc && !findTab.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)
return tab !== undefined;
};
@action
- focusFunc = (doc: Doc, options: FocusViewOptions) => {
+ focusFunc = () => {
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
}
@@ -498,8 +639,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
}
this._lastTab = this.tab;
(this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
- DocServer.GetRefField(this._props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
- new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
+ DocServer.GetRefField(this._props.documentId).then(
+ action(doc => {
+ doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document);
+ })
+ );
+ new _global.ResizeObserver(action(() => this._forceInvalidateScreenToLocal++)).observe(ref);
}
}}>
{this.docView}
@@ -507,141 +652,3 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
);
}
}
-
-interface TabMinimapViewProps {
- document: Doc;
- tabView: () => DocumentView | undefined;
- addDocTab: (doc: Doc, where: OpenWhere) => boolean;
- PanelWidth: () => number;
- PanelHeight: () => number;
- background: () => string;
-}
-interface TabMiniThumbProps {
- miniWidth: () => number;
- miniHeight: () => number;
- miniTop: () => number;
- miniLeft: () => number;
-}
-
-@observer
-class TabMiniThumb extends React.Component<TabMiniThumbProps> {
- render() {
- const { miniWidth, miniHeight, miniLeft, miniTop } = this.props;
- return <div className="miniThumb" style={{ width: `${miniWidth()}%`, height: `${miniHeight()}%`, left: `${miniLeft()}%`, top: `${miniTop()}%` }} />;
- }
-}
-@observer
-export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps> {
- static miniStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string): any => {
- if (doc) {
- switch (property.split(':')[0]) {
- 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';
- case DocumentType.IMG: return 'blue';
- case DocumentType.MAP: return 'orange';
- case DocumentType.VID: return 'purple';
- case DocumentType.RTF: return 'yellow';
- case DocumentType.COL: return undefined;
- default: return 'gray';
- } // 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
- }
- };
-
- @computed get renderBounds() {
- const compView = this._props.tabView()?.ComponentView as CollectionFreeFormView;
- const bounds = compView?.freeformData?.(true)?.bounds;
- if (!bounds) return undefined;
- const xbounds = bounds.r - bounds.x;
- const ybounds = bounds.b - bounds.y;
- const dim = Math.max(xbounds, ybounds);
- return { l: bounds.x + xbounds / 2 - dim / 2, t: bounds.y + ybounds / 2 - dim / 2, cx: bounds.x + xbounds / 2, cy: bounds.y + ybounds / 2, dim };
- }
- @computed get xPadding() {
- return !this.renderBounds ? 0 : Math.max(0, this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) - 2 * (this.renderBounds.cx - this.renderBounds.l));
- }
- @computed get yPadding() {
- return !this.renderBounds ? 0 : Math.max(0, this._props.PanelHeight() / NumCast(this._props.document._freeform_scale, 1) - 2 * (this.renderBounds.cy - this.renderBounds.l));
- }
- childLayoutTemplate = () => Cast(this._props.document.childLayoutTemplate, Doc, null);
- returnMiniSize = () => NumCast(this._props.document._miniMapSize, 150);
- miniDown = (e: React.PointerEvent) => {
- const doc = this._props.document;
- const miniSize = this.returnMiniSize();
- doc &&
- setupMoveUpEvents(
- this,
- e,
- action((e: PointerEvent, down: number[], delta: number[]) => {
- const renderBounds = this.renderBounds ?? { l: 0, r: 0, t: 0, b: 0, dim: 1 };
- doc._freeform_panX = clamp(NumCast(doc._freeform_panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
- doc._freeform_panY = clamp(NumCast(doc._freeform_panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
- return false;
- }),
- emptyFunction,
- emptyFunction
- );
- };
- popup = () => {
- if (!this.renderBounds) return <></>;
- const renderBounds = this.renderBounds;
- const miniWidth = () => (this._props.PanelWidth() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100;
- const miniHeight = () => (this._props.PanelHeight() / NumCast(this._props.document._freeform_scale, 1) / renderBounds.dim) * 100;
- const miniLeft = () => 50 + ((NumCast(this._props.document._freeform_panX) - renderBounds.cx) / renderBounds.dim) * 100 - miniWidth() / 2;
- const miniTop = () => 50 + ((NumCast(this._props.document._freeform_panY) - renderBounds.cy) / renderBounds.dim) * 100 - miniHeight() / 2;
- const miniSize = this.returnMiniSize();
- return (
- <div className="miniMap" style={{ width: miniSize, height: miniSize, background: this._props.background() }}>
- <CollectionFreeFormView
- Document={this._props.document}
- docViewPath={returnEmptyDocViewList}
- childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this.
- noOverlay={true} // don't render overlay Docs since they won't scale
- isContentActive={emptyFunction}
- isAnyChildContentActive={returnFalse}
- select={emptyFunction}
- isSelected={returnFalse}
- dontRegisterView={true}
- fieldKey={Doc.LayoutFieldKey(this._props.document)}
- addDocument={returnFalse}
- moveDocument={returnFalse}
- removeDocument={returnFalse}
- PanelWidth={this.returnMiniSize}
- PanelHeight={this.returnMiniSize}
- ScreenToLocalTransform={Transform.Identity}
- renderDepth={0}
- whenChildContentsActiveChanged={emptyFunction}
- focus={emptyFunction}
- styleProvider={TabMinimapView.miniStyleProvider}
- addDocTab={this._props.addDocTab}
- pinToPres={TabDocView.PinDoc}
- childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
- childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
- searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
- fitContentsToBox={returnTrue}
- xPadding={this.xPadding}
- yPadding={this.yPadding}
- />
- <div className="miniOverlay" onPointerDown={this.miniDown}>
- <TabMiniThumb miniLeft={miniLeft} miniTop={miniTop} miniWidth={miniWidth} miniHeight={miniHeight} />
- </div>
- </div>
- );
- };
- 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={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 20323a521..fab8e3892 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -55,7 +55,7 @@ export interface TreeViewProps {
treeViewParent: Doc;
renderDepth: number;
dragAction: dropActionType;
- addDocTab: (doc: Doc, where: OpenWhere) => boolean;
+ addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean;
panelWidth: () => number;
panelHeight: () => number;
addDocument: (doc: Doc | Doc[], annotationKey?: string, relativeTo?: Doc, before?: boolean) => boolean;
@@ -200,11 +200,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}
return false;
};
- @undoBatch remove = (doc: Doc | Doc[], key: string) => {
+ @undoBatch remove = (docs: Doc | Doc[], key: string) => {
this.treeView._props.select(false);
- const ind = DocListCast(this.dataDoc[key]).indexOf(doc instanceof Doc ? doc : doc.lastElement());
+ const ind = DocListCast(this.dataDoc[key]).indexOf(docs instanceof Doc ? docs : docs.lastElement());
- const res = (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
+ const res = (docs instanceof Doc ? [docs] : docs).reduce((flg, doc) => flg && Doc.RemoveDocFromList(this.dataDoc, key, doc), true);
res && ind > 0 && DocumentManager.Instance.getDocumentView(DocListCast(this.dataDoc[key])[ind - 1], this.treeView.DocumentView?.())?.select(false);
return res;
};
@@ -318,7 +318,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this._props.hierarchyIndex !== undefined && this._props.AddToMap?.(this.Document, this._props.hierarchyIndex);
}
- onDragUp = (e: PointerEvent) => {
+ onDragUp = () => {
document.removeEventListener('pointerup', this.onDragUp, true);
document.removeEventListener('pointermove', this.onDragMove, true);
};
@@ -403,7 +403,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
if (!this._header.current) return false;
const rect = this._header.current.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
+ const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || !!(!before && this.treeViewOpen && this.childDocs?.length);
if (de.complete.linkDragData) {
const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor();
const destDoc = this.Document;
@@ -431,14 +431,14 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return false;
};
- localAdd = (doc: Doc | Doc[]) => {
- const innerAdd = (doc: Doc) => {
+ localAdd = (docs: Doc | Doc[]): boolean => {
+ const innerAdd = (doc: Doc): boolean => {
const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[this.fieldKey])) instanceof ComputedField;
const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, this.fieldKey, doc);
dataIsComputed && Doc.SetContainer(doc, DocCast(this.Document.embedContainer));
return added;
};
- return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
+ return (docs instanceof Doc ? [docs] : docs).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
};
dropping: boolean = false;
@@ -513,16 +513,16 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
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);
- const moveDoc = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.move(doc, target, addDoc);
- const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => {
- const innerAdd = (doc: Doc) => {
+ const remDoc = (docs: Doc | Doc[]) => this.remove(docs, key);
+ const moveDoc = (docs: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.move(docs, target, addDoc);
+ const addDoc = (docs: Doc | Doc[], addBefore?: Doc, before?: boolean) => {
+ const innerAdd = (iDoc: Doc) => {
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, true);
- dataIsComputed && Doc.SetContainer(doc, DocCast(this.Document.embedContainer));
+ const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, iDoc, addBefore, before, false, true);
+ dataIsComputed && Doc.SetContainer(iDoc, DocCast(this.Document.embedContainer));
return added;
};
- return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
+ return (docs instanceof Doc ? [docs] : docs).reduce((flg, iDoc) => flg && innerAdd(iDoc), true as boolean);
};
contentElement = TreeView.GetChildElements(
contents instanceof Doc ? [contents] : DocListCast(contents),
@@ -643,7 +643,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return added;
};
- const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
+ const addDoc = (docs: Doc | Doc[], addBefore?: Doc, before?: boolean) => (docs instanceof Doc ? [docs] : docs).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;
let downY = 0;
@@ -911,7 +911,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
// 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.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;
@@ -1192,7 +1192,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
const pt = [de.clientX, de.clientY];
const rect = this._header.current!.getBoundingClientRect();
const before = pt[1] < rect.top + rect.height / 2;
- const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
+ const inside = this.treeView.fileSysMode && !this.Document.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || !!(!before && this.treeViewOpen && this.childDocs?.length);
this.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, dropActionType.copy, undefined, undefined, false, false));
};
@@ -1259,7 +1259,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
remove: undefined | ((doc: Doc | Doc[]) => boolean),
move: DragManager.MoveFunction,
dragAction: dropActionType,
- addDocTab: (doc: Doc, where: OpenWhere) => boolean,
+ addDocTab: (doc: Doc | Doc[], where: OpenWhere) => boolean,
styleProvider: undefined | StyleProviderFuncType,
screenToLocalXf: () => Transform,
isContentActive: (outsideReaction?: boolean) => boolean,
@@ -1282,11 +1282,6 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
hierarchyIndex?: number[],
renderCount?: number
) {
- 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(treeViewParent.treeView_SortCriterion, TreeSort.WhenAdded));
const rowWidth = () => panelWidth() - treeBulletWidth() * (treeView._props.NativeDimScaling?.() || 1);
const treeViewRefs = new Map<Doc, TreeView | undefined>();
@@ -1327,7 +1322,6 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
dataDoc={pair.data}
treeViewParent={treeViewParent}
prevSibling={docs[i]}
- // TODO: [AL] add these
hierarchyIndex={hierarchyIndex ? [...hierarchyIndex, i + 1] : undefined}
AddToMap={AddToMap}
RemFromMap={RemFromMap}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
index 29d835b28..65a529d62 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx
@@ -4,7 +4,6 @@ import * as React from 'react';
import { Doc, DocListCast, FieldType, FieldResult } from '../../../../fields/Doc';
import { InkTool } from '../../../../fields/InkField';
import { StrCast } from '../../../../fields/Types';
-import { DocumentManager } from '../../../util/DocumentManager';
import { LinkManager } from '../../../util/LinkManager';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton';
@@ -49,8 +48,8 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
setupStates = () => {
this._originalbackground = StrCast(this._props.Document[DocData].backgroundColor);
// state entry functions
- const setBackground = (colour: string) => () => {this._props.Document[DocData].backgroundColor = colour;} // prettier-ignore
- const setOpacity = (opacity: number) => () => {this._props.LayoutDoc.opacity = opacity;} // prettier-ignore
+ // 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.childDocs().length ? this._props.childDocs()[0] : undefined);
const numDocs = () => this._props.childDocs().length;
@@ -73,7 +72,6 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
let trail: number;
- const trailView = () => DocumentManager.Instance.DocumentViews.find(view => view.Document === Doc.MyTrails);
const presentationMode = () => Doc.ActivePresentation?.presentation_status;
// set of states
@@ -83,6 +81,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
docCreated: [() => numDocs(), () => {
docX = firstDoc()?.x;
docY = firstDoc()?.y;
+ // eslint-disable-next-line no-use-before-define
return oneDoc;
}],
}
@@ -93,18 +92,20 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
{
// docCreated: [() => numDocs() > 1, () => multipleDocs],
docDeleted: [() => numDocs() < 1, () => start],
- docMoved: [() => (docX && docX != docNewX()) || (docY && docY != docNewY()), () => {
+ docMoved: [() => (docX && docX !== docNewX()) || (docY && docY !== docNewY()), () => {
docX = firstDoc()?.x;
docY = firstDoc()?.y;
+ // eslint-disable-next-line no-use-before-define
return movedDoc;
}],
}
); // prettier-ignore
const movedDoc = InfoState(
- 'Great moves. Try creating a second document. You can see the list of supported document types by typing a colon (\":\")',
+ 'Great moves. Try creating a second document. You can see the list of supported document types by typing a colon (":")',
{
- docCreated: [() => numDocs() == 2, () => multipleDocs],
+ // eslint-disable-next-line no-use-before-define
+ docCreated: [() => numDocs() === 2, () => multipleDocs],
docDeleted: [() => numDocs() < 1, () => start],
},
'dash-colon-menu.gif',
@@ -114,6 +115,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
const multipleDocs = InfoState(
'Let\'s create a new link. Click the link icon on one of your documents.',
{
+ // eslint-disable-next-line no-use-before-define
linkStarted: [() => linkStart(), () => startedLink],
docRemoved: [() => numDocs() < 2, () => oneDoc],
},
@@ -124,6 +126,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
'Now click the highlighted link icon on your other document.',
{
linkUnstart: [() => linkUnstart(), () => multipleDocs],
+ // eslint-disable-next-line no-use-before-define
linkCreated: [() => numDocLinks(), () => madeLink],
docRemoved: [() => numDocs() < 2, () => oneDoc],
},
@@ -136,6 +139,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
linkCreated: [() => !numDocLinks(), () => multipleDocs],
linkViewed: [() => linkMenuOpen(), () => {
alert(numDocLinks() + " cheer for " + numDocLinks() + " link!");
+ // eslint-disable-next-line no-use-before-define
return viewedLink;
}],
},
@@ -147,10 +151,12 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
{
linkDeleted: [() => !numDocLinks(), () => multipleDocs],
docRemoved: [() => numDocs() < 2, () => oneDoc],
- docCreated: [() => numDocs() == 3, () => {
+ docCreated: [() => numDocs() === 3, () => {
trail = pin().length;
+ // eslint-disable-next-line no-use-before-define
return presentDocs;
}],
+ // eslint-disable-next-line no-use-before-define
activePen: [() => activeTool() === InkTool.Pen, () => penMode],
},
'documentation.png',
@@ -164,6 +170,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
() => pin().length > trail,
() => {
trail = pin().length;
+ // eslint-disable-next-line no-use-before-define
return pinnedDoc1;
},
],
@@ -186,11 +193,13 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
() => pin().length > trail,
() => {
trail = pin().length;
+ // eslint-disable-next-line no-use-before-define
return pinnedDoc2;
},
],
// editPresentation: [() => presentationMode() === 'edit', () => editPresentationMode],
// manualPresentation: [() => presentationMode() === 'manual', () => manualPresentationMode],
+ // eslint-disable-next-line no-use-before-define
autoPresentation: [() => presentationMode() === 'auto', () => autoPresentationMode],
docRemoved: [() => numDocs() < 3, () => viewedLink],
});
@@ -200,11 +209,13 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
() => pin().length > trail,
() => {
trail = pin().length;
+ // eslint-disable-next-line no-use-before-define
return pinnedDoc3;
},
],
// editPresentation: [() => presentationMode() === 'edit', () => editPresentationMode],
// manualPresentation: [() => presentationMode() === 'manual', () => manualPresentationMode],
+ // eslint-disable-next-line no-use-before-define
autoPresentation: [() => presentationMode() === 'auto', () => autoPresentationMode],
docRemoved: [() => numDocs() < 3, () => viewedLink],
});
@@ -219,6 +230,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
],
// editPresentation: [() => presentationMode() === 'edit', () => editPresentationMode],
// manualPresentation: [() => presentationMode() === 'manual', () => manualPresentationMode],
+ // eslint-disable-next-line no-use-before-define
autoPresentation: [() => presentationMode() === 'auto', () => autoPresentationMode],
docRemoved: [() => numDocs() < 3, () => viewedLink],
});
@@ -236,15 +248,18 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent<Collectio
const manualPresentationMode = InfoState("You're in manual presentation mode.", {
// editPresentation: [() => presentationMode() === 'edit', () => editPresentationMode],
+ // eslint-disable-next-line no-use-before-define
autoPresentation: [() => presentationMode() === 'auto', () => autoPresentationMode],
docRemoved: [() => numDocs() < 3, () => viewedLink],
- docCreated: [() => numDocs() == 4, () => completed],
+ // eslint-disable-next-line no-use-before-define
+ docCreated: [() => numDocs() === 4, () => completed],
});
const autoPresentationMode = InfoState("You're in auto presentation mode.", {
// editPresentation: [() => presentationMode() === 'edit', () => editPresentationMode],
manualPresentation: [() => presentationMode() === 'manual', () => manualPresentationMode],
docRemoved: [() => numDocs() < 3, () => viewedLink],
+ // eslint-disable-next-line no-use-before-define
docCreated: [() => numDocs() === 4, () => completed],
});
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index a0b96c75a..3970c6807 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable no-use-before-define */
import { Doc, Field, FieldType, FieldResult } from '../../../../fields/Doc';
import { Id, ToString } from '../../../../fields/FieldSymbols';
import { ObjectField } from '../../../../fields/ObjectField';
@@ -48,7 +49,7 @@ export interface PoolData {
export interface ViewDefResult {
ele: JSX.Element;
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
+ 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<FieldType>) {
if (typeof target === 'number' || Number(target)) {
@@ -84,9 +85,9 @@ interface PivotColumn {
filters: string[];
}
-export function computePassLayout(poolData: Map<string, PoolData>, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) {
+export function computePassLayout(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>();
- childPairs.forEach(({ layout, data }, i) => {
+ childPairs.forEach(({ layout, data }) => {
docMap.set(layout[Id], {
x: NumCast(layout.x),
y: NumCast(layout.y),
@@ -97,10 +98,15 @@ export function computePassLayout(poolData: Map<string, PoolData>, pivotDoc: Doc
replica: '',
});
});
+ // eslint-disable-next-line no-use-before-define
return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, []);
}
-export function computeStarburstLayout(poolData: Map<string, PoolData>, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) {
+function toNumber(val: FieldResult<FieldType>) {
+ return val === undefined ? undefined : NumCast(val, Number(StrCast(val)));
+}
+
+export function computeStarburstLayout(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 burstDiam = [NumCast(pivotDoc._width), NumCast(pivotDoc._height)];
const burstScale = NumCast(pivotDoc._starburstDocScale, 1);
@@ -132,7 +138,7 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
let nonNumbers = 0;
const pivotFieldKey = toLabel(engineProps?.pivotField ?? pivotDoc._pivotField) || 'author';
- childPairs.map(pair => {
+ childPairs.forEach(pair => {
const listValue = Cast(pair.layout[pivotFieldKey], listSpec('string'), null);
const num = toNumber(pair.layout[pivotFieldKey]);
@@ -184,11 +190,11 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
const textlen = Array.from(pivotColumnGroups.keys())
.map(c => getTextWidth(toLabel(c), desc))
.reduce((p, c) => Math.max(p, c), 0 as number);
- const max_text = Math.min(Math.ceil(textlen / 120) * 28, panelDim[1] / 2);
+ const maxText = Math.min(Math.ceil(textlen / 120) * 28, panelDim[1] / 2);
const maxInColumn = Array.from(pivotColumnGroups.values()).reduce((p, s) => Math.max(p, s.docs.length), 1);
const colWidth = panelDim[0] / pivotColumnGroups.size;
- const colHeight = panelDim[1] - max_text;
+ const colHeight = panelDim[1] - maxText;
let numCols = 0;
let bestArea = 0;
let pivotAxisWidth = 0;
@@ -212,7 +218,7 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
let x = 0;
const sortedPivotKeys = pivotNumbers ? Array.from(pivotColumnGroups.keys()).sort((n1: FieldResult, n2: FieldResult) => toNumber(n1)! - toNumber(n2)!) : Array.from(pivotColumnGroups.keys()).sort();
sortedPivotKeys.forEach(key => {
- const val = pivotColumnGroups.get(key)!;
+ const val = pivotColumnGroups.get(key);
let y = 0;
let xCount = 0;
const text = toLabel(key);
@@ -222,11 +228,11 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
x,
y: pivotAxisWidth,
width: pivotAxisWidth * expander * numCols,
- height: max_text,
+ height: maxText,
fontSize,
payload: val,
});
- val.docs.forEach((doc, i) => {
+ val?.docs.forEach((doc, i) => {
const layoutDoc = Doc.Layout(doc);
let wid = pivotAxisWidth;
let hgt = pivotAxisWidth / (Doc.NativeAspect(layoutDoc) || 1);
@@ -262,14 +268,11 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do
payload: pivotColumnGroups.get(key)!.filters,
}));
groupNames.push(...dividers);
- return normalizeResults(panelDim, max_text, docMap, poolData, viewDefsToJSX, groupNames, 0, []);
-}
-
-function toNumber(val: FieldResult<FieldType>) {
- return val === undefined ? undefined : NumCast(val, Number(StrCast(val)));
+ // eslint-disable-next-line no-use-before-define
+ return normalizeResults(panelDim, maxText, docMap, poolData, viewDefsToJSX, groupNames, 0, []);
}
-export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps?: any) {
+export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[] /* , engineProps?: any */) {
const fieldKey = 'data';
const pivotDateGroups = new Map<number, Doc[]>();
const docMap = new Map<string, PoolData>();
@@ -340,6 +343,7 @@ export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc:
if (!stack && (curTime === undefined || Math.abs(x - (curTime - minTime) * scaling) > pivotAxisWidth)) {
groupNames.push({ type: 'text', text: toLabel(key), x: x, y: stack * 25, height: fontHeight, fontSize, payload: undefined });
}
+ // eslint-disable-next-line no-use-before-define
layoutDocsAtTime(keyDocs, key);
});
if (sortedKeys.length && curTime !== undefined && curTime > sortedKeys[sortedKeys.length - 1]) {
@@ -404,7 +408,7 @@ function normalizeResults(
Array.from(docMap.entries())
.filter(ele => ele[1].pair)
- .map(ele => {
+ .forEach(ele => {
const newPosRaw = ele[1];
if (newPosRaw) {
const newPos: PoolData = {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index a70713429..d9c988d54 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable jsx-a11y/no-static-element-interactions */
import { Bezier } from 'bezier-js';
@@ -22,7 +23,6 @@ import { TraceMobx } from '../../../../fields/util';
import { Gestures, PointData } from '../../../../pen-gestures/GestureTypes';
import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
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';
@@ -48,6 +48,7 @@ import { DocumentView, OpenWhere } from '../../nodes/DocumentView';
import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { PresBox } from '../../nodes/trails/PresBox';
+// eslint-disable-next-line import/extensions
import { CreateImage } from '../../nodes/WebBoxRenderer';
import { StyleProp } from '../../StyleProvider';
import { CollectionSubView } from '../CollectionSubView';
@@ -76,7 +77,7 @@ export interface collectionFreeformViewProps {
@observer
export class CollectionFreeFormView extends CollectionSubView<Partial<collectionFreeformViewProps>>() {
public get displayName() {
- return 'CollectionFreeFormView(' + this.Document.title?.toString() + ')';
+ return 'CollectionFreeFormView(' + (this.Document.title?.toString() ?? '') + ')';
} // this makes mobx trace() statements more descriptive
@observable _paintedId = 'id' + Utils.GenerateGuid().replace(/-/g, '');
@@ -94,8 +95,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
super(props);
makeObservable(this);
}
- @observable
- public static ShowPresPaths = false;
private _panZoomTransitionTimer: any;
private _lastX: number = 0;
@@ -238,7 +237,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
};
@observable _keyframeEditing = false;
- @action setKeyFrameEditing = (set: boolean) => (this._keyframeEditing = set);
+ @action setKeyFrameEditing = (set: boolean) => {
+ this._keyframeEditing = set;
+ };
getKeyFrameEditing = () => this._keyframeEditing;
onBrowseClickHandler = () => this._props.onBrowseClickScript?.() || ScriptCast(this.layoutDoc.onBrowseClick);
onChildClickHandler = () => this._props.childClickScript || ScriptCast(this.Document.onChildClick);
@@ -256,7 +257,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
// this search order, for example, allows icons of cropped images to find the panx/pany/zoom on the cropped image's data doc instead of the usual layout doc because the zoom/panX/panY define the cropped image
panX = () => this.freeformData()?.bounds.cx ?? NumCast(this.Document[this.panXFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panX, 1));
panY = () => this.freeformData()?.bounds.cy ?? NumCast(this.Document[this.panYFieldKey], NumCast(Cast(this.Document.resolvedDataDoc, Doc, null)?.freeform_panY, 1));
- zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], 1); //, NumCast(DocCast(this.Document.resolvedDataDoc)?.[this.scaleFieldKey], 1));
+ zoomScaling = () => this.freeformData()?.scale ?? NumCast(Doc.Layout(this.Document)[this.scaleFieldKey], 1); // , NumCast(DocCast(this.Document.resolvedDataDoc)?.[this.scaleFieldKey], 1));
PanZoomCenterXf = () => (this._props.isAnnotationOverlay && this.zoomScaling() === 1 ? `` : `translate(${this.centeringShiftX}px, ${this.centeringShiftY}px) scale(${this.zoomScaling()}) translate(${-this.panX()}px, ${-this.panY()}px)`);
ScreenToContentsXf = () => this.screenToFreeformContentsXf.copy();
getActiveDocuments = () => this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => pair.layout);
@@ -272,7 +273,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
addDocument = (newBox: Doc | Doc[]) => {
let retVal = false;
if (newBox instanceof Doc) {
- if ((retVal = this._props.addDocument?.(newBox) || false)) {
+ retVal = this._props.addDocument?.(newBox) || false;
+ if (retVal) {
this.bringToFront(newBox);
this.updateCluster(newBox);
}
@@ -282,15 +284,17 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
if (retVal) {
const newBoxes = newBox instanceof Doc ? [newBox] : newBox;
- for (const newBox of newBoxes) {
- if (newBox.activeFrame !== undefined) {
- const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field.key]);
- CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field.key}_indexed`]);
- CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field.key]);
- delete newBox.activeFrame;
- CollectionFreeFormDocumentView.animFields.forEach((field, i) => field.key !== 'opacity' && (newBox[field.key] = vals[i]));
+ newBoxes.forEach(box => {
+ if (box.activeFrame !== undefined) {
+ const vals = CollectionFreeFormDocumentView.animFields.map(field => box[field.key]);
+ CollectionFreeFormDocumentView.animFields.forEach(field => delete box[`${field.key}_indexed`]);
+ CollectionFreeFormDocumentView.animFields.forEach(field => delete box[field.key]);
+ delete box.activeFrame;
+ CollectionFreeFormDocumentView.animFields.forEach((field, i) => {
+ field.key !== 'opacity' && (box[field.key] = vals[i]);
+ });
}
- }
+ });
if (this.Document._currentFrame !== undefined && !this._props.isAnnotationOverlay) {
CollectionFreeFormDocumentView.setupKeyframes(newBoxes, NumCast(this.Document._currentFrame), true);
}
@@ -313,14 +317,19 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
focus = (anchor: Doc, options: FocusViewOptions) => {
- if (this._lightboxDoc) return;
+ if (this._lightboxDoc) return undefined;
if (anchor === this.Document) {
// if (options.willZoomCentered && options.zoomScale) {
// this.fitContentOnce();
// options.didMove = true;
// }
}
- if (anchor.type !== DocumentType.CONFIG && !DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]).includes(anchor) && !this.childLayoutPairs.map(pair => pair.layout).includes(anchor)) return;
+ // prettier-ignore
+ if (anchor.type !== DocumentType.CONFIG &&
+ !DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]).includes(anchor) && //
+ !this.childLayoutPairs.map(pair => pair.layout).includes(anchor)) {
+ return undefined;
+ }
const xfToCollection = options?.docTransform ?? Transform.Identity();
const savedState = { panX: NumCast(this.Document[this.panXFieldKey]), panY: NumCast(this.Document[this.panYFieldKey]), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined };
const cantTransform = this.fitContentsToBox || ((this.Document.isGroup || this.layoutDoc._lockedTransform) && !LightboxView.LightboxDoc);
@@ -336,12 +345,16 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.setPan(panX, panY, focusTime, true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
return focusTime;
}
+ return undefined;
};
getView = async (doc: Doc, options: FocusViewOptions): Promise<Opt<DocumentView>> =>
new Promise<Opt<DocumentView>>(res => {
if (doc.hidden && this._lightboxDoc !== doc) options.didMove = !(doc.hidden = false);
- if (doc === this.Document) return res(this.DocumentView?.());
+ if (doc === this.Document) {
+ res(this.DocumentView?.());
+ return;
+ }
const findDoc = (finish: (dv: DocumentView) => void) => DocumentManager.Instance.AddViewRenderedCb(doc, dv => finish(dv));
findDoc(dv => res(dv));
});
@@ -357,7 +370,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
.map(pair => pair.layout)
.slice()
.sort((doc1, doc2) => NumCast(doc1.zIndex) - NumCast(doc2.zIndex));
- zsorted.forEach((doc, index) => (doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1));
+ zsorted.forEach((doc, index) => {
+ doc.zIndex = doc.stroke_isInkMask ? 5000 : index + 1;
+ });
const dvals = CollectionFreeFormDocumentView.getValues(refDoc, NumCast(refDoc.activeFrame, 1000));
const dropPos = this.Document._currentFrame !== undefined ? [NumCast(dvals.x), NumCast(dvals.y)] : [NumCast(refDoc.x), NumCast(refDoc.y)];
@@ -410,7 +425,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
let added = false;
// do nothing if link is dropped into any freeform view parent of dragged document
const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, x, y, title: 'dropped annotation' });
- added = this._props.addDocument?.(source) ? true : false;
+ added = !!this._props.addDocument?.(source);
de.complete.linkDocument = DocUtils.MakeLink(linkDragData.linkSourceGetAnchor(), source, { link_relationship: 'annotated by:annotation of' }); // TODODO this is where in text links get passed
if (de.complete.linkDocument) {
de.complete.linkDocument.layout_isSvg = true;
@@ -425,8 +440,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de, de.complete.annoDragData);
- else if (de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData);
- else if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData);
+ if (de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData);
+ if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData);
return false;
};
@@ -487,8 +502,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
@action
- updateClusters(_freeform_useClusters: boolean) {
- this.Document._freeform_useClusters = _freeform_useClusters;
+ updateClusters(useClusters: boolean) {
+ this.Document._freeform_useClusters = useClusters;
this._clusterSets.length = 0;
this.childLayoutPairs.map(pair => pair.layout).map(c => this.updateCluster(c));
}
@@ -498,12 +513,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const childLayouts = this.childLayoutPairs.map(pair => pair.layout);
if (this.Document._freeform_useClusters) {
const docFirst = docs[0];
- docs.map(doc => this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1)));
+ docs.forEach(doc => this._clusterSets.map(set => Doc.IndexOf(doc, set) !== -1 && set.splice(Doc.IndexOf(doc, set), 1)));
const preferredInd = NumCast(docFirst.layout_cluster);
- docs.map(doc => (doc.layout_cluster = -1));
+ docs.forEach(doc => {
+ doc.layout_cluster = -1;
+ });
docs.map(doc =>
this._clusterSets.map((set, i) =>
- set.map(member => {
+ set.forEach(member => {
if (docFirst.layout_cluster === -1 && Doc.IndexOf(member, childLayouts) !== -1 && CollectionFreeFormView.overlapping(doc, member, this._clusterDistance)) {
docFirst.layout_cluster = i;
}
@@ -518,19 +535,21 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
) {
docFirst.layout_cluster = preferredInd;
}
- this._clusterSets.map((set, i) => {
+ this._clusterSets.forEach((set, i) => {
if (docFirst.layout_cluster === -1 && !set.filter(member => Doc.IndexOf(member, childLayouts) !== -1).length) {
docFirst.layout_cluster = i;
}
});
if (docFirst.layout_cluster === -1) {
- docs.map(doc => {
+ docs.forEach(doc => {
doc.layout_cluster = this._clusterSets.length;
this._clusterSets.push([doc]);
});
} else if (this._clusterSets.length) {
for (let i = this._clusterSets.length; i <= NumCast(docFirst.layout_cluster); i++) !this._clusterSets[i] && this._clusterSets.push([]);
- docs.map(doc => this._clusterSets[(doc.layout_cluster = NumCast(docFirst.layout_cluster))].push(doc));
+ docs.forEach(doc => {
+ this._clusterSets[(doc.layout_cluster = NumCast(docFirst.layout_cluster))].push(doc);
+ });
}
childLayouts.map(child => !this._clusterSets.some((set, i) => Doc.IndexOf(child, set) !== -1 && child.layout_cluster === i) && this.updateCluster(child));
}
@@ -573,17 +592,21 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (doc && this.childDocList?.includes(doc))
switch (property.split(':')[0]) {
case StyleProp.BackgroundColor:
- const cluster = NumCast(doc?.layout_cluster);
- if (this.Document._freeform_useClusters && doc?.type !== DocumentType.IMG) {
- if (this._clusterSets.length <= cluster) {
- setTimeout(() => doc && this.updateCluster(doc));
- } else {
- // choose a cluster color from a palette
- const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
- styleProp = colors[cluster % colors.length];
- const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
- // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document
- set?.map(s => (styleProp = StrCast(s.backgroundColor)));
+ {
+ const cluster = NumCast(doc?.layout_cluster);
+ if (this.Document._freeform_useClusters && doc?.type !== DocumentType.IMG) {
+ if (this._clusterSets.length <= cluster) {
+ setTimeout(() => doc && this.updateCluster(doc));
+ } else {
+ // choose a cluster color from a palette
+ const colors = ['#da42429e', '#31ea318c', 'rgba(197, 87, 20, 0.55)', '#4a7ae2c4', 'rgba(216, 9, 255, 0.5)', '#ff7601', '#1dffff', 'yellow', 'rgba(27, 130, 49, 0.55)', 'rgba(0, 0, 0, 0.268)'];
+ styleProp = colors[cluster % colors.length];
+ const set = this._clusterSets[cluster]?.filter(s => s.backgroundColor);
+ // override the cluster color with an explicitly set color on a non-background document. then override that with an explicitly set color on a background document
+ set?.forEach(s => {
+ styleProp = StrCast(s.backgroundColor);
+ });
+ }
}
}
break;
@@ -591,6 +614,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (doc && this.Document._currentFrame !== undefined) {
return CollectionFreeFormDocumentView.getStringValues(doc, NumCast(this.Document._currentFrame))?.fillColor;
}
+ break;
+ default:
}
return styleProp;
};
@@ -626,9 +651,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case InkTool.None:
if (!(this._props.layoutEngine?.() || StrCast(this.layoutDoc._layoutEngine))) {
this._hitCluster = this.pickCluster(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
- setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, this._hitCluster !== -1 ? true : false, false);
+ setupMoveUpEvents(this, e, this.onPointerMove, emptyFunction, emptyFunction, this._hitCluster !== -1, false);
}
break;
+ default:
}
}
}
@@ -639,13 +665,34 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@undoBatch
onGesture = (e: Event, ge: GestureUtils.GestureEvent) => {
switch (ge.gesture) {
- default:
+ // case Gestures.Rectangle:
+ // {
+ // const strokes = this.getActiveDocuments()
+ // .filter(doc => doc.type === DocumentType.INK)
+ // .map(i => {
+ // const d = Cast(i.stroke, InkField);
+ // const x = NumCast(i.x) - Math.min(...(d?.inkData.map(pd => pd.X) ?? [0]));
+ // const y = NumCast(i.y) - Math.min(...(d?.inkData.map(pd => pd.Y) ?? [0]));
+ // return !d ? [] : d.inkData.map(pd => ({ X: x + pd.X, Y: y + pd.Y }));
+ // });
+
+ // CognitiveServices.Inking.Appliers.InterpretStrokes(strokes).then(results => {});
+ // }
+ // break;
+ 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] }));
+ e.stopPropagation();
+ }
+ break;
case Gestures.Line:
case Gestures.Circle:
case Gestures.Rectangle:
case Gestures.Triangle:
case Gestures.Stroke:
- const points = ge.points;
+ default: {
+ const { points } = ge;
const B = this.screenToFreeformContentsXf.transformBounds(ge.bounds.left, ge.bounds.top, ge.bounds.width, ge.bounds.height);
const inkWidth = ActiveInkWidth() * this.ScreenToLocalBoxXf().Scale;
const inkDoc = Docs.Create.InkDocument(
@@ -664,29 +711,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
this.addDocument(inkDoc);
e.stopPropagation();
- break;
- case Gestures.Rectangle:
- const strokes = this.getActiveDocuments()
- .filter(doc => doc.type === DocumentType.INK)
- .map(i => {
- const d = Cast(i.stroke, InkField);
- const x = NumCast(i.x) - Math.min(...(d?.inkData.map(pd => pd.X) ?? [0]));
- const y = NumCast(i.y) - Math.min(...(d?.inkData.map(pd => pd.Y) ?? [0]));
- return !d ? [] : d.inkData.map(pd => ({ X: x + pd.X, Y: y + pd.Y }));
- });
-
- CognitiveServices.Inking.Appliers.InterpretStrokes(strokes).then(results => {});
- break;
- 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] }));
- e.stopPropagation();
- }
+ }
}
};
@action
- onEraserUp = (e: PointerEvent): void => {
+ onEraserUp = (): void => {
this._deleteList.forEach(ink => ink._props.removeDocument?.(ink.Document));
this._deleteList = [];
this._batch?.end();
@@ -792,7 +821,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return this.childDocs
.map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.()))
.filter(inkView => inkView?.ComponentView instanceof InkingStroke)
- .map(inkView => ({ inkViewBounds: inkView!.getBounds, inkStroke: inkView!.ComponentView as InkingStroke, inkView: inkView! }))
+ .map(inkView => inkView!)
+ .map(inkView => ({ inkViewBounds: inkView.getBounds, inkStroke: inkView.ComponentView as InkingStroke, inkView }))
.filter(
({ inkViewBounds }) =>
inkViewBounds && // bounding box of eraser segment and ink stroke overlap
@@ -807,7 +837,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
// Convert from screen space to ink space for the intersection.
const prevPointInkSpace = inkStroke.ptFromScreen(lastPoint);
const currPointInkSpace = inkStroke.ptFromScreen(currPoint);
- for (var i = 0; i < inkData.length - 3; i += 4) {
+ for (let i = 0; i < inkData.length - 3; i += 4) {
const rawIntersects = InkField.Segment(inkData, i).intersects({
// compute all unique intersections
p1: { x: prevPointInkSpace.X, y: prevPointInkSpace.Y },
@@ -833,16 +863,17 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@action
segmentInkStroke = (ink: DocumentView, excludeT: number): Segment[] => {
const segments: Segment[] = [];
- var segment: Segment = [];
- var startSegmentT = 0;
+ let segment: Segment = [];
+ let startSegmentT = 0;
const { inkData } = (ink?.ComponentView as InkingStroke).inkScaledData();
// This iterates through all segments of the curve and splits them where they intersect another curve.
// if 'excludeT' is specified, then any segment containing excludeT will be skipped (ie, deleted)
- for (var i = 0; i < inkData.length - 3; i += 4) {
+ for (let i = 0; i < inkData.length - 3; i += 4) {
const inkSegment = InkField.Segment(inkData, i);
// Getting all t-value intersections of the current curve with all other curves.
const tVals = this.getInkIntersections(i, ink, inkSegment).sort();
if (tVals.length) {
+ // eslint-disable-next-line no-loop-func
tVals.forEach((t, index) => {
const docCurveTVal = t + Math.floor(i / 4);
if (excludeT < startSegmentT || excludeT > docCurveTVal) {
@@ -895,9 +926,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point));
const otherCtrlPts = otherScreenPts.map(spt => (ink.ComponentView as InkingStroke).ptFromScreen(spt));
- for (var j = 0; j < otherCtrlPts.length - 3; j += 4) {
+ for (let j = 0; j < otherCtrlPts.length - 3; j += 4) {
const neighboringSegment = i === j || i === j - 4 || i === j + 4;
// Ensuring that the curve intersected by the eraser is not checked for further ink intersections.
+ // eslint-disable-next-line no-continue
if (ink?.Document === otherInk.Document && neighboringSegment) continue;
const otherCurve = new Bezier(otherCtrlPts.slice(j, j + 4).map(p => ({ x: p.X, y: p.Y })));
@@ -908,7 +940,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
if (apt.d !== undefined && apt.d < 1 && apt.t !== undefined && !tVals.includes(apt.t)) {
tVals.push(apt.t);
}
- this.bintersects(curve, otherCurve).forEach((val: string | number, i: number) => {
+ this.bintersects(curve, otherCurve).forEach((val: string | number /* , i: number */) => {
// Converting the Bezier.js Split type to a t-value number.
const t = +val.toString().split('/')[0];
if (i % 2 === 0 && !tVals.includes(t)) tVals.push(t); // bcz: Hack! don't know why but intersection points are doubled from bezier.js (but not identical).
@@ -971,8 +1003,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.scrollPan({ deltaX: -deltaX * this.screenToFreeformContentsXf.Scale, deltaY: e.shiftKey ? 0 : -deltaY * this.screenToFreeformContentsXf.Scale });
break;
}
- default:
+ // eslint-disable-next-line no-fallthrough
case freeformScrollMode.Zoom:
+ default:
if ((e.ctrlKey || !scrollable) && this._props.isContentActive()) {
this.zoom(e.clientX, e.clientY, Math.max(-1, Math.min(1, e.deltaY))); // if (!this._props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc?
// e.preventDefault();
@@ -982,7 +1015,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
@action
- setPan(panX: number, panY: number, panTime: number = 0, clamp: boolean = false) {
+ setPan(panXIn: number, panYIn: number, panTime: number = 0, clamp: boolean = false) {
+ let panX = panXIn;
+ let panY = panYIn;
// this is the easiest way to do this -> will talk with Bob about using mobx to do this to remove this line of code.
if (Doc.UserDoc()?.presentationMode === 'watching') ReplayMovements.Instance.pauseFromInteraction();
@@ -1034,11 +1069,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
scale * NumCast(this.dataDoc._panY_max, nativeHeight) +
(!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) {
- } 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);
- setTimeout(() => (this.layoutDoc.layout_scrollTop = relTop * maxScrollTop), 10);
+ if (fitYscroll > 2 && this.layoutDoc.layout_scrollTop === undefined && NumCast(this.layoutDoc._freeform_scale, minScale) === minScale) {
+ const maxPanScrollY = minPanY + fitYscroll;
+ const relTop = (panY - minPanY) / (maxPanScrollY - minPanY);
+ setTimeout(() => {
+ this.layoutDoc.layout_scrollTop = relTop * maxScrollTop;
+ }, 10);
newPanY = minPanY;
}
!this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX);
@@ -1090,7 +1126,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._panZoomTransition = transitionTime;
this._panZoomTransitionTimer && clearTimeout(this._panZoomTransitionTimer);
this._panZoomTransitionTimer = setTimeout(
- action(() => (this._panZoomTransition = 0)),
+ action(() => {
+ this._panZoomTransition = 0;
+ }),
transitionTime
);
};
@@ -1173,6 +1211,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
e.stopPropagation?.();
return this.createTextDocCopy(fieldProps, !e.altKey && e.key !== 'Tab');
}
+ return undefined;
};
@computed get childPointerEvents() {
const engine = this._props.layoutEngine?.() || StrCast(this.Document._layoutEngine);
@@ -1194,6 +1233,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const childData = entry.pair.data;
return (
<CollectionFreeFormDocumentView
+ // eslint-disable-next-line react/jsx-props-no-spreading
{...OmitKeys(entry, ['replica', 'pair']).omit}
key={childLayout[Id] + (entry.replica || '')}
Document={childLayout}
@@ -1205,7 +1245,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
isGroupActive={this._props.isGroupActive}
renderDepth={this._props.renderDepth + 1}
hideDecorations={BoolCast(childLayout._layout_isSvg && childLayout.type === DocumentType.LINK)}
- suppressSetHeight={this.layoutEngine ? true : false}
+ suppressSetHeight={!!this.layoutEngine}
RenderCutoffProvider={this.renderCutoffProvider}
CollectionFreeFormView={this}
LayoutTemplate={childLayout.z ? undefined : this._props.childLayoutTemplate}
@@ -1239,37 +1279,42 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
/>
);
}
- addDocTab = action((doc: Doc, where: OpenWhere) => {
- if (this._props.isAnnotationOverlay) return this._props.addDocTab(doc, where);
+ addDocTab = action((docsIn: Doc | Doc[], where: OpenWhere) => {
+ const docs = docsIn instanceof Doc ? [docsIn] : docsIn;
+ if (this._props.isAnnotationOverlay) return this._props.addDocTab(docs, where);
switch (where) {
case OpenWhere.inParent:
- return this._props.addDocument?.(doc) || false;
- case OpenWhere.inParentFromScreen:
- const docContext = DocCast((doc instanceof Doc ? doc : doc?.[0])?.embedContainer);
+ return this._props.addDocument?.(docs) || false;
+ case OpenWhere.inParentFromScreen: {
+ const docContext = DocCast(docs[0]?.embedContainer);
return (
(this.addDocument?.(
- (doc instanceof Doc ? [doc] : doc).map(doc => {
- const pt = this.screenToFreeformContentsXf.transformPoint(NumCast(doc.x), NumCast(doc.y));
- doc.x = pt[0];
- doc.y = pt[1];
+ (docs instanceof Doc ? [docs] : docs).map(doc => {
+ [doc.x, doc.y] = this.screenToFreeformContentsXf.transformPoint(NumCast(doc.x), NumCast(doc.y));
return doc;
})
) &&
(!docContext || this._props.removeDocument?.(docContext))) ||
false
);
+ }
case undefined:
case OpenWhere.lightbox:
- if (this.layoutDoc._isLightbox) {
- this._lightboxDoc = doc;
- return true;
- }
- if (doc === this.Document || this.childDocList?.includes(doc) || this.childLayoutPairs.map(pair => pair.layout)?.includes(doc)) {
- if (doc.hidden) doc.hidden = false;
- return true;
+ {
+ const firstDoc = docs[0];
+ if (this.layoutDoc._isLightbox) {
+ this._lightboxDoc = firstDoc;
+ return true;
+ }
+ if (firstDoc === this.Document || this.childDocList?.includes(firstDoc) || this.childLayoutPairs.map(pair => pair.layout)?.includes(firstDoc)) {
+ if (firstDoc.hidden) firstDoc.hidden = false;
+ return true;
+ }
}
+ break;
+ default:
}
- return this._props.addDocTab(doc, where);
+ return this._props.addDocTab(docs, where);
});
@observable _lightboxDoc: Opt<Doc> = undefined;
@@ -1314,9 +1359,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
e.stopPropagation();
};
- viewDefsToJSX = (views: ViewDefBounds[]) => {
- return !Array.isArray(views) ? [] : views.filter(ele => this.viewDefToJSX(ele)).map(ele => this.viewDefToJSX(ele)!);
- };
+ viewDefsToJSX = (views: ViewDefBounds[]) => (!Array.isArray(views) ? [] : views.filter(ele => this.viewDefToJSX(ele)).map(ele => this.viewDefToJSX(ele)!));
viewDefToJSX(viewDef: ViewDefBounds): Opt<ViewDefResult> {
const { x, y, z } = viewDef;
@@ -1337,7 +1380,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
),
bounds: viewDef,
};
- } else if (viewDef.type === 'div') {
+ }
+ if (viewDef.type === 'div') {
return [x, y].some(val => val === undefined)
? undefined
: {
@@ -1353,9 +1397,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
bounds: viewDef,
};
}
+ return undefined;
}
renderCutoffProvider = computedFn(
+ // eslint-disable-next-line prefer-arrow-callback
function renderCutoffProvider(this: any, doc: Doc) {
return this.Document.isTemplateDoc ? false : !this._renderCutoffData.get(doc[Id] + '');
}.bind(this)
@@ -1369,7 +1415,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
doFreeformLayout(poolData: Map<string, PoolData>) {
- this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map((pair, i) => poolData.set(pair.layout[Id], this.getCalculatedPositions(pair)));
+ this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => poolData.set(pair.layout[Id], this.getCalculatedPositions(pair)));
return [] as ViewDefResult[];
}
@@ -1385,6 +1431,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
case computeTimelineLayout.name: return { newPool, computedElementData: this.doEngineLayout(newPool, computeTimelineLayout) };
case computePivotLayout.name: return { newPool, computedElementData: this.doEngineLayout(newPool, computePivotLayout) };
case computeStarburstLayout.name: return { newPool, computedElementData: this.doEngineLayout(newPool, computeStarburstLayout) };
+ default:
}
return { newPool, computedElementData: this.doFreeformLayout(newPool) };
}
@@ -1469,7 +1516,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._disposers.pointerevents = reaction(
() => this.childPointerEvents,
- pointerevents => (this._childPointerEvents = pointerevents as any),
+ pointerevents => {
+ this._childPointerEvents = pointerevents as any;
+ },
{ fireImmediately: true }
);
@@ -1643,7 +1692,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
};
- onContextMenu = (e: React.MouseEvent) => {
+ onContextMenu = () => {
if (this._props.isAnnotationOverlay || !ContextMenu.Instance) return;
const appearance = ContextMenu.Instance.findByDescription('Appearance...');
@@ -1654,7 +1703,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' });
return;
}
- !Doc.noviceMode && Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: 'Reset default note style', event: () => (Doc.UserDoc().defaultTextLayout = undefined), icon: 'eye' });
+ !Doc.noviceMode &&
+ Doc.UserDoc().defaultTextLayout &&
+ appearanceItems.push({
+ description: 'Reset default note style',
+ event: () => {
+ Doc.UserDoc().defaultTextLayout = undefined;
+ },
+ icon: 'eye',
+ });
appearanceItems.push({ description: `Pin View`, event: () => this._props.pinToPres(this.Document, { pinViewport: MarqueeView.CurViewBounds(this.dataDoc, this._props.PanelWidth(), this._props.PanelHeight()) }), icon: 'map-pin' });
!Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: this.updateIcon, icon: 'compress-arrows-alt' });
this._props.renderDepth && appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' });
@@ -1669,8 +1726,21 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const optionItems = options && 'subitems' in options ? options.subitems : [];
!this._props.isAnnotationOverlay &&
!Doc.noviceMode &&
- optionItems.push({ description: (this._showAnimTimeline ? 'Close' : 'Open') + ' Animation Timeline', event: action(() => (this._showAnimTimeline = !this._showAnimTimeline)), icon: 'eye' });
- this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null).backgroundColor = StrCast(this.layoutDoc.backgroundColor)), icon: 'palette' });
+ optionItems.push({
+ description: (this._showAnimTimeline ? 'Close' : 'Open') + ' Animation Timeline',
+ event: action(() => {
+ this._showAnimTimeline = !this._showAnimTimeline;
+ }),
+ icon: 'eye',
+ });
+ this._props.renderDepth &&
+ optionItems.push({
+ description: 'Use Background Color as Default',
+ event: () => {
+ Cast(Doc.UserDoc().emptyCollection, Doc, null).backgroundColor = StrCast(this.layoutDoc.backgroundColor);
+ },
+ icon: 'palette',
+ });
this._props.renderDepth && optionItems.push({ description: 'Fit Content Once', event: this.fitContentOnce, icon: 'object-group' });
if (!Doc.noviceMode) {
optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? 'Freeze' : 'Unfreeze') + ' Aspect', event: this.toggleNativeDimensions, icon: 'snowflake' });
@@ -1750,7 +1820,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
);
}
- showPresPaths = () => CollectionFreeFormView.ShowPresPaths;
+ showPresPaths = () => SnappingManager.ShowPresPaths;
brushedView = () => this._brushedView;
gridColor = () =>
DashColor(lightOrDark(this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor)))
@@ -1908,7 +1978,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
) : (
<>
{this._firstRender ? this.placeholder : this.marqueeView}
- {this._props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />}
+ {
+ // eslint-disable-next-line no-use-before-define
+ this._props.noOverlay ? null : <CollectionFreeFormOverlayView elements={this.elementFunc} />
+ }
{!this.GroupChildDrag ? null : <div className="collectionFreeForm-groupDropper" />}
</>
)}
@@ -1920,7 +1993,6 @@ 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
}
}
@@ -1959,6 +2031,7 @@ 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?.()));
+ return undefined;
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function pinWithView(pinContent: boolean) {
@@ -1989,7 +2062,7 @@ ScriptingGlobals.add(function datavizFromSchema() {
if (!view.layoutDoc.schema_columnKeys) {
view.layoutDoc.schema_columnKeys = new List<string>(['title', 'type', 'author', 'author_date']);
}
- const keys = Cast(view.layoutDoc.schema_columnKeys, listSpec('string'))?.filter(key => key != 'text');
+ const keys = Cast(view.layoutDoc.schema_columnKeys, listSpec('string'))?.filter(key => key !== 'text');
if (!keys) return;
const children = DocListCast(view.Document[Doc.LayoutFieldKey(view.Document)]);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b03e435ce..2f9cc49e0 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -196,7 +196,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
const eachCell = ns.join('\t').split('\t');
let eachRow = [];
for (let i = 1; i < eachCell.length; i++) {
- eachRow.push(eachCell[i].replace(/\,/g, ''));
+ eachRow.push(eachCell[i].replace(/,/g, ''));
if (i % headers.length === 0) {
csvRows.push(eachRow);
eachRow = [];
@@ -377,7 +377,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
});
@undoBatch
- pileup = action((e: KeyboardEvent | React.PointerEvent | undefined) => {
+ pileup = action(() => {
const selected = this.marqueeSelect(false);
SelectionManager.DeselectAll();
selected.forEach(d => this._props.removeDocument?.(d));
@@ -485,7 +485,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
});
@undoBatch
- summary = action((e: KeyboardEvent | React.PointerEvent | undefined) => {
+ summary = action(() => {
const selected = this.marqueeSelect(false).map(d => {
this._props.removeDocument?.(d);
d.x = NumCast(d.x) - this.Bounds.left;
@@ -530,8 +530,8 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
(e as any).propagationIsStopped = true;
if (e.key === 'g') this.collection(e, true);
if (e.key === 'c' || e.key === 't') this.collection(e);
- if (e.key === 's' || e.key === 'S') this.summary(e);
- if (e.key === 'p') this.pileup(e);
+ if (e.key === 's' || e.key === 'S') this.summary();
+ if (e.key === 'p') this.pileup();
this.cleanupInteractions(false);
}
if (e.key === 'r' || e.key === ' ') {
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 08eb35586..ee30006ae 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -1,3 +1,6 @@
+/* eslint-disable jsx-a11y/alt-text */
+/* eslint-disable react/jsx-props-no-spreading */
+/* eslint-disable no-use-before-define */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Popup, Size, Type } from 'browndash-components';
import { action, computed, makeObservable, observable } from 'mobx';
@@ -26,7 +29,7 @@ import { EditableView } from '../../EditableView';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DefaultStyleProvider } from '../../StyleProvider';
import { Colors } from '../../global/globalEnums';
-import { OpenWhere, returnEmptyDocViewList } from '../../nodes/DocumentView';
+import { returnEmptyDocViewList } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
import { KeyValueBox } from '../../nodes/KeyValueBox';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
@@ -64,8 +67,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
makeObservable(this);
}
- static addFieldDoc = (doc: Doc, where: OpenWhere) => {
- DocFocusOrOpen(doc);
+ static addFieldDoc = (doc: Doc | Doc[] /* , where: OpenWhere */) => {
+ DocFocusOrOpen(doc instanceof Doc ? doc : doc[0]);
return true;
};
public static renderProps(props: SchemaTableCellProps) {
@@ -186,7 +189,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
return (
<div
className="schema-table-cell"
- onPointerDown={action(e => !this.selected && this._props.selectCell(this._props.Document, this._props.col))}
+ onPointerDown={action(() => !this.selected && this._props.selectCell(this._props.Document, this._props.col))}
style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}>
{this.content}
</div>
@@ -207,7 +210,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 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
+ if (!/\.(png|jpg|jpeg|gif|webp)$/.test(url.href.toLowerCase())) return url.href; // Why is this here — good question
const ext = extname(url.href);
return url.href.replace(ext, '_s' + ext);
@@ -246,7 +249,7 @@ export class SchemaImageCell extends ObservableReactComponent<SchemaTableCellPro
};
@action
- removeHoverPreview = (e: React.PointerEvent) => {
+ removeHoverPreview = () => {
if (!this._previewRef) return;
document.body.removeChild(this._previewRef);
};
@@ -258,7 +261,7 @@ export class SchemaImageCell extends ObservableReactComponent<SchemaTableCellPro
const height = this._props.rowHeight() ? this._props.rowHeight() - (this._props.padding || 6) * 2 : undefined;
const width = height ? height * aspect : undefined; // increase the width of the image if necessary to maintain proportionality
- return <img src={this.url} width={width ? width : undefined} height={height} style={{}} draggable="false" onPointerEnter={this.showHoverPreview} onPointerMove={this.moveHoverPreview} onPointerLeave={this.removeHoverPreview} />;
+ return <img src={this.url} width={width || undefined} height={height} style={{}} draggable="false" onPointerEnter={this.showHoverPreview} onPointerMove={this.moveHoverPreview} onPointerLeave={this.removeHoverPreview} />;
}
}
@@ -282,15 +285,15 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
// } else {
// ^ DateCast is always undefined for some reason, but that is what the field should be set to
date && (this._props.Document[this._props.fieldKey] = new DateField(date));
- //}
+ // }
}, 'date change');
render() {
- const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props);
+ const { pointerEvents } = SchemaTableCell.renderProps(this._props);
return (
<>
<div style={{ pointerEvents: 'none' }}>
- <DatePicker dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={e => {}} />
+ <DatePicker dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={emptyFunction} />
</div>
{pointerEvents === 'none' ? null : (
<Popup
@@ -301,7 +304,7 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
background={SettingsManager.userBackgroundColor}
popup={
<div style={{ width: 'fit-content', height: '200px' }}>
- <DatePicker open={true} dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={this.handleChange} />
+ <DatePicker open dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={this.handleChange} />
</div>
}
/>
@@ -329,7 +332,7 @@ export class SchemaRTFCell extends ObservableReactComponent<SchemaTableCellProps
fieldProps.isContentActive = this.selectedFunc;
return (
<div className="schemaRTFCell" style={{ fontStyle: this.selected ? undefined : 'italic', color, textDecoration, cursor, pointerEvents }}>
- {this.selected ? <FormattedTextBox {...fieldProps} autoFocus={true} onBlur={() => this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
+ {this.selected ? <FormattedTextBox {...fieldProps} autoFocus onBlur={() => this._props.finishEdit?.()} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))}
</div>
);
}
@@ -355,8 +358,8 @@ export class SchemaBoolCell extends ObservableReactComponent<SchemaTableCellProp
checked={BoolCast(this._props.Document[this._props.fieldKey])}
onChange={undoBatch((value: React.ChangeEvent<HTMLInputElement> | undefined) => {
if ((value?.nativeEvent as any).shiftKey) {
- this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString());
- } else KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString());
+ this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? ''));
+ } else KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? ''));
})}
/>
<EditableView
@@ -391,7 +394,7 @@ export class SchemaEnumerationCell extends ObservableReactComponent<SchemaTableC
return this._props.isRowActive() && selected?.[0] === this._props.Document && selected[1] === this._props.col;
}
render() {
- const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props);
+ const { color, textDecoration, cursor, pointerEvents } = SchemaTableCell.renderProps(this._props);
const options = this._props.options?.map(facet => ({ value: facet, label: facet }));
return (
<div className="schemaSelectionCell" style={{ color, textDecoration, cursor, pointerEvents }}>