aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-01-30 15:23:40 -0500
committerbobzel <zzzman@gmail.com>2023-01-30 15:23:40 -0500
commit5e2f64f3ee172e37d0d3277637a7778b640a2066 (patch)
tree11f9a5862e7e70b2eeb931f4eb3c5b509a3714cf /src
parent95b8a5a2b470d3118b6eeac484a45b23df2830b4 (diff)
fixed pointerEvents for text box footnotes. fixed keyvalue editing to not typecheck. fixed schema header field editing from keyvalue pane. fixed webBox error causing overlayview to not work for Repls and others. fixed some layout issues with stackingview columns.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/EditableView.tsx1
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx311
-rw-r--r--src/client/views/collections/CollectionStackingView.scss21
-rw-r--r--src/client/views/collections/CollectionStackingViewFieldColumn.tsx58
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx1
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx2
-rw-r--r--src/client/views/nodes/WebBoxRenderer.js4
-rw-r--r--src/client/views/nodes/formattedText/FootnoteView.tsx72
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx4
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx2
-rw-r--r--src/fields/SchemaHeaderField.ts7
12 files changed, 257 insertions, 228 deletions
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 8036df471..bb190e93b 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -43,7 +43,6 @@ export interface EditableProps {
menuCallback?: (x: number, y: number) => void;
textCallback?: (char: string) => boolean;
showMenuOnLoad?: boolean;
- toggle?: () => void;
background?: string | undefined;
placeholder?: string;
}
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index a94e706eb..befd89e41 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -1,24 +1,24 @@
-import React = require("react");
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { DataSym, Doc, DocListCast } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { ScriptField } from "../../../fields/ScriptField";
-import { NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, numberRange, returnEmptyString, setupMoveUpEvents } from "../../../Utils";
-import { Docs } from "../../documents/Documents";
-import { DragManager } from "../../util/DragManager";
-import { CompileScript } from "../../util/Scripting";
-import { SnappingManager } from "../../util/SnappingManager";
-import { Transform } from "../../util/Transform";
-import { undoBatch } from "../../util/UndoManager";
-import { EditableView } from "../EditableView";
-import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
-import { CollectionStackingView } from "./CollectionStackingView";
-import "./CollectionStackingView.scss";
-const higflyout = require("@hig/flyout");
+import React = require('react');
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, observable, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import { DataSym, Doc, DocListCast } from '../../../fields/Doc';
+import { Id } from '../../../fields/FieldSymbols';
+import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
+import { ScriptField } from '../../../fields/ScriptField';
+import { NumCast, StrCast } from '../../../fields/Types';
+import { emptyFunction, numberRange, returnEmptyString, setupMoveUpEvents } from '../../../Utils';
+import { Docs } from '../../documents/Documents';
+import { DragManager } from '../../util/DragManager';
+import { CompileScript } from '../../util/Scripting';
+import { SnappingManager } from '../../util/SnappingManager';
+import { Transform } from '../../util/Transform';
+import { undoBatch } from '../../util/UndoManager';
+import { EditableView } from '../EditableView';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+import { CollectionStackingView } from './CollectionStackingView';
+import './CollectionStackingView.scss';
+const higflyout = require('@hig/flyout');
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -32,7 +32,7 @@ interface CMVFieldRowProps {
docList: Doc[];
parent: CollectionStackingView;
pivotField: string;
- type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined;
+ type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined;
createDropTarget: (ele: HTMLDivElement) => void;
screenToLocalTransform: () => Transform;
setDocHeight: (key: string, thisHeight: number) => void;
@@ -43,15 +43,21 @@ interface CMVFieldRowProps {
@observer
export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowProps> {
- @observable private _background = "inherit";
+ @observable private _background = 'inherit';
@observable private _createAliasSelected: boolean = false;
- @observable private heading: string = "";
- @observable private color: string = "#f1efeb";
+ @observable private heading: string = '';
+ @observable private color: string = '#f1efeb';
@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)); }
- private set _color(value: string) { 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)); }
+ private set _heading(value: string) {
+ 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));
+ }
+ private set _collapsed(value: boolean) {
+ runInAction(() => this.props.headingObject && (this.props.headingObject.collapsed = this.collapsed = value));
+ }
private _dropDisposer?: DragManager.DragDropDisposer;
private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
@@ -65,11 +71,11 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
this.props.observeHeight(ele);
this._dropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this));
}
- }
+ };
@action
componentDidMount() {
- this.heading = this.props.headingObject?.heading || "";
- this.color = this.props.headingObject?.color || "#f1efeb";
+ this.heading = this.props.headingObject?.heading || '';
+ this.color = this.props.headingObject?.color || '#f1efeb';
this.collapsed = this.props.headingObject?.collapsed || false;
}
componentWillUnmount() {
@@ -85,14 +91,13 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
const trueHeight = rawHeight * transformScale;
this.props.setDocHeight(this.heading, trueHeight);
}
- }
+ };
@undoBatch
rowDrop = action((e: Event, de: DragManager.DropEvent) => {
this._createAliasSelected = false;
if (de.complete.docDragData) {
- (this.props.parent.Document.dropConverter instanceof ScriptField) &&
- this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData });
+ this.props.parent.Document.dropConverter instanceof ScriptField && this.props.parent.Document.dropConverter.script.run({ dragData: de.complete.docDragData });
const key = this.props.pivotField;
const castedValue = this.getValue(this.heading);
const onLayoutDoc = this.onLayoutDoc(key);
@@ -105,10 +110,10 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
getValue = (value: string): any => {
const parsed = parseInt(value);
if (!isNaN(parsed)) return parsed;
- if (value.toLowerCase().indexOf("true") > -1) return true;
- if (value.toLowerCase().indexOf("false") > -1) return false;
+ if (value.toLowerCase().indexOf('true') > -1) return true;
+ if (value.toLowerCase().indexOf('false') > -1) return false;
return value;
- }
+ };
@action
headingChanged = (value: string, shiftDown?: boolean) => {
@@ -126,58 +131,60 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
return true;
}
return false;
- }
+ };
@action
changeColumnColor = (color: string) => {
this._createAliasSelected = false;
this._color = color;
- }
+ };
- pointerEnteredRow = action(() => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4"));
+ pointerEnteredRow = action(() => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4'));
@action
pointerLeaveRow = () => {
this._createAliasSelected = false;
- this._background = "inherit";
- }
+ this._background = 'inherit';
+ };
@action
addDocument = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
if (!value && !forceEmptyNote) return false;
this._createAliasSelected = false;
const key = this.props.pivotField;
- const newDoc = Docs.Create.TextDocument("", { _autoHeight: true, _width: 200, _fitWidth: true, title: value });
+ const newDoc = Docs.Create.TextDocument('', { _autoHeight: true, _width: 200, _fitWidth: true, title: value });
const onLayoutDoc = this.onLayoutDoc(key);
FormattedTextBox.SelectOnLoad = newDoc[Id];
FormattedTextBox.SelectOnLoadChar = value;
(onLayoutDoc ? newDoc : newDoc[DataSym])[key] = 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)
- }
+ };
- deleteRow = undoBatch(action(() => {
- this._createAliasSelected = false;
- const key = this.props.pivotField;
- this.props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true));
- if (this.props.parent.columnHeaders && this.props.headingObject) {
- const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject);
- this.props.parent.columnHeaders.splice(index, 1);
- }
- }));
+ deleteRow = undoBatch(
+ action(() => {
+ this._createAliasSelected = false;
+ const key = this.props.pivotField;
+ this.props.docList.forEach(d => Doc.SetInPlace(d, key, undefined, true));
+ if (this.props.parent.columnHeaders && this.props.headingObject) {
+ const index = this.props.parent.columnHeaders.indexOf(this.props.headingObject);
+ this.props.parent.columnHeaders.splice(index, 1);
+ }
+ })
+ );
@action
collapseSection = (e: any) => {
this._createAliasSelected = false;
this.toggleVisibility();
e.stopPropagation();
- }
+ };
headerMove = (e: PointerEvent) => {
const alias = Doc.MakeAlias(this.props.Document);
const key = this.props.pivotField;
let value = this.getValue(this.heading);
- value = typeof value === "string" ? `"${value}"` : value;
+ value = typeof value === 'string' ? `"${value}"` : value;
const script = `return doc.${key} === ${value}`;
const compiled = CompileScript(script, { params: { doc: Doc.name } });
if (compiled.compiled) {
@@ -185,7 +192,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY);
}
return true;
- }
+ };
@action
headerDown = (e: React.PointerEvent<HTMLDivElement>) => {
@@ -193,7 +200,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
setupMoveUpEvents(this, e, this.headerMove, emptyFunction, e => !this.props.chromeHidden && this.collapseSection(e));
this._createAliasSelected = false;
}
- }
+ };
/**
* Returns true if a key is on the layout doc of the documents in the collection.
@@ -203,143 +210,141 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
if (Doc.Get(doc, key, true)) return true;
});
return false;
- }
+ };
renderColorPicker = () => {
const selected = this.color;
- const pink = PastelSchemaPalette.get("pink2");
- const purple = PastelSchemaPalette.get("purple4");
- const blue = PastelSchemaPalette.get("bluegreen1");
- const yellow = PastelSchemaPalette.get("yellow4");
- const red = PastelSchemaPalette.get("red2");
- const green = PastelSchemaPalette.get("bluegreen7");
- const cyan = PastelSchemaPalette.get("bluegreen5");
- const orange = PastelSchemaPalette.get("orange1");
- const gray = "#f1efeb";
+ const pink = PastelSchemaPalette.get('pink2');
+ const purple = PastelSchemaPalette.get('purple4');
+ const blue = PastelSchemaPalette.get('bluegreen1');
+ const yellow = PastelSchemaPalette.get('yellow4');
+ const red = PastelSchemaPalette.get('red2');
+ const green = PastelSchemaPalette.get('bluegreen7');
+ const cyan = PastelSchemaPalette.get('bluegreen5');
+ const orange = PastelSchemaPalette.get('orange1');
+ const gray = '#f1efeb';
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>
+ <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>
</div>
);
- }
+ };
- toggleAlias = action(() => this._createAliasSelected = true);
- toggleVisibility = () => this._collapsed = !this.collapsed;
+ toggleAlias = action(() => (this._createAliasSelected = true));
+ toggleVisibility = () => (this._collapsed = !this.collapsed);
renderMenu = () => {
const selected = this._createAliasSelected;
- return (<div className="collectionStackingView-optionPicker">
- <div className="optionOptions">
- <div className={"optionPicker" + (selected === true ? " active" : "")} onClick={this.toggleAlias}>Create Alias</div>
- <div className={"optionPicker" + (selected === true ? " active" : "")} onClick={this.deleteRow}>Delete</div>
+ return (
+ <div className="collectionStackingView-optionPicker">
+ <div className="optionOptions">
+ <div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.toggleAlias}>
+ Create Alias
+ </div>
+ <div className={'optionPicker' + (selected === true ? ' active' : '')} onClick={this.deleteRow}>
+ Delete
+ </div>
+ </div>
</div>
- </div>);
- }
+ );
+ };
@action
textCallback = (char: string) => {
- return this.addDocument("", false);
- }
+ return 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))));
const showChrome = !this.props.chromeHidden;
const stackPad = showChrome ? `0px ${this.props.parent.xMargin}px` : `${this.props.parent.yMargin}px ${this.props.parent.xMargin}px 0px ${this.props.parent.xMargin}px `;
- return this.collapsed ? (null) :
- <div style={{ position: "relative" }}>
- {showChrome ?
- <div className="collectionStackingView-addDocumentButton"
+ return this.collapsed ? null : (
+ <div style={{ position: 'relative' }}>
+ {showChrome ? (
+ <div
+ className="collectionStackingView-addDocumentButton"
style={{
//width: style.columnWidth / style.numGroupColumns,
- padding: `${NumCast(this.props.parent.layoutDoc._yPadding, this.props.parent.yMargin)}px 0px 0px 0px`
+ 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"}
- toggle={this.toggleVisibility} />
- </div> : null
- }
- <div className={`collectionStackingView-masonryGrid`}
+ <EditableView GetValue={returnEmptyString} SetValue={this.addDocument} textCallback={this.textCallback} contents={'+ NEW'} />
+ </div>
+ ) : null}
+ <div
+ className={`collectionStackingView-masonryGrid`}
ref={this._contRef}
style={{
padding: stackPad,
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: string, i: any) => list + ` ${this.props.parent.columnWidth}px`, ''),
}}>
{this.props.parent.children(this.props.docList)}
- {this.props.showHandle && this.props.parent.props.isContentActive() ? this.props.parent.columnDragger : (null)}
+ {this.props.showHandle && this.props.parent.props.isContentActive() ? this.props.parent.columnDragger : null}
</div>
- </div>;
+ </div>
+ );
}
@computed get headingView() {
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}
- toggle={this.toggleVisibility} />;
- return this.props.Document.miniHeaders ?
- <div className="collectionStackingView-miniHeader">
- {editableHeaderView}
- </div> :
- !this.props.headingObject ? (null) :
- <div className="collectionStackingView-sectionHeader" ref={this._headerRef} >
- <div className="collectionStackingView-sectionHeader-subCont" onPointerDown={this.headerDown}
- title={evContents === `NO ${key.toUpperCase()} VALUE` ?
- `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
- style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : "lightgrey" }}>
- {noChrome ? evContents : editableHeaderView}
- {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
- <div className="collectionStackingView-sectionColor">
- <button className="collectionStackingView-sectionColorButton" onClick={action(e => this._paletteOn = !this._paletteOn)}>
- <FontAwesomeIcon icon="palette" size="lg" />
+ 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} />;
+ return this.props.Document.miniHeaders ? (
+ <div className="collectionStackingView-miniHeader">{editableHeaderView}</div>
+ ) : !this.props.headingObject ? null : (
+ <div className="collectionStackingView-sectionHeader" ref={this._headerRef}>
+ <div
+ className="collectionStackingView-sectionHeader-subCont"
+ onPointerDown={this.headerDown}
+ title={evContents === `NO ${key.toUpperCase()} VALUE` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''}
+ style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : 'lightgrey' }}>
+ {noChrome ? evContents : editableHeaderView}
+ {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? null : (
+ <div className="collectionStackingView-sectionColor">
+ <button className="collectionStackingView-sectionColorButton" onClick={action(e => (this._paletteOn = !this._paletteOn))}>
+ <FontAwesomeIcon icon="palette" size="lg" />
+ </button>
+ {this._paletteOn ? this.renderColorPicker() : null}
+ </div>
+ )}
+ {noChrome ? null : (
+ <button className="collectionStackingView-sectionDelete" onClick={noChrome ? undefined : this.collapseSection}>
+ <FontAwesomeIcon icon={this.collapsed ? 'chevron-down' : 'chevron-up'} size="lg" />
+ </button>
+ )}
+ {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? null : (
+ <div className="collectionStackingView-sectionOptions">
+ <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderMenu()}>
+ <button className="collectionStackingView-sectionOptionButton">
+ <FontAwesomeIcon icon="ellipsis-v" size="lg" />
</button>
- {this._paletteOn ? this.renderColorPicker() : (null)}
- </div>
- }
- {noChrome ? (null) : <button className="collectionStackingView-sectionDelete" onClick={noChrome ? undefined : this.collapseSection}>
- <FontAwesomeIcon icon={this.collapsed ? "chevron-down" : "chevron-up"} size="lg" />
- </button>}
- {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
- <div className="collectionStackingView-sectionOptions">
- <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderMenu()}>
- <button className="collectionStackingView-sectionOptionButton">
- <FontAwesomeIcon icon="ellipsis-v" size="lg" />
- </button>
- </Flyout>
- </div>
- }
- </div>
- </div>;
+ </Flyout>
+ </div>
+ )}
+ </div>
+ </div>
+ );
}
render() {
const background = this._background;
- return <div className="collectionStackingView-masonrySection"
- style={{ width: this.props.parent.NodeWidth, background }}
- ref={this.createRowDropRef}
- onPointerEnter={this.pointerEnteredRow}
- onPointerLeave={this.pointerLeaveRow}
- >
- {this.headingView}
- {this.contentLayout}
- </div >;
+ return (
+ <div className="collectionStackingView-masonrySection" style={{ width: this.props.parent.NodeWidth, background }} ref={this.createRowDropRef} onPointerEnter={this.pointerEnteredRow} onPointerLeave={this.pointerLeaveRow}>
+ {this.headingView}
+ {this.contentLayout}
+ </div>
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 7385f933b..f3397e2c4 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -150,11 +150,14 @@
}
.collectionStackingView-collapseBar {
- margin-left: 2px;
- margin-right: 2px;
margin-top: 2px;
background: $medium-gray;
height: 5px;
+ width: 100%;
+ display: none;
+ position: absolute;
+ top: 0;
+ cursor: default;
&.active {
margin-left: 0;
@@ -236,7 +239,7 @@
.editableView-container-editing-oneLine,
.editableView-container-editing {
color: grey;
- padding: 10px;
+ //padding: 10px;
}
.editableView-input:hover,
@@ -333,7 +336,7 @@
.collectionStackingView-sectionDelete {
position: absolute;
- right: 25px;
+ right: 0px;
top: 0;
height: 100%;
display: none;
@@ -352,6 +355,10 @@
.collectionStackingView-sectionDelete {
display: unset;
}
+
+ .collectionStackingView-collapseBar {
+ display: block;
+ }
}
.collectionStackingView-addDocumentButton,
@@ -365,7 +372,7 @@
.editableView-container-editing-oneLine,
.editableView-container-editing {
color: grey;
- padding: 10px;
+ padding-top: 10px;
width: 100%;
}
@@ -380,7 +387,7 @@
letter-spacing: 2px;
color: grey;
border: 0px;
- padding: 12px 10px 11px 10px;
+ padding-top: 10px; // 12px 10px 11px 10px;
}
}
@@ -394,7 +401,7 @@
letter-spacing: 2px;
color: grey;
border: 0px;
- padding: 12px 10px 11px 10px;
+ padding-top: 10px; // : 12px 10px 11px 10px;
}
}
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 7b268cd49..d62c4dc62 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -1,12 +1,12 @@
import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { RichTextField } from '../../../fields/RichTextField';
import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { ScriptField } from '../../../fields/ScriptField';
-import { Cast, NumCast, StrCast } from '../../../fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
import { emptyFunction, setupMoveUpEvents, returnFalse, returnEmptyString } from '../../../Utils';
@@ -56,6 +56,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@observable private _background = 'inherit';
private dropDisposer?: DragManager.DragDropDisposer;
+ private _disposers: { [name: string]: IReactionDisposer } = {};
private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
@observable _paletteOn = false;
@@ -75,7 +76,16 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
}
};
+ @action
+ componentDidMount() {
+ this._disposers.collapser = reaction(
+ () => this.props.headingObject?.collapsed,
+ collapsed => (this.collapsed = collapsed !== undefined ? BoolCast(collapsed) : false),
+ { fireImmediately: true }
+ );
+ }
componentWillUnmount() {
+ this._disposers.collapser?.();
this.props.unobserveHeight(this._ele);
}
@@ -146,7 +156,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
@action
collapseSection = () => {
this.props.headingObject?.setCollapsed(!this.props.headingObject.collapsed);
- this.toggleVisibility();
+ this.collapsed = BoolCast(this.props.headingObject?.collapsed);
};
headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
@@ -275,7 +285,8 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
const heading = this._heading;
const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin;
const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
- const evContents = heading ? heading : this.props?.type === 'number' ? '0' : `NO ${key.toUpperCase()} VALUE`;
+ const noValueHeader = `NO ${key.toUpperCase()} VALUE`;
+ const evContents = heading ? heading : this.props?.type === 'number' ? '0' : noValueHeader;
const headingView = this.props.headingObject ? (
<div
key={heading}
@@ -285,29 +296,24 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
marginTop: this.props.yMargin,
width: this.props.columnWidth / (uniqueHeadings.length + (this.props.chromeHidden ? 0 : 1) || 1),
}}>
- <div className={'collectionStackingView-collapseBar' + (this.props.headingObject.collapsed === true ? ' active' : '')} onClick={this.collapseSection}></div>
{/* the default bucket (no key value) has a tooltip that describes what it is.
Further, it does not have a color and cannot be deleted. */}
<div
className="collectionStackingView-sectionHeader-subCont"
onPointerDown={this.headerDown}
- title={evContents === `NO ${key.toUpperCase()} VALUE` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''}
- style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this._color : 'inherit' }}>
- <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} toggle={this.toggleVisibility} />
- {evContents === `NO ${key.toUpperCase()} VALUE` ? null : (
- <div className="collectionStackingView-sectionColor">
- <button className="collectionStackingView-sectionColorButton" onClick={action(e => (this._paletteOn = !this._paletteOn))}>
- <FontAwesomeIcon icon="palette" size="lg" />
- </button>
- {this._paletteOn ? this.renderColorPicker() : null}
- </div>
- )}
- {
- <button className="collectionStackingView-sectionDelete" onClick={this.deleteColumn}>
- <FontAwesomeIcon icon="trash" size="lg" />
+ title={evContents === noValueHeader ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''}
+ style={{ background: evContents !== noValueHeader ? this._color : 'inherit' }}>
+ <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
+ <div className="collectionStackingView-sectionColor" style={{ display: evContents === noValueHeader ? 'none' : undefined }}>
+ <button className="collectionStackingView-sectionColorButton" onClick={action(e => (this._paletteOn = !this._paletteOn))}>
+ <FontAwesomeIcon icon="palette" size="lg" />
</button>
- }
- {evContents === `NO ${key.toUpperCase()} VALUE` ? null : (
+ {this._paletteOn ? this.renderColorPicker() : null}
+ </div>
+ <button className="collectionStackingView-sectionDelete" onClick={this.deleteColumn}>
+ <FontAwesomeIcon icon="trash" size="lg" />
+ </button>
+ {/* {evContents === noValueHeader ? null : (
<div className="collectionStackingView-sectionOptions">
<Flyout anchorPoint={anchorPoints.TOP_RIGHT} content={this.renderMenu()}>
<button className="collectionStackingView-sectionOptionButton">
@@ -315,8 +321,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
</button>
</Flyout>
</div>
- )}
+ )} */}
</div>
+ <div
+ className={'collectionStackingView-collapseBar' + (this.props.headingObject.collapsed === true ? ' active' : '')}
+ style={{ display: this.props.headingObject.collapsed === true ? 'block' : undefined }}
+ onClick={this.collapseSection}
+ />
</div>
) : null;
const templatecols = `${this.props.columnWidth / this.props.numGroupColumns}px `;
@@ -348,14 +359,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
//TODO: would be great if there was additional space beyond the frame, so that you can actually see your
// bottom note
//TODO: ok, so we are using a single column, and this is it!
- <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton" style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10, marginLeft: 25 }}>
+ <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton" style={{ width: 'calc(100% - 25px)', maxWidth: this.props.columnWidth / this.props.numGroupColumns - 25, marginBottom: 10 }}>
<EditableView
GetValue={returnEmptyString}
SetValue={this.addNewTextDoc}
textCallback={this.textCallback}
placeholder={"Type ':' for commands"}
contents={<FontAwesomeIcon icon={'plus'} />}
- toggle={this.toggleVisibility}
menuCallback={this.menuCallback}
/>
</div>
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 8c613198d..0ec21cc51 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -239,7 +239,6 @@ export class CollectionTimeView extends CollectionSubView() {
}
return false;
}}
- toggle={this.toggleVisibility}
background={'#f1efeb'} // this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
contents={':' + StrCast(this.layoutDoc._pivotField)}
showMenuOnLoad={true}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 18c5b81ec..60417430f 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -66,7 +66,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
value = eq ? value.substr(1) : value;
const dubEq = value.startsWith(':=') ? 'computed' : value.startsWith(';=') ? 'script' : false;
value = dubEq ? value.substr(2) : value;
- const options: ScriptOptions = { addReturn: true, params: { this: Doc.name, self: Doc.name, _last_: 'any', _readOnly_: 'boolean' }, editable: false };
+ const options: ScriptOptions = { addReturn: true, typecheck: false, params: { this: Doc.name, self: Doc.name, _last_: 'any', _readOnly_: 'boolean' }, editable: false };
if (dubEq) options.typecheck = false;
const script = CompileScript(value, options);
return !script.compiled ? undefined : { script, type: dubEq, onDelegate: eq };
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index acf4fe4b0..d0d638e98 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -981,7 +981,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
}
return this.props.styleProvider?.(doc, props, property);
};
- pointerEvents = () => (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none');
+ pointerEvents = () => (!this._draggingSidebar && this.props.isContentActive() && this.props.pointerEvents?.() !== 'none' && !MarqueeOptionsMenu.Instance?.isShown() ? 'all' : SnappingManager.GetIsDragging() ? undefined : 'none');
annotationPointerEvents = () => (this._isAnnotating || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None ? 'all' : 'none');
render() {
const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js
index cebb94d86..20554b858 100644
--- a/src/client/views/nodes/WebBoxRenderer.js
+++ b/src/client/views/nodes/WebBoxRenderer.js
@@ -216,7 +216,9 @@ var ForeignHtmlRenderer = function (styleSheets) {
}
const styleElem = document.createElement('style');
- styleElem.innerHTML = cssStyles.replace('&gt;', '>').replace('&lt;', '<');
+ styleElem.innerHTML =
+ '#mw-sidebar-checkbox ~ .vector-main-menu-container { display: none !important; } ' + // hack to prevent wikipedia menu from appearing
+ cssStyles.replace('&gt;', '>').replace('&lt;', '<');
const styleElemString = new XMLSerializer().serializeToString(styleElem).replace(/&gt;/g, '>').replace(/&lt;/g, '<');
diff --git a/src/client/views/nodes/formattedText/FootnoteView.tsx b/src/client/views/nodes/formattedText/FootnoteView.tsx
index 1683cc972..531a60297 100644
--- a/src/client/views/nodes/formattedText/FootnoteView.tsx
+++ b/src/client/views/nodes/formattedText/FootnoteView.tsx
@@ -1,10 +1,10 @@
-import { EditorView } from "prosemirror-view";
-import { EditorState } from "prosemirror-state";
-import { keymap } from "prosemirror-keymap";
-import { baseKeymap, toggleMark } from "prosemirror-commands";
-import { schema } from "./schema_rts";
-import { redo, undo } from "prosemirror-history";
-import { StepMap } from "prosemirror-transform";
+import { EditorView } from 'prosemirror-view';
+import { EditorState } from 'prosemirror-state';
+import { keymap } from 'prosemirror-keymap';
+import { baseKeymap, toggleMark } from 'prosemirror-commands';
+import { schema } from './schema_rts';
+import { redo, undo } from 'prosemirror-history';
+import { StepMap } from 'prosemirror-transform';
export class FootnoteView {
innerView: any;
@@ -20,38 +20,39 @@ export class FootnoteView {
this.getPos = getPos;
// The node's representation in the editor (empty, for now)
- this.dom = document.createElement("footnote");
+ this.dom = document.createElement('footnote');
- this.dom.addEventListener("pointerup", this.toggle, true);
+ this.dom.addEventListener('pointerup', this.toggle, true);
// These are used when the footnote is selected
this.innerView = null;
}
selectNode() {
- this.dom.classList.add("ProseMirror-selectednode");
+ this.dom.classList.add('ProseMirror-selectednode');
if (!this.innerView) this.open();
}
deselectNode() {
- this.dom.classList.remove("ProseMirror-selectednode");
+ this.dom.classList.remove('ProseMirror-selectednode');
if (this.innerView) this.close();
}
open() {
// Append a tooltip to the outer node
- const tooltip = this.dom.appendChild(document.createElement("div"));
- tooltip.className = "footnote-tooltip";
+ const tooltip = this.dom.appendChild(document.createElement('div'));
+ tooltip.className = 'footnote-tooltip';
// And put a sub-ProseMirror into that
this.innerView = new EditorView(tooltip, {
// You can use any node as an editor document
state: EditorState.create({
doc: this.node,
- plugins: [keymap(baseKeymap),
- keymap({
- "Mod-z": () => undo(this.outerView.state, this.outerView.dispatch),
- "Mod-y": () => redo(this.outerView.state, this.outerView.dispatch),
- "Mod-b": toggleMark(schema.marks.strong)
- }),
+ plugins: [
+ keymap(baseKeymap),
+ keymap({
+ 'Mod-z': () => undo(this.outerView.state, this.outerView.dispatch),
+ 'Mod-y': () => redo(this.outerView.state, this.outerView.dispatch),
+ 'Mod-b': toggleMark(schema.marks.strong),
+ }),
// new Plugin({
// view(newView) {
// // TODO -- make this work with RichTextMenu
@@ -59,7 +60,6 @@ export class FootnoteView {
// }
// })
],
-
}),
// This is the magic part
dispatchTransaction: this.dispatchInner.bind(this),
@@ -69,36 +69,39 @@ export class FootnoteView {
// footnote is node-selected (and thus DOM-selected) when
// the parent editor is focused.
e.stopPropagation();
- document.addEventListener("pointerup", this.ignore, true);
+ document.addEventListener('pointerup', this.ignore, true);
if (this.outerView.hasFocus()) this.innerView.focus();
- }) as any
- }
+ }) as any,
+ },
});
setTimeout(() => this.innerView?.docView.setSelection(0, 0, this.innerView.root, true), 0);
}
ignore = (e: PointerEvent) => {
e.stopPropagation();
- document.removeEventListener("pointerup", this.ignore, true);
- }
+ document.removeEventListener('pointerup', this.ignore, true);
+ };
toggle = () => {
+ console.log('TOGGLE');
if (this.innerView) this.close();
else this.open();
- }
+ };
close() {
+ console.log('CLOSE');
this.innerView?.destroy();
this.innerView = null;
- this.dom.textContent = "";
+ this.dom.textContent = '';
}
dispatchInner(tr: any) {
const { state, transactions } = this.innerView.state.applyTransaction(tr);
this.innerView.updateState(state);
- if (!tr.getMeta("fromOutside")) {
- const outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1);
+ if (!tr.getMeta('fromOutside')) {
+ const outerTr = this.outerView.state.tr,
+ offsetMap = StepMap.offset(this.getPos() + 1);
for (const transaction of transactions) {
for (const step of transaction.steps) {
outerTr.step(step.map(offsetMap));
@@ -117,11 +120,11 @@ export class FootnoteView {
if (start !== null) {
let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content);
const overlap = start - Math.min(endA, endB);
- if (overlap > 0) { endA += overlap; endB += overlap; }
- this.innerView.dispatch(
- state.tr
- .replace(start, endB, node.slice(start, endA))
- .setMeta("fromOutside", true));
+ if (overlap > 0) {
+ endA += overlap;
+ endB += overlap;
+ }
+ this.innerView.dispatch(state.tr.replace(start, endB, node.slice(start, endA)).setMeta('fromOutside', true));
}
}
return true;
@@ -139,4 +142,3 @@ export class FootnoteView {
return true;
}
}
-
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 8407eee96..80832c9be 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1611,7 +1611,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
@action
onBlur = (e: any) => {
if (this.ProseRef?.children[0] !== e.nativeEvent.target) return;
- this.autoLink();
+ if (!(this.EditorView?.state.selection instanceof NodeSelection) || this.EditorView.state.selection.node.type !== this.EditorView.state.schema.nodes.footnote) {
+ this.autoLink();
+ }
FormattedTextBox.Focused === this && (FormattedTextBox.Focused = undefined);
if (RichTextMenu.Instance?.view === this._editorView && !this.props.isSelected(true)) {
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined);
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index ff05dcdcb..d9bc2d981 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -2048,7 +2048,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
</div>
<Tooltip title={<div className="dash-tooltip">{this.layoutDoc.presStatus === PresStatus.Autoplay ? 'Pause' : 'Autoplay'}</div>}>
<div className="presPanel-button" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.startOrPause(true), false, false)}>
- <FontAwesomeIcon icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'pause' : 'play'} />
+ <FontAwesomeIcon color={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'red' : undefined} icon={this.layoutDoc.presStatus === PresStatus.Autoplay ? 'pause' : 'play'} />
</div>
</Tooltip>
<div
diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts
index 0b51db70b..4b1855cb0 100644
--- a/src/fields/SchemaHeaderField.ts
+++ b/src/fields/SchemaHeaderField.ts
@@ -2,7 +2,7 @@ import { Deserializable } from '../client/util/SerializationHelper';
import { serializable, primitive } from 'serializr';
import { ObjectField } from './ObjectField';
import { Copy, ToScriptString, ToString, OnUpdate } from './FieldSymbols';
-import { scriptingGlobal } from '../client/util/ScriptingGlobals';
+import { scriptingGlobal, ScriptingGlobals } from '../client/util/ScriptingGlobals';
import { ColumnType } from '../client/views/collections/collectionSchema/CollectionSchemaView';
export const PastelSchemaPalette = new Map<string, string>([
@@ -115,9 +115,12 @@ export class SchemaHeaderField extends ObjectField {
}
[ToScriptString]() {
- return `header(${this.heading},${this.type},${this.width}})`;
+ return `schemaHeaderField("${this.heading}","${this.color}",${this.type},${this.width},${this.desc},${this.collapsed})`;
}
[ToString]() {
return `SchemaHeaderField`;
}
}
+ScriptingGlobals.add(function schemaHeaderField(heading: string, color: string, type: number, width: number, desc?: boolean, collapsed?: boolean) {
+ return new SchemaHeaderField(heading, color, type, width, desc, collapsed);
+});