aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-07-07 16:20:33 -0400
committerbobzel <zzzman@gmail.com>2022-07-07 16:20:33 -0400
commitb7e66da6b23cdb41c127000dfe13843d35f7d0cc (patch)
tree97f74e2c5dde93d470cb928a0577435927fc2e80
parent897544f4bbe003778bcc48a11fd30b57f9e1ea50 (diff)
fixed more errors.
-rw-r--r--package.json2
-rw-r--r--src/client/views/InkTranscription.tsx354
-rw-r--r--src/client/views/StyleProvider.tsx348
-rw-r--r--src/client/views/collections/CollectionDockingView.scss29
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx337
-rw-r--r--src/client/views/collections/TabDocView.tsx609
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.scss27
-rw-r--r--src/client/views/collections/collectionSchema/CollectionSchemaView.tsx610
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx582
9 files changed, 1592 insertions, 1306 deletions
diff --git a/package.json b/package.json
index c2b6c24bf..2e3ef0a07 100644
--- a/package.json
+++ b/package.json
@@ -241,7 +241,7 @@
"path-browserify": "^1.0.1",
"pdf-parse": "^1.1.1",
"pdfjs": "^2.4.7",
- "pdfjs-dist": "^2.13.216",
+ "pdfjs-dist": "^2.14.305",
"probe-image-size": "^4.0.0",
"process": "^0.11.10",
"prosemirror-commands": "^1.2.1",
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 487bbcd00..5936ea32d 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -2,16 +2,15 @@ import * as iink from 'iink-js';
import { action, observable } from 'mobx';
import * as React from 'react';
import { Doc, DocListCast, HeightSym, WidthSym } from '../../fields/Doc';
-import { InkData, InkField, InkTool } from "../../fields/InkField";
+import { InkData, InkField, InkTool } from '../../fields/InkField';
import { Cast, DateCast, NumCast } from '../../fields/Types';
import { aggregateBounds } from '../../Utils';
-import { DocumentType } from "../documents/DocumentTypes";
-import { DocumentManager } from "../util/DocumentManager";
+import { DocumentType } from '../documents/DocumentTypes';
+import { DocumentManager } from '../util/DocumentManager';
import { CollectionFreeFormView } from './collections/collectionFreeForm';
import { InkingStroke } from './InkingStroke';
import { CurrentUserUtils } from '../util/CurrentUserUtils';
-import "./InkTranscription.scss";
-
+import './InkTranscription.scss';
/**
* Class component that handles inking in writing mode
@@ -40,124 +39,128 @@ export class InkTranscription extends React.Component {
@action
setMathRef = (r: any) => {
if (!this._mathRegister) {
- this._mathRegister = r ? iink.register(r, {
- recognitionParams: {
- type: 'MATH',
- protocol: 'WEBSOCKET',
- server: {
- host: 'cloud.myscript.com',
- applicationKey: process.env.IINKJS_APP,
- hmacKey: process.env.IINKJS_HMAC,
- websocket: {
- pingEnabled: false,
- autoReconnect: true
- }
- },
- iink: {
- math: {
- mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix']
- },
- export: {
- jiix: {
- strokes: true
- }
- }
- }
- }
- }) : null;
+ this._mathRegister = r
+ ? iink.register(r, {
+ recognitionParams: {
+ type: 'MATH',
+ protocol: 'WEBSOCKET',
+ server: {
+ host: 'cloud.myscript.com',
+ applicationKey: process.env.IINKJS_APP,
+ hmacKey: process.env.IINKJS_HMAC,
+ websocket: {
+ pingEnabled: false,
+ autoReconnect: true,
+ },
+ },
+ iink: {
+ math: {
+ mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix'],
+ },
+ export: {
+ jiix: {
+ strokes: true,
+ },
+ },
+ },
+ },
+ })
+ : null;
}
r.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef));
- return this._mathRef = r;
- }
+ return (this._mathRef = r);
+ };
@action
setTextRef = (r: any) => {
if (!this._textRegister) {
- this._textRegister = r ? iink.register(r, {
- recognitionParams: {
- type: 'TEXT',
- protocol: 'WEBSOCKET',
- server: {
- host: 'cloud.myscript.com',
- applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f',
- hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1',
- websocket: {
- pingEnabled: false,
- autoReconnect: true
- }
- },
- iink: {
- text: {
- mimeTypes: ['text/plain']
- },
- export: {
- jiix: {
- strokes: true
- }
- }
- }
- }
- }) : null;
+ this._textRegister = r
+ ? iink.register(r, {
+ recognitionParams: {
+ type: 'TEXT',
+ protocol: 'WEBSOCKET',
+ server: {
+ host: 'cloud.myscript.com',
+ applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f',
+ hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1',
+ websocket: {
+ pingEnabled: false,
+ autoReconnect: true,
+ },
+ },
+ iink: {
+ text: {
+ mimeTypes: ['text/plain'],
+ },
+ export: {
+ jiix: {
+ strokes: true,
+ },
+ },
+ },
+ },
+ })
+ : null;
}
r.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
- return this._textRef = r;
- }
+ return (this._textRef = r);
+ };
/**
* Handles processing Dash Doc data for ink transcription.
- *
- * @param groupDoc the group which contains the ink strokes we want to transcribe
- * @param containingLayout the layout which contains the group
+ *
+ * @param groupDoc the group which contains the ink strokes we want to transcribe
* @param inkDocs the ink docs contained within the selected group
* @param math boolean whether to do math transcription or not
*/
- transcribeInk = (groupDoc: Doc | undefined, containingLayout: Doc, inkDocs: Doc[], math: boolean) => {
+ transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => {
if (!groupDoc) return;
const validInks = inkDocs.filter(s => s.type === DocumentType.INK);
const strokes: InkData[] = [];
const times: number[] = [];
- validInks.filter(i => Cast(i.data, InkField)).forEach(i => {
- const d = Cast(i.data, InkField, null);
- const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke;
- strokes.push(d.inkData.map(pd => (inkStroke.ptToScreen({ X: pd.X, Y: pd.Y }))));
- times.push(DateCast(i.creationDate).getDate().getTime());
- });
+ validInks
+ .filter(i => Cast(i.data, InkField))
+ .forEach(i => {
+ const d = Cast(i.data, InkField, null);
+ const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke;
+ strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y })));
+ times.push(DateCast(i.creationDate).getDate().getTime());
+ });
this.currGroup = groupDoc;
- const pointerData = { "events": strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) };
+ const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) };
const processGestures = false;
if (math) {
this._mathRef.editor.pointerEvents(pointerData, processGestures);
- }
- else {
+ } else {
this._textRef.editor.pointerEvents(pointerData, processGestures);
}
- }
+ };
/**
* Converts the Dash Ink Data to JSON.
- *
+ *
* @param stroke The dash ink data
* @param time the time of the stroke
* @returns json object representation of ink data
*/
inkJSON = (stroke: InkData, time: number) => {
return {
- "pointerType": "PEN",
- "pointerId": 1,
- "x": stroke.map(point => point.X),
- "y": stroke.map(point => point.Y),
- "t": new Array(stroke.length).fill(time),
- "p": new Array(stroke.length).fill(1.0)
+ pointerType: 'PEN',
+ pointerId: 1,
+ x: stroke.map(point => point.X),
+ y: stroke.map(point => point.Y),
+ t: new Array(stroke.length).fill(time),
+ p: new Array(stroke.length).fill(1.0),
};
- }
+ };
/**
* Creates subgroups for each word for the whole text transcription
@@ -181,11 +184,11 @@ export class InkTranscription extends React.Component {
if (!marqViewRef) return;
this.groupInkDocs(selected, docView, word);
});
- }
+ };
/**
* Event listener function for when the 'exported' event is heard.
- *
+ *
* @param e the event objects
* @param ref the ref to the editor
*/
@@ -200,24 +203,23 @@ export class InkTranscription extends React.Component {
}
ref.editor.clear();
- }
- else if (exports['text/plain']) {
+ } else if (exports['text/plain']) {
if (exports['application/vnd.myscript.jiix']) {
this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']);
// map timestamp to strokes
const timestampWord = new Map<number, string>();
this.lastJiix.words.map((word: any) => {
if (word.items) {
- word.items.forEach((i: { id: string, timestamp: string, X: Array<number>, Y: Array<number>, F: Array<number> }) => {
+ word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => {
const ms = Date.parse(i.timestamp);
timestampWord.set(ms, word.label);
- })
+ });
}
- })
+ });
const wordInkDocMap = new Map<string, Doc[]>();
if (this.currGroup) {
- const docList = DocListCast(this.currGroup.data)
+ const docList = DocListCast(this.currGroup.data);
docList.forEach((inkDoc: Doc) => {
// just having the times match up and be a unique value (actual timestamp doesn't matter)
const ms = DateCast(inkDoc.creationDate).getDate().getTime() + 14400000;
@@ -241,108 +243,106 @@ export class InkTranscription extends React.Component {
if (this.currGroup) {
this.currGroup.transcription = text;
- this.currGroup.title = text.split("\n")[0];
+ this.currGroup.title = text.split('\n')[0];
}
ref.editor.clear();
}
}
- }
-
-/**
- * Creates the ink grouping once the user leaves the writing mode.
- */
-createInkGroup() {
- // TODO nda - if document being added to is a inkGrouping then we can just add to that group
- if (CurrentUserUtils.ActiveTool === InkTool.Write) {
- CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
- // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
- const selected = ffView.unprocessedDocs;
- const newCollection = this.groupInkDocs(selected, ffView);
- ffView.unprocessedDocs = [];
-
- InkTranscription.Instance.transcribeInk(newCollection, ffView.layoutDoc, selected, false);
- });
- }
- CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
-}
+ };
-/**
- * Creates the groupings for a given list of ink docs on a specific doc view
- * @param selected: the list of ink docs to create a grouping of
- * @param docView: the view in which we want the grouping to be created
- * @param word: optional param if the group we are creating is a word (subgrouping individual words)
- * @returns a new collection Doc or undefined if the grouping fails
- */
- groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined {
- const bounds: { x: number, y: number, width?: number, height?: number }[] = []
-
- // calculate the necessary bounds from the selected ink docs
- selected.map(action(d => {
- const x = NumCast(d.x);
- const y = NumCast(d.y);
- const width = d[WidthSym]();
- const height = d[HeightSym]();
- bounds.push({ x, y, width, height });
- }))
-
- // calculate the aggregated bounds
- const aggregBounds = aggregateBounds(bounds, 0, 0);
- const marqViewRef = docView._marqueeViewRef.current;
-
- // set the vals for bounds in marqueeView
- if (marqViewRef) {
- marqViewRef._downX = aggregBounds.x;
- marqViewRef._downY = aggregBounds.y;
- marqViewRef._lastX = aggregBounds.r;
- marqViewRef._lastY = aggregBounds.b;
+ /**
+ * Creates the ink grouping once the user leaves the writing mode.
+ */
+ createInkGroup() {
+ // TODO nda - if document being added to is a inkGrouping then we can just add to that group
+ if (CurrentUserUtils.ActiveTool === InkTool.Write) {
+ CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
+ // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
+ const selected = ffView.unprocessedDocs;
+ const newCollection = this.groupInkDocs(selected, ffView);
+ ffView.unprocessedDocs = [];
+
+ InkTranscription.Instance.transcribeInk(newCollection, selected, false);
+ });
+ }
+ CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
}
- // map through all the selected ink strokes and create the groupings
- selected.map(action(d => {
- const dx = NumCast(d.x);
- const dy = NumCast(d.y);
- delete d.x;
- delete d.y;
- delete d.activeFrame;
- delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
- delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
- // calculate pos based on bounds
- if (marqViewRef?.Bounds) {
- d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
- d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
+ /**
+ * Creates the groupings for a given list of ink docs on a specific doc view
+ * @param selected: the list of ink docs to create a grouping of
+ * @param docView: the view in which we want the grouping to be created
+ * @param word: optional param if the group we are creating is a word (subgrouping individual words)
+ * @returns a new collection Doc or undefined if the grouping fails
+ */
+ groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined {
+ const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
+
+ // calculate the necessary bounds from the selected ink docs
+ selected.map(
+ action(d => {
+ const x = NumCast(d.x);
+ const y = NumCast(d.y);
+ const width = d[WidthSym]();
+ const height = d[HeightSym]();
+ bounds.push({ x, y, width, height });
+ })
+ );
+
+ // calculate the aggregated bounds
+ const aggregBounds = aggregateBounds(bounds, 0, 0);
+ const marqViewRef = docView._marqueeViewRef.current;
+
+ // set the vals for bounds in marqueeView
+ if (marqViewRef) {
+ marqViewRef._downX = aggregBounds.x;
+ marqViewRef._downY = aggregBounds.y;
+ marqViewRef._lastX = aggregBounds.r;
+ marqViewRef._lastY = aggregBounds.b;
}
- return d;
- }));
- docView.props.removeDocument?.(selected);
- // Gets a collection based on the selected nodes using a marquee view ref
- const newCollection = marqViewRef?.getCollection(selected, undefined, true);
- if (newCollection) {
- newCollection.height = newCollection[HeightSym]();
- newCollection.width = newCollection[WidthSym]();
- // if the grouping we are creating is an individual word
- if (word) {
- newCollection.title = word;
+
+ // map through all the selected ink strokes and create the groupings
+ selected.map(
+ action(d => {
+ const dx = NumCast(d.x);
+ const dy = NumCast(d.y);
+ delete d.x;
+ delete d.y;
+ delete d.activeFrame;
+ delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+ delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+ // calculate pos based on bounds
+ if (marqViewRef?.Bounds) {
+ d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
+ d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
+ }
+ return d;
+ })
+ );
+ docView.props.removeDocument?.(selected);
+ // Gets a collection based on the selected nodes using a marquee view ref
+ const newCollection = marqViewRef?.getCollection(selected, undefined, true);
+ if (newCollection) {
+ newCollection.height = newCollection[HeightSym]();
+ newCollection.width = newCollection[WidthSym]();
+ // if the grouping we are creating is an individual word
+ if (word) {
+ newCollection.title = word;
+ }
}
- }
- // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
- newCollection && docView.props.addDocument?.(newCollection);
- return newCollection;
-}
+ // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
+ newCollection && docView.props.addDocument?.(newCollection);
+ return newCollection;
+ }
render() {
return (
<div className="ink-transcription">
- <div className='math-editor'
- ref={this.setMathRef}
- touch-action="none">
- </div>
- <div className='text-editor'
- ref={this.setTextRef}
- touch-action="none">
- </div>
+ <div className="math-editor" ref={this.setMathRef} touch-action="none"></div>
+ <div className="text-editor" ref={this.setTextRef} touch-action="none"></div>
</div>
- )
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 35415ae4e..a9770d253 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -1,13 +1,11 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import 'golden-layout/src/css/goldenlayout-base.css';
-import 'golden-layout/src/css/goldenlayout-dark-theme.css';
import { action, runInAction } from 'mobx';
import { extname } from 'path';
-import { Doc, Opt, StrListCast } from "../../fields/Doc";
+import { Doc, Opt, StrListCast } from '../../fields/Doc';
import { List } from '../../fields/List';
import { listSpec } from '../../fields/Schema';
-import { BoolCast, Cast, ImageCast, NumCast, StrCast } from "../../fields/Types";
+import { BoolCast, Cast, ImageCast, NumCast, StrCast } from '../../fields/Types';
import { DashColor, lightOrDark } from '../../Utils';
import { DocumentType } from '../documents/DocumentTypes';
import { CurrentUserUtils } from '../util/CurrentUserUtils';
@@ -16,227 +14,307 @@ import { ColorScheme } from '../util/SettingsManager';
import { SnappingManager } from '../util/SnappingManager';
import { undoBatch, UndoManager } from '../util/UndoManager';
import { CollectionViewType } from './collections/CollectionView';
+import { TreeSort } from './collections/TreeView';
import { Colors } from './global/globalEnums';
+import { InkingStroke } from './InkingStroke';
import { MainView } from './MainView';
-import { DocumentViewProps } from "./nodes/DocumentView";
+import { DocumentViewProps } from './nodes/DocumentView';
import { FieldViewProps } from './nodes/FieldView';
import { SliderBox } from './nodes/SliderBox';
-import "./StyleProvider.scss";
-import React = require("react");
-import { InkingStroke } from './InkingStroke';
-import { TreeSort } from './collections/TreeView';
+import './StyleProvider.scss';
+import React = require('react');
export enum StyleProp {
- TreeViewIcon = "treeViewIcon",
- TreeViewSortings = "treeViewSortings",// options for how to sort tree view items
- DocContents = "docContents", // when specified, the JSX returned will replace the normal rendering of the document view
- Opacity = "opacity", // opacity of the document view
- Hidden = "hidden", // whether the document view should not be isplayed
- BoxShadow = "boxShadow", // box shadow - used for making collections standout and for showing clusters in free form views
- BorderRounding = "borderRounding", // border radius of the document view
- Color = "color", // foreground color of Document view items
- BackgroundColor = "backgroundColor", // background color of a document view
- WidgetColor = "widgetColor", // color to display UI widgets on a document view -- used for the sidebar divider dragger on a text note
- HideLinkButton = "hideLinkButton", // hides the blue-dot link button. used when a document acts like a button
- LinkSource = "linkSource", // source document of a link -- used by LinkAnchorBox
- PointerEvents = "pointerEvents", // pointer events for DocumentView -- inherits pointer events if not specified
- Decorations = "decorations", // additional decoration to display above a DocumentView -- currently only used to display a Lock for making things background
- HeaderMargin = "headerMargin", // margin at top of documentview, typically for displaying a title -- doc contents will start below that
- TitleHeight = "titleHeight", // Height of Title area
- ShowTitle = "showTitle", // whether to display a title on a Document (optional :hover suffix)
- JitterRotation = "jitterRotation", // whether documents should be randomly rotated
- BorderPath = "customBorder", // border path for document view
- FontSize = "fontSize", // size of text font
- FontFamily = "fontFamily", // size of text font
+ TreeViewIcon = 'treeViewIcon',
+ TreeViewSortings = 'treeViewSortings', // options for how to sort tree view items
+ DocContents = 'docContents', // when specified, the JSX returned will replace the normal rendering of the document view
+ Opacity = 'opacity', // opacity of the document view
+ Hidden = 'hidden', // whether the document view should not be isplayed
+ BoxShadow = 'boxShadow', // box shadow - used for making collections standout and for showing clusters in free form views
+ BorderRounding = 'borderRounding', // border radius of the document view
+ Color = 'color', // foreground color of Document view items
+ BackgroundColor = 'backgroundColor', // background color of a document view
+ WidgetColor = 'widgetColor', // color to display UI widgets on a document view -- used for the sidebar divider dragger on a text note
+ HideLinkButton = 'hideLinkButton', // hides the blue-dot link button. used when a document acts like a button
+ LinkSource = 'linkSource', // source document of a link -- used by LinkAnchorBox
+ PointerEvents = 'pointerEvents', // pointer events for DocumentView -- inherits pointer events if not specified
+ Decorations = 'decorations', // additional decoration to display above a DocumentView -- currently only used to display a Lock for making things background
+ HeaderMargin = 'headerMargin', // margin at top of documentview, typically for displaying a title -- doc contents will start below that
+ TitleHeight = 'titleHeight', // Height of Title area
+ ShowTitle = 'showTitle', // whether to display a title on a Document (optional :hover suffix)
+ JitterRotation = 'jitterRotation', // whether documents should be randomly rotated
+ BorderPath = 'customBorder', // border path for document view
+ FontSize = 'fontSize', // size of text font
+ FontFamily = 'fontFamily', // size of text font
}
-function darkScheme() { return CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark; }
+function darkScheme() {
+ return CurrentUserUtils.ActiveDashboard?.colorScheme === ColorScheme.Dark;
+}
function toggleLockedPosition(doc: Doc) {
- UndoManager.RunInBatch(() => runInAction(() => {
- doc._lockedPosition = !doc._lockedPosition;
- doc._pointerEvents = doc._lockedPosition ? "none" : undefined;
- }), "toggleBackground");
+ UndoManager.RunInBatch(
+ () =>
+ runInAction(() => {
+ doc._lockedPosition = !doc._lockedPosition;
+ doc._pointerEvents = doc._lockedPosition ? 'none' : undefined;
+ }),
+ 'toggleBackground'
+ );
}
export function testDocProps(toBeDetermined: any): toBeDetermined is DocumentViewProps {
- return (toBeDetermined?.isContentActive) ? toBeDetermined : undefined;
+ return toBeDetermined?.isContentActive ? toBeDetermined : undefined;
}
export function wavyBorderPath(pw: number, ph: number, inset: number = 0.05) {
- return `M ${pw * .5} ${ph * inset} C ${pw * .6} ${ph * inset} ${pw * (1 - 2 * inset)} 0 ${pw * (1 - inset)} ${ph * inset} C ${pw} ${ph * (2 * inset)} ${pw * (1 - inset)} ${ph * .25} ${pw * (1 - inset)} ${ph * .3} C ${pw * (1 - inset)} ${ph * .4} ${pw} ${ph * (1 - 2 * inset)} ${pw * (1 - inset)} ${ph * (1 - inset)} C ${pw * (1 - 2 * inset)} ${ph} ${pw * .6} ${ph * (1 - inset)} ${pw * .5} ${ph * (1 - inset)} C ${pw * .3} ${ph * (1 - inset)} ${pw * (2 * inset)} ${ph} ${pw * inset} ${ph * (1 - inset)} C 0 ${ph * (1 - 2 * inset)} ${pw * inset} ${ph * .8} ${pw * inset} ${ph * .75} C ${pw * inset} ${ph * .7} 0 ${ph * (2 * inset)} ${pw * inset} ${ph * inset} C ${pw * (2 * inset)} 0 ${pw * .25} ${ph * inset} ${pw * .5} ${ph * inset}`;
+ return `M ${pw * 0.5} ${ph * inset} C ${pw * 0.6} ${ph * inset} ${pw * (1 - 2 * inset)} 0 ${pw * (1 - inset)} ${ph * inset} C ${pw} ${ph * (2 * inset)} ${pw * (1 - inset)} ${ph * 0.25} ${pw * (1 - inset)} ${ph * 0.3} C ${
+ pw * (1 - inset)
+ } ${ph * 0.4} ${pw} ${ph * (1 - 2 * inset)} ${pw * (1 - inset)} ${ph * (1 - inset)} C ${pw * (1 - 2 * inset)} ${ph} ${pw * 0.6} ${ph * (1 - inset)} ${pw * 0.5} ${ph * (1 - inset)} C ${pw * 0.3} ${ph * (1 - inset)} ${pw * (2 * inset)} ${ph} ${
+ pw * inset
+ } ${ph * (1 - inset)} C 0 ${ph * (1 - 2 * inset)} ${pw * inset} ${ph * 0.8} ${pw * inset} ${ph * 0.75} C ${pw * inset} ${ph * 0.7} 0 ${ph * (2 * inset)} ${pw * inset} ${ph * inset} C ${pw * (2 * inset)} 0 ${pw * 0.25} ${ph * inset} ${
+ pw * 0.5
+ } ${ph * inset}`;
}
// a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab
-//
+//
export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any {
- const remoteDocHeader = "author;creationDate;noMargin";
+ const remoteDocHeader = 'author;creationDate;noMargin';
const docProps = testDocProps(props) ? props : undefined;
- const selected = property.includes(":selected");
- const isCaption = property.includes(":caption");
- const isAnchor = property.includes(":anchor");
- const isAnnotated = property.includes(":annotated");
- const isOpen = property.includes(":open");
- const fieldKey = props?.fieldKey ? props.fieldKey + "-" : isCaption ? "caption-" : "";
- const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === "comic";
+ const selected = property.includes(':selected');
+ const isCaption = property.includes(':caption');
+ const isAnchor = property.includes(':anchor');
+ const isAnnotated = property.includes(':annotated');
+ const isOpen = property.includes(':open');
+ const fieldKey = props?.fieldKey ? props.fieldKey + '-' : isCaption ? 'caption-' : '';
+ const comicStyle = () => doc && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic';
const isBackground = () => doc && BoolCast(doc._lockedPosition);
const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle);
- const random = (min: number, max: number, x: number, y: number) => /* min should not be equal to max */ min + ((Math.abs(x * y) * 9301 + 49297) % 233280 / 233280) * (max - min);
- switch (property.split(":")[0]) {
+ const random = (min: number, max: number, x: number, y: number) => /* min should not be equal to max */ min + (((Math.abs(x * y) * 9301 + 49297) % 233280) / 233280) * (max - min);
+ switch (property.split(':')[0]) {
case StyleProp.TreeViewIcon:
const img = ImageCast(doc?.icon, ImageCast(doc?.data));
if (img) {
const ext = extname(img.url.href);
- const url = doc?.icon ? img.url.href : img.url.href.replace(ext, "_s" + ext);
- return <img src={url} width={20} height={15} style={{ margin: "auto", display: "block", objectFit: "contain" }} />;
+ const url = doc?.icon ? img.url.href : img.url.href.replace(ext, '_s' + ext);
+ return <img src={url} width={20} height={15} style={{ margin: 'auto', display: 'block', objectFit: 'contain' }} />;
}
return Doc.toIcon(doc, isOpen);
case StyleProp.TreeViewSortings:
- const allSorts: { [key: string]: { color: string, label: string } | undefined } = {};
- allSorts[TreeSort.Down] = { color: "blue", label: "↓" };
- allSorts[TreeSort.Up] = { color: "crimson", label: "↑" };
- if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: "green", label: "z" };
- allSorts[TreeSort.None] = { color: "darkgray", label: '\u00A0\u00A0\u00A0' };
+ const allSorts: { [key: string]: { color: string; label: string } | undefined } = {};
+ allSorts[TreeSort.Down] = { color: 'blue', label: '↓' };
+ allSorts[TreeSort.Up] = { color: 'crimson', label: '↑' };
+ if (doc?._viewType === CollectionViewType.Freeform) allSorts[TreeSort.Zindex] = { color: 'green', label: 'z' };
+ allSorts[TreeSort.None] = { color: 'darkgray', label: '\u00A0\u00A0\u00A0' };
return allSorts;
- case StyleProp.DocContents: return undefined;
- case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? "lightgrey" : "dimgrey";
- case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
- case StyleProp.HideLinkButton: return props?.hideLinkButton || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
- case StyleProp.FontSize: return StrCast(doc?.[fieldKey + "fontSize"], StrCast(doc?.fontSize, StrCast(Doc.UserDoc().fontSize)));
- case StyleProp.FontFamily: return StrCast(doc?.[fieldKey + "fontFamily"], StrCast(doc?.fontFamily, StrCast(Doc.UserDoc().fontFamily)));
- case StyleProp.ShowTitle: return (doc && !doc.presentationTargetDoc &&
- StrCast(doc._showTitle,
- props?.showTitle?.() ||
- (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any) ?
- (doc.author === Doc.CurrentUserEmail ? StrCast(Doc.UserDoc().showTitle) :
- remoteDocHeader) : "")) || "");
+ case StyleProp.DocContents:
+ return undefined;
+ case StyleProp.WidgetColor:
+ return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? 'lightgrey' : 'dimgrey';
+ case StyleProp.Opacity:
+ return Cast(doc?._opacity, 'number', Cast(doc?.opacity, 'number', null));
+ case StyleProp.HideLinkButton:
+ return props?.hideLinkButton || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
+ case StyleProp.FontSize:
+ return StrCast(doc?.[fieldKey + 'fontSize'], StrCast(doc?.fontSize, StrCast(Doc.UserDoc().fontSize)));
+ case StyleProp.FontFamily:
+ return StrCast(doc?.[fieldKey + 'fontFamily'], StrCast(doc?.fontFamily, StrCast(Doc.UserDoc().fontFamily)));
+ case StyleProp.ShowTitle:
+ return (
+ (doc &&
+ !doc.presentationTargetDoc &&
+ StrCast(
+ doc._showTitle,
+ props?.showTitle?.() ||
+ (!Doc.IsSystem(doc) && [DocumentType.COL, DocumentType.LABEL, DocumentType.RTF, DocumentType.IMG, DocumentType.VID].includes(doc.type as any)
+ ? doc.author === Doc.CurrentUserEmail
+ ? StrCast(Doc.UserDoc().showTitle)
+ : remoteDocHeader
+ : '')
+ )) ||
+ ''
+ );
case StyleProp.Color:
if (MainView.Instance.LastButton === doc) return Colors.DARK_GRAY;
- const docColor: Opt<string> = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color));
+ const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color));
if (docColor) return docColor;
const docView = props?.DocumentView?.();
- const backColor = backgroundCol() || docView?.props.styleProvider?.(docView.props.treeViewDoc, docView.props, "backgroundColor");
+ const backColor = backgroundCol() || docView?.props.styleProvider?.(docView.props.treeViewDoc, docView.props, 'backgroundColor');
if (!backColor) return undefined;
return lightOrDark(backColor);
- case StyleProp.Hidden: return BoolCast(doc?.hidden);
- case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"], StrCast(doc?.borderRounding, doc?._viewType === CollectionViewType.Pile ? "50%" : ""));
- case StyleProp.TitleHeight: return 15;
- case StyleProp.BorderPath: return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, .08), width: 3 } : { path: undefined, width: 0 };
- case StyleProp.JitterRotation: return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
- case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
- (doc?.type === DocumentType.RTF && !showTitle()?.includes("noMargin")) || doc?.type === DocumentType.LABEL) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
+ case StyleProp.Hidden:
+ return BoolCast(doc?.hidden);
+ case StyleProp.BorderRounding:
+ return StrCast(doc?.[fieldKey + 'borderRounding'], StrCast(doc?.borderRounding, doc?._viewType === CollectionViewType.Pile ? '50%' : ''));
+ case StyleProp.TitleHeight:
+ return 15;
+ case StyleProp.BorderPath:
+ return comicStyle() && props?.renderDepth && doc?.type !== DocumentType.INK
+ ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, 0.08), width: 3 }
+ : { path: undefined, width: 0 };
+ case StyleProp.JitterRotation:
+ return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
+ case StyleProp.HeaderMargin:
+ return ([CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) || (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) || doc?.type === DocumentType.LABEL) &&
+ showTitle() &&
+ !StrCast(doc?.showTitle).includes(':hover')
+ ? 15
+ : 0;
case StyleProp.BackgroundColor: {
if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY;
- let docColor: Opt<string> =
- StrCast(doc?.[fieldKey + "backgroundColor"],
- StrCast(doc?._backgroundColor,
- StrCast(props?.Document.backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : "")));
+ let docColor: Opt<string> = StrCast(doc?.[fieldKey + 'backgroundColor'], StrCast(doc?._backgroundColor, StrCast(props?.Document.backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : '')));
switch (doc?.type) {
- case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break;
- case DocumentType.PRES: docColor = docColor || (darkScheme() ? "transparent" : "transparent"); break;
- case DocumentType.FONTICON: docColor = docColor || Colors.DARK_GRAY; break;
- case DocumentType.RTF: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
- case DocumentType.FILTER: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : "rgba(105, 105, 105, 0.432)"); break;
- case DocumentType.INK: docColor = doc?.isInkMask ? "rgba(0,0,0,0.7)" : undefined; break;
- case DocumentType.SLIDER: break;
- case DocumentType.EQUATION: docColor = docColor || "transparent"; break;
- case DocumentType.LABEL: docColor = docColor || (doc.annotationOn !== undefined ? "rgba(128, 128, 128, 0.18)" : undefined) || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
- case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
- case DocumentType.LINKANCHOR: docColor = isAnchor ? Colors.LIGHT_BLUE : "transparent"; break;
- case DocumentType.LINK: docColor = (isAnchor ? docColor : "") || "transparent"; break;
+ case DocumentType.PRESELEMENT:
+ docColor = docColor || (darkScheme() ? '' : '');
+ break;
+ case DocumentType.PRES:
+ docColor = docColor || (darkScheme() ? 'transparent' : 'transparent');
+ break;
+ case DocumentType.FONTICON:
+ docColor = docColor || Colors.DARK_GRAY;
+ break;
+ case DocumentType.RTF:
+ docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY);
+ break;
+ case DocumentType.FILTER:
+ docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : 'rgba(105, 105, 105, 0.432)');
+ break;
+ case DocumentType.INK:
+ docColor = doc?.isInkMask ? 'rgba(0,0,0,0.7)' : undefined;
+ break;
+ case DocumentType.SLIDER:
+ break;
+ case DocumentType.EQUATION:
+ docColor = docColor || 'transparent';
+ break;
+ case DocumentType.LABEL:
+ docColor = docColor || (doc.annotationOn !== undefined ? 'rgba(128, 128, 128, 0.18)' : undefined) || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY);
+ break;
+ case DocumentType.BUTTON:
+ docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY);
+ break;
+ case DocumentType.LINKANCHOR:
+ docColor = isAnchor ? Colors.LIGHT_BLUE : 'transparent';
+ break;
+ case DocumentType.LINK:
+ docColor = (isAnchor ? docColor : '') || 'transparent';
+ break;
case DocumentType.IMG:
case DocumentType.WEB:
case DocumentType.PDF:
case DocumentType.MAP:
case DocumentType.SCREENSHOT:
- case DocumentType.VID: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+ case DocumentType.VID:
+ docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY);
+ break;
case DocumentType.COL:
if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
- docColor = docColor ||
- (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background
- doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc
- (doc?._isGroup ? undefined :
- Cast((props?.renderDepth || 0) > 0 ?
- Doc.UserDoc().activeCollectionNestedBackground :
- Doc.UserDoc().activeCollectionBackground, "string") ?? (darkScheme() ?
- Colors.BLACK :
- "linear-gradient(#065fff, #85c1f9)"))
- );
+ docColor =
+ docColor ||
+ (doc?._viewType === CollectionViewType.Pile || Doc.IsSystem(doc)
+ ? darkScheme()
+ ? Colors.DARK_GRAY
+ : Colors.LIGHT_GRAY // system docs (seen in treeView) get a grayish background
+ : doc.annotationOn
+ ? '#00000015' // faint interior for collections on PDFs, images, etc
+ : doc?._isGroup
+ ? undefined
+ : Cast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (darkScheme() ? Colors.BLACK : 'linear-gradient(#065fff, #85c1f9)'));
break;
//if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
- default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
+ default:
+ docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE);
+ break;
}
if (docColor && !doc) docColor = DashColor(docColor).fade(0.5).toString();
return docColor;
}
case StyleProp.BoxShadow: {
- if (!doc || opacity() === 0) return undefined; // if it's not visible, then no shadow)
+ if (!doc || opacity() === 0) return undefined; // if it's not visible, then no shadow)
- if (doc?.isLinkButton && ![DocumentType.LINK, DocumentType.INK].includes(doc.type as any)) return StrCast(doc?._linkButtonShadow, "lightblue 0em 0em 1em");
+ if (doc?.isLinkButton && ![DocumentType.LINK, DocumentType.INK].includes(doc.type as any)) return StrCast(doc?._linkButtonShadow, 'lightblue 0em 0em 1em');
switch (doc?.type) {
case DocumentType.COL:
- return StrCast(doc?.boxShadow,
- doc?._viewType === CollectionViewType.Pile ? "4px 4px 10px 2px" :
- isBackground() || doc?._isGroup || docProps?.LayoutTemplateString ? undefined : // groups have no drop shadow -- they're supposed to be "invisible". LayoutString's imply collection is being rendered as something else (e.g., title of a Slide)
- `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`);
+ return StrCast(
+ doc?.boxShadow,
+ doc?._viewType === CollectionViewType.Pile
+ ? '4px 4px 10px 2px'
+ : isBackground() || doc?._isGroup || docProps?.LayoutTemplateString
+ ? undefined // groups have no drop shadow -- they're supposed to be "invisible". LayoutString's imply collection is being rendered as something else (e.g., title of a Slide)
+ : `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.boxShadow, '0.2vw 0.2vw 0.8vw')}`
+ );
case DocumentType.LABEL:
- if (doc?.annotationOn !== undefined) return "black 2px 2px 1px";
+ if (doc?.annotationOn !== undefined) return 'black 2px 2px 1px';
default:
- return doc.z ? `#9c9396 ${StrCast(doc?.boxShadow, "10px 10px 0.9vw")}` : // if it's a floating doc, give it a big shadow
- props?.ContainingCollectionDoc?._useClusters && doc.type !== DocumentType.INK ? (`${backgroundCol()} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.ContentScaling?.() || 1)}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent
- NumCast(doc.group, -1) !== -1 && doc.type !== DocumentType.INK ? (`gray ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.ContentScaling?.() || 1)}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent
- isBackground() ? undefined : // if it's a background & has a cluster color, make the shadow spread really big
- StrCast(doc.boxShadow, "");
+ return doc.z
+ ? `#9c9396 ${StrCast(doc?.boxShadow, '10px 10px 0.9vw')}` // if it's a floating doc, give it a big shadow
+ : props?.ContainingCollectionDoc?._useClusters && doc.type !== DocumentType.INK
+ ? `${backgroundCol()} ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.ContentScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ : NumCast(doc.group, -1) !== -1 && doc.type !== DocumentType.INK
+ ? `gray ${StrCast(doc.boxShadow, `0vw 0vw ${(isBackground() ? 100 : 50) / (docProps?.ContentScaling?.() || 1)}px`)}` // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ : isBackground()
+ ? undefined // if it's a background & has a cluster color, make the shadow spread really big
+ : StrCast(doc.boxShadow, '');
}
}
case StyleProp.PointerEvents:
if (doc?.pointerEvents) return StrCast(doc.pointerEvents);
- if (props?.pointerEvents?.() === "none") return "none";
+ if (props?.pointerEvents?.() === 'none') return 'none';
const isInk = doc && StrCast(Doc.Layout(doc).layout).includes(InkingStroke.name);
- if (opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return "none";
- if (!isInk) return "all";
+ if (opacity() === 0 || (isInk && !docProps?.treeViewDoc) || doc?.isInkMask) return 'none';
+ if (!isInk) return 'all';
return undefined;
case StyleProp.Decorations:
if (props?.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform || doc?.x !== undefined || doc?.y !== undefined) {
- return doc && (isBackground() || selected) && !Doc.IsSystem(doc) && (props?.renderDepth || 0) > 0 &&
- ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ?
+ return doc &&
+ (isBackground() || selected) &&
+ !Doc.IsSystem(doc) &&
+ (props?.renderDepth || 0) > 0 &&
+ ((doc.type === DocumentType.COL && doc._viewType !== CollectionViewType.Pile) || [DocumentType.RTF, DocumentType.IMG, DocumentType.INK].includes(doc.type as DocumentType)) ? (
<div className="styleProvider-lock" onClick={() => toggleLockedPosition(doc)}>
- <FontAwesomeIcon icon={isBackground() ? "lock" : "unlock"} style={{ color: isBackground() ? "red" : undefined }} size="lg" />
+ <FontAwesomeIcon icon={isBackground() ? 'lock' : 'unlock'} style={{ color: isBackground() ? 'red' : undefined }} size="lg" />
</div>
- : (null);
+ ) : null;
}
}
}
export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) {
- return <div title={field} className={`styleProvider-treeView-icon${doc[field] ? "-active" : ""}`}
- onClick={undoBatch(action((e: React.MouseEvent) => {
- e.stopPropagation();
- clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true);
- }))}>
- <FontAwesomeIcon icon={(doc[field] ? onIcon as any : offIcon) as IconProp} size="sm" />
- </div>;
+ return (
+ <div
+ title={field}
+ className={`styleProvider-treeView-icon${doc[field] ? '-active' : ''}`}
+ onClick={undoBatch(
+ action((e: React.MouseEvent) => {
+ e.stopPropagation();
+ clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true);
+ })
+ )}>
+ <FontAwesomeIcon icon={(doc[field] ? (onIcon as any) : offIcon) as IconProp} size="sm" />
+ </div>
+ );
}
/**
* add lock and hide button decorations for the "Dashboards" flyout TreeView
*/
export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) {
-
- if (doc && property.split(":")[0] === StyleProp.Decorations) {
- return doc._viewType === CollectionViewType.Docking ? (null) :
+ if (doc && property.split(':')[0] === StyleProp.Decorations) {
+ return doc._viewType === CollectionViewType.Docking ? null : (
<>
- {DashboardToggleButton(doc, "hidden", "eye-slash", "eye", () => {
+ {DashboardToggleButton(doc, 'hidden', 'eye-slash', 'eye', () => {
doc.hidden = doc.hidden ? undefined : true;
if (!doc.hidden) {
DocFocusOrOpen(doc, props?.ContainingCollectionDoc);
}
})}
- </>;
+ </>
+ );
}
return DefaultStyleProvider(doc, props, property);
}
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 21045a20e..6d5a39bc2 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,5 +1,6 @@
-@import "../global/globalCssVariables.scss";
-
+@import '../global/globalCssVariables.scss';
+@import '../../../../node_modules/golden-layout/src/css/goldenlayout-base.css';
+@import '../../../../node_modules/golden-layout/src/css/goldenlayout-dark-theme.css';
.lm_title {
-webkit-appearance: none;
@@ -153,7 +154,7 @@
background: $white;
}
- .lm_controls>li {
+ .lm_controls > li {
opacity: 1;
transform: scale(1);
}
@@ -196,7 +197,7 @@
position: absolute;
cursor: move;
border: 2px solid #cfe8ff;
- box-shadow: inset 0 0 60px rgba(0, 0, 0, .2);
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.2);
border-radius: 5px;
z-index: 1000;
box-sizing: border-box;
@@ -205,7 +206,7 @@
.flexlayout__outline_rect_edge {
cursor: move;
border: 2px solid #b7d1b5;
- box-shadow: inset 0 0 60px rgba(0, 0, 0, .2);
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.2);
border-radius: 5px;
z-index: 1000;
box-sizing: border-box;
@@ -214,7 +215,7 @@
.flexlayout__edge_rect {
position: absolute;
z-index: 1000;
- box-shadow: inset 0 0 5px rgba(0, 0, 0, .2);
+ box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
background-color: lightgray;
}
@@ -222,7 +223,7 @@
position: absolute;
cursor: move;
border: 2px solid #aaaaaa;
- box-shadow: inset 0 0 60px rgba(0, 0, 0, .3);
+ box-shadow: inset 0 0 60px rgba(0, 0, 0, 0.3);
border-radius: 5px;
z-index: 1000;
box-sizing: border-box;
@@ -301,7 +302,7 @@
.flexlayout__tab_button:hover .flexlayout__tab_button_trailing,
.flexlayout__tab_button--selected .flexlayout__tab_button_trailing {
- background: transparent url("../../../../node_modules/flexlayout-react/images/close_white.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/close_white.png') no-repeat center;
}
.flexlayout__tab_button_overflow {
@@ -314,7 +315,7 @@
font-size: 10px;
color: lightgray;
font-family: Arial, sans-serif;
- background: transparent url("../../../../node_modules/flexlayout-react/images/more.png") no-repeat left;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/more.png') no-repeat left;
}
.flexlayout__tabset_header {
@@ -369,7 +370,7 @@
height: 20px;
border: none;
outline-width: 0;
- background: transparent url("../../../../node_modules/flexlayout-react/images/maximize.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/maximize.png') no-repeat center;
}
.flexlayout__tab_toolbar_button-max {
@@ -377,7 +378,7 @@
height: 20px;
border: none;
outline-width: 0;
- background: transparent url("../../../../node_modules/flexlayout-react/images/restore.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/restore.png') no-repeat center;
}
.flexlayout__popup_menu_item {
@@ -390,7 +391,7 @@
}
.flexlayout__popup_menu_container {
- box-shadow: inset 0 0 5px rgba(0, 0, 0, .15);
+ box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.15);
border: 1px solid #555;
background: #222;
border-radius: 3px;
@@ -497,7 +498,7 @@
.flexlayout__border_button:hover .flexlayout__border_button_trailing,
.flexlayout__border_button--selected .flexlayout__border_button_trailing {
- background: transparent url("../../../../node_modules/flexlayout-react/images/close_white.png") no-repeat center;
+ background: transparent url('../../../../node_modules/flexlayout-react/images/close_white.png') no-repeat center;
}
.flexlayout__border_toolbar_left {
@@ -539,4 +540,4 @@
bottom: 0;
right: 0;
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 0830b6fdf..27478e59b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,34 +1,32 @@
-import 'golden-layout/src/css/goldenlayout-base.css';
-import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx";
-import { observer } from "mobx-react";
+import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
import * as ReactDOM from 'react-dom';
-import * as GoldenLayout from "../../../client/goldenLayout";
-import { Doc, DocListCast, Opt } from "../../../fields/Doc";
+import * as GoldenLayout from '../../../client/goldenLayout';
+import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { inheritParentAcls } from '../../../fields/util';
import { emptyFunction, incrementTitleCopy } from '../../../Utils';
-import { DocServer } from "../../DocServer";
+import { DocServer } from '../../DocServer';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
-import { DragManager } from "../../util/DragManager";
+import { DragManager } from '../../util/DragManager';
import { InteractionUtils } from '../../util/InteractionUtils';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SelectionManager } from '../../util/SelectionManager';
-import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from '../../util/UndoManager';
import { LightboxView } from '../LightboxView';
-import "./CollectionDockingView.scss";
+import './CollectionDockingView.scss';
import { CollectionFreeFormView } from './collectionFreeForm';
-import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import { CollectionViewType } from './CollectionView';
import { TabDocView } from './TabDocView';
-import React = require("react");
-const _global = (window /* browser */ || global /* node */) as any;
+import React = require('react');
+const _global = (window /* browser */ || global) /* node */ as any;
@observer
export class CollectionDockingView extends CollectionSubView() {
@@ -41,8 +39,8 @@ export class CollectionDockingView extends CollectionSubView() {
width: width,
props: {
documentId: document[Id],
- panelName // name of tab that can be used to close or replace its contents
- }
+ panelName, // name of tab that can be used to close or replace its contents
+ },
};
}
@@ -50,14 +48,16 @@ export class CollectionDockingView extends CollectionSubView() {
private _lightboxReactionDisposer?: IReactionDisposer;
private _containerRef = React.createRef<HTMLDivElement>();
public _flush: UndoManager.Batch | undefined;
- private _ignoreStateChange = "";
+ private _ignoreStateChange = '';
public tabMap: Set<any> = new Set();
- public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; }
+ public get HasFullScreen() {
+ return this._goldenLayout._maximisedItem !== null;
+ }
private _goldenLayout: any = null;
constructor(props: SubCollectionViewProps) {
super(props);
- runInAction(() => CollectionDockingView.Instance = this);
+ runInAction(() => (CollectionDockingView.Instance = this));
//Why is this here?
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
@@ -66,19 +66,18 @@ export class CollectionDockingView extends CollectionSubView() {
/**
* Switches from dragging a document around a freeform canvas to dragging it as a tab to be docked.
- *
+ *
* @param e fake mouse down event position data containing pageX and pageY coordinates
* @param dragDocs the documents to be dragged
* @param batch optionally an undo batch that has been started to use instead of starting a new batch
- */
- public StartOtherDrag = (e: { pageX: number, pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => {
- this._flush = this._flush ?? UndoManager.StartBatch("golden layout drag");
- const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) :
- { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) };
- const dragSource = this._goldenLayout.createDragSource(document.createElement("div"), config);
+ */
+ public StartOtherDrag = (e: { pageX: number; pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => {
+ this._flush = this._flush ?? UndoManager.StartBatch('golden layout drag');
+ const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) : { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) };
+ const dragSource = this._goldenLayout.createDragSource(document.createElement('div'), config);
this.tabDragStart(dragSource, finishDrag);
dragSource._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 });
- }
+ };
tabItemDropped = () => DragManager.CompleteWindowDrag?.(false);
tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => {
@@ -88,7 +87,7 @@ export class CollectionDockingView extends CollectionSubView() {
if (aborted) {
proxy._dragListener.AbortDrag();
if (this._flush) {
- this._flush.cancel(); // cancel the undo change being logged
+ this._flush.cancel(); // cancel the undo change being logged
this._flush = undefined;
this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout)
}
@@ -96,16 +95,16 @@ export class CollectionDockingView extends CollectionSubView() {
}
finishDrag?.(aborted);
};
- }
+ };
@undoBatch
public CloseFullScreen = () => {
this._goldenLayout._maximisedItem?.toggleMaximise();
this.stateChanged();
- }
+ };
@undoBatch
public static CloseSplit(document: Opt<Doc>, panelName?: string): boolean {
- const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document);
+ const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find(tab => (panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document));
if (tab) {
const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
if (j !== -1) {
@@ -121,12 +120,12 @@ export class CollectionDockingView extends CollectionSubView() {
public static OpenFullScreen(doc: Doc) {
SelectionManager.DeselectAll();
const instance = CollectionDockingView.Instance;
- if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") {
+ if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === 'layout') {
return CurrentUserUtils.openDashboard(doc);
}
const newItemStackConfig = {
type: 'stack',
- content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))]
+ content: [CollectionDockingView.makeDocumentConfig(Doc.MakeAlias(doc))],
};
const docconfig = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
instance._goldenLayout.root.contentItems[0].addChild(docconfig);
@@ -150,7 +149,7 @@ export class CollectionDockingView extends CollectionSubView() {
stack.contentItems[activeContentItemIndex].remove();
return CollectionDockingView.Instance.layoutChanged();
}
- const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => tab.contentItem.config.props.panelName === panelName);
+ const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find(tab => tab.contentItem.config.props.panelName === panelName);
if (tab) {
tab.header.parent.addChild(newConfig, undefined);
const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
@@ -160,11 +159,9 @@ export class CollectionDockingView extends CollectionSubView() {
return CollectionDockingView.AddSplit(document, panelName, stack, panelName);
}
-
@undoBatch
public static ToggleSplit(doc: Doc, location: string, stack?: any, panelName?: string) {
- return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex((tab) => tab.DashDoc === doc) !== -1 ?
- CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName);
+ return Array.from(CollectionDockingView.Instance.tabMap.keys()).findIndex(tab => tab.DashDoc === doc) !== -1 ? CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName);
}
//
@@ -193,35 +190,37 @@ export class CollectionDockingView extends CollectionSubView() {
const newItem = glayRoot.layoutManager.createContentItem({ type: 'stack', content: [docContentConfig] }, instance._goldenLayout);
newItem.callDownwards('_$init');
return newItem;
- }
- if (glayRoot.contentItems.length === 0) { // if no rows / columns
+ };
+ if (glayRoot.contentItems.length === 0) {
+ // if no rows / columns
glayRoot.addChild(newContentItem());
} else if (glayRoot.contentItems[0].isStack) {
glayRoot.contentItems[0].addChild(docContentConfig);
- } else if (
- glayRoot.contentItems.length === 1 &&
- glayRoot.contentItems[0].contentItems.length === 1 &&
- glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) {
+ } else if (glayRoot.contentItems.length === 1 && glayRoot.contentItems[0].contentItems.length === 1 && glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) {
glayRoot.contentItems[0].contentItems[0].addChild(docContentConfig);
- }
- else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
+ } else if (instance._goldenLayout.root.contentItems[0].isRow) {
+ // if row
switch (pullSide) {
default:
- case "right": glayRoot.contentItems[0].addChild(newContentItem()); break;
- case "left": glayRoot.contentItems[0].addChild(newContentItem(), 0); break;
- case "top":
- case "bottom":
+ case 'right':
+ glayRoot.contentItems[0].addChild(newContentItem());
+ break;
+ case 'left':
+ glayRoot.contentItems[0].addChild(newContentItem(), 0);
+ break;
+ case 'top':
+ case 'bottom':
// if not going in a row layout, must add already existing content into column
const rowlayout = glayRoot.contentItems[0];
- const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
+ const newColumn = rowlayout.layoutManager.createContentItem({ type: 'column' }, instance._goldenLayout);
const newItem = newContentItem();
instance._goldenLayout.saveScrollTops(rowlayout.element);
rowlayout.parent.replaceChild(rowlayout, newColumn);
- if (pullSide === "top") {
+ if (pullSide === 'top') {
newColumn.addChild(rowlayout, undefined, true);
newColumn.addChild(newItem, 0, true);
- } else if (pullSide === "bottom") {
+ } else if (pullSide === 'bottom') {
newColumn.addChild(newItem, undefined, true);
newColumn.addChild(rowlayout, 0, true);
}
@@ -230,21 +229,26 @@ export class CollectionDockingView extends CollectionSubView() {
rowlayout.config.height = 50;
newItem.config.height = 50;
}
- } else {// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
+ } else {
+ // if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
switch (pullSide) {
- case "top": glayRoot.contentItems[0].addChild(newContentItem(), 0); break;
- case "bottom": glayRoot.contentItems[0].addChild(newContentItem()); break;
- case "left":
- case "right":
+ case 'top':
+ glayRoot.contentItems[0].addChild(newContentItem(), 0);
+ break;
+ case 'bottom':
+ glayRoot.contentItems[0].addChild(newContentItem());
+ break;
+ case 'left':
+ case 'right':
default:
// if not going in a row layout, must add already existing content into column
const collayout = glayRoot.contentItems[0];
- const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
+ const newRow = collayout.layoutManager.createContentItem({ type: 'row' }, instance._goldenLayout);
const newItem = newContentItem();
instance._goldenLayout.saveScrollTops(collayout.element);
collayout.parent.replaceChild(collayout, newRow);
- if (pullSide === "left") {
+ if (pullSide === 'left') {
newRow.addChild(collayout, undefined, true);
newRow.addChild(newItem, 0, true);
} else {
@@ -276,7 +280,7 @@ export class CollectionDockingView extends CollectionSubView() {
const config = StrCast(this.props.Document.dockingConfig);
if (config) {
const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) ?? [];
+ const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')) ?? [];
await Promise.all(docids.map(id => DocServer.GetRefField(id)));
if (this._goldenLayout) {
@@ -287,12 +291,12 @@ export class CollectionDockingView extends CollectionSubView() {
this._goldenLayout.unbind('tabCreated', this.tabCreated);
this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
this._goldenLayout.unbind('stackCreated', this.stackCreated);
- } catch (e) { }
+ } catch (e) {}
}
this.tabMap.clear();
this._goldenLayout.destroy();
}
- const glay = this._goldenLayout = new GoldenLayout(JSON.parse(config));
+ const glay = (this._goldenLayout = new GoldenLayout(JSON.parse(config)));
glay.on('tabCreated', this.tabCreated);
glay.on('tabDestroyed', this.tabDestroyed);
glay.on('stackCreated', this.stackCreated);
@@ -303,46 +307,52 @@ export class CollectionDockingView extends CollectionSubView() {
glay.root.layoutManager.on('dragStart', this.tabDragStart);
glay.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
}
- }
+ };
componentDidMount: () => void = () => {
if (this._containerRef.current) {
- this._lightboxReactionDisposer = reaction(() => LightboxView.LightboxDoc, doc => setTimeout(() => !doc && this.onResize(undefined)));
+ this._lightboxReactionDisposer = reaction(
+ () => LightboxView.LightboxDoc,
+ doc => setTimeout(() => !doc && this.onResize(undefined))
+ );
new _global.ResizeObserver(this.onResize).observe(this._containerRef.current);
- this._reactionDisposer = reaction(() => StrCast(this.props.Document.dockingConfig),
+ this._reactionDisposer = reaction(
+ () => StrCast(this.props.Document.dockingConfig),
config => {
- if (!this._goldenLayout || this._ignoreStateChange !== config) { // bcz: TODO! really need to diff config with ignoreStateChange and modify the current goldenLayout instead of building a new one.
+ if (!this._goldenLayout || this._ignoreStateChange !== config) {
+ // bcz: TODO! really need to diff config with ignoreStateChange and modify the current goldenLayout instead of building a new one.
this.setupGoldenLayout();
}
- this._ignoreStateChange = "";
- });
+ this._ignoreStateChange = '';
+ }
+ );
setTimeout(this.setupGoldenLayout);
//window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
}
- }
+ };
componentWillUnmount: () => void = () => {
try {
this._goldenLayout.unbind('stackCreated', this.stackCreated);
this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- } catch (e) { }
+ } catch (e) {}
this._goldenLayout?.destroy();
window.removeEventListener('resize', this.onResize);
this._reactionDisposer?.();
this._lightboxReactionDisposer?.();
- }
+ };
@action
onResize = (event: any) => {
const cur = this._containerRef.current;
// bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
!LightboxView.LightboxDoc && cur && this._goldenLayout?.updateSize(cur.getBoundingClientRect().width, cur.getBoundingClientRect().height);
- }
+ };
@action
onPointerUp = (e: MouseEvent): void => {
- window.removeEventListener("pointerup", this.onPointerUp);
+ window.removeEventListener('pointerup', this.onPointerUp);
const flush = this._flush;
this._flush = undefined;
if (flush) {
@@ -350,69 +360,65 @@ export class CollectionDockingView extends CollectionSubView() {
if (!this.stateChanged()) flush.cancel();
else flush.end();
}
- }
+ };
@action
onPointerDown = (e: React.PointerEvent): void => {
let hitFlyout = false;
for (let par = e.target as any; !hitFlyout && par; par = par.parentElement) {
- hitFlyout = (par.className === "dockingViewButtonSelector");
+ hitFlyout = par.className === 'dockingViewButtonSelector';
}
if (!hitFlyout) {
const htmlTarget = e.target as HTMLElement;
- window.addEventListener("mouseup", this.onPointerUp);
- if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) {
- const className = typeof htmlTarget.className === "string" ? htmlTarget.className : "";
- if (!className.includes("lm_close") && !className.includes("lm_maximise")) {
- this._flush = UndoManager.StartBatch("golden layout edit");
+ window.addEventListener('mouseup', this.onPointerUp);
+ if (!htmlTarget.closest('*.lm_content') && (htmlTarget.closest('*.lm_tab') || htmlTarget.closest('*.lm_stack'))) {
+ const className = typeof htmlTarget.className === 'string' ? htmlTarget.className : '';
+ if (!className.includes('lm_close') && !className.includes('lm_maximise')) {
+ this._flush = UndoManager.StartBatch('golden layout edit');
}
}
}
- if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) &&
- ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.ActiveTool)) {
+ if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.ActiveTool)) {
e.stopPropagation();
}
- }
+ };
public CaptureThumbnail() {
const content = this.props.DocumentView?.()?.ContentDiv;
if (content) {
- const _width = Number(getComputedStyle(content).width.replace("px",""));
- const _height = Number(getComputedStyle(content).height.replace("px",""));
- return CollectionFreeFormView.UpdateIcon(
- this.layoutDoc[Id] + "-icon" + (new Date()).getTime(),
- content,
- _width, _height,
- _width, _height, 0, 1, true, this.layoutDoc[Id] + "-icon",
- (iconFile, _nativeWidth, _nativeHeight) => {
- const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title+"-icon", _width, _height, _nativeWidth, _nativeHeight});
- const proto = Cast(img.proto, Doc, null)!;
- proto["data-nativeWidth"] = _width;
- proto["data-nativeHeight"] = _height;
- this.dataDoc.thumb = img;
- });
+ const _width = Number(getComputedStyle(content).width.replace('px', ''));
+ const _height = Number(getComputedStyle(content).height.replace('px', ''));
+ return CollectionFreeFormView.UpdateIcon(this.layoutDoc[Id] + '-icon' + new Date().getTime(), content, _width, _height, _width, _height, 0, 1, true, this.layoutDoc[Id] + '-icon', (iconFile, _nativeWidth, _nativeHeight) => {
+ const img = Docs.Create.ImageDocument(new ImageField(iconFile), { title: this.rootDoc.title + '-icon', _width, _height, _nativeWidth, _nativeHeight });
+ const proto = Cast(img.proto, Doc, null)!;
+ proto['data-nativeWidth'] = _width;
+ proto['data-nativeHeight'] = _height;
+ this.dataDoc.thumb = img;
+ });
}
-
}
- public static async TakeSnapshot(doc: Doc|undefined, clone = false) {
+ public static async TakeSnapshot(doc: Doc | undefined, clone = false) {
if (!doc) return undefined;
let json = StrCast(doc.dockingConfig);
if (clone) {
const cloned = await Doc.MakeClone(doc);
- Array.from(cloned.map.entries()).map(entry => json = json.replace(entry[0], entry[1][Id]));
+ Array.from(cloned.map.entries()).map(entry => (json = json.replace(entry[0], entry[1][Id])));
Doc.GetProto(cloned.clone).dockingConfig = json;
return CurrentUserUtils.openDashboard(cloned.clone);
}
const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const origtabids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", "")) || [];
- const origtabs = origtabids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
+ const origtabids = matches?.map(m => m.replace('"documentId":"', '').replace('"', '')) || [];
+ const origtabs = origtabids
+ .map(id => DocServer.GetCachedRefField(id))
+ .filter(f => f)
+ .map(f => f as Doc);
const newtabs = origtabs.map(origtab => {
const origtabdocs = DocListCast(origtab.data);
const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeAlias(origtab);
const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeAlias(origtabdoc));
if (newtabdocs.length) {
Doc.GetProto(newtab).data = new List<Doc>(newtabdocs);
- newtabdocs.forEach(ntab => ntab.context = newtab);
+ newtabdocs.forEach(ntab => (ntab.context = newtab));
}
json = json.replace(origtab[Id], newtab[Id]);
return newtab;
@@ -426,22 +432,27 @@ export class CollectionDockingView extends CollectionSubView() {
this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
const json = JSON.stringify(this._goldenLayout.toConfig());
const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
- const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", ""));
- const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
+ const docids = matches?.map(m => m.replace('"documentId":"', '').replace('"', ''));
+ const docs = !docids
+ ? []
+ : docids
+ .map(id => DocServer.GetCachedRefField(id))
+ .filter(f => f)
+ .map(f => f as Doc);
const changesMade = this.props.Document.dockcingConfig !== json;
if (changesMade && !this._flush) {
UndoManager.RunInBatch(() => {
this.props.Document.dockingConfig = json;
this.props.Document.data = new List<Doc>(docs);
- }, "state changed");
+ }, 'state changed');
}
return changesMade;
- }
+ };
tabDestroyed = (tab: any) => {
- if(tab.DashDoc?.type !== DocumentType.KVP) {
- Doc.AddDocToList(CurrentUserUtils.MyHeaderBar, "data", tab.DashDoc);
- Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true);
+ if (tab.DashDoc?.type !== DocumentType.KVP) {
+ Doc.AddDocToList(CurrentUserUtils.MyHeaderBar, 'data', tab.DashDoc);
+ Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, 'data', tab.DashDoc, undefined, true, true);
}
const dview = CollectionDockingView.Instance.props.Document;
const fieldKey = CollectionDockingView.Instance.props.fieldKey;
@@ -450,63 +461,95 @@ export class CollectionDockingView extends CollectionSubView() {
tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
this.stateChanged();
- }
+ };
tabCreated = (tab: any) => {
this.tabMap.add(tab);
- tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
- }
+ tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
+ };
stackCreated = (stack: any) => {
stack.header?.element.on('mousedown', (e: any) => {
const dashboard = CurrentUserUtils.ActiveDashboard;
if (dashboard && e.target === stack.header?.element[0] && e.button === 2) {
- dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1;
+ dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
const docToAdd = Docs.Create.FreeformDocument([], {
- _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _backgroundGridShow: true, _fitWidth: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`,
+ _width: this.props.PanelWidth(),
+ _height: this.props.PanelHeight(),
+ _backgroundGridShow: true,
+ _fitWidth: true,
+ title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
});
this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
- CollectionDockingView.AddSplit(docToAdd, "", stack);
+ CollectionDockingView.AddSplit(docToAdd, '', stack);
}
});
- stack.header?.controlsContainer.find('.lm_close') //get the close icon
+ stack.header?.controlsContainer
+ .find('.lm_close') //get the close icon
.off('click') //unbind the current click handler
- .click(action(() => {
- //if (confirm('really close this?')) {
- if (!stack.parent.parent.isRoot || stack.parent.contentItems.length > 1) {
- stack.remove();
- } else {
- alert('cant delete the last stack');
- }
- }));
+ .click(
+ action(() => {
+ //if (confirm('really close this?')) {
+ if (!stack.parent.parent.isRoot || stack.parent.contentItems.length > 1) {
+ stack.remove();
+ } else {
+ alert('cant delete the last stack');
+ }
+ })
+ );
- stack.header?.controlsContainer.find('.lm_maximise') //get the close icon
+ stack.header?.controlsContainer
+ .find('.lm_maximise') //get the close icon
.click(() => setTimeout(this.stateChanged));
- stack.header?.controlsContainer.find('.lm_popout') //get the popout icon
+ stack.header?.controlsContainer
+ .find('.lm_popout') //get the popout icon
.off('click') //unbind the current click handler
- .click(action(() => {
- // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size
- const dashboard = CurrentUserUtils.ActiveDashboard;
- if (dashboard) {
- dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1;
- const docToAdd = Docs.Create.FreeformDocument([], {
- _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, _backgroundGridShow: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`
- });
- this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
- CollectionDockingView.AddSplit(docToAdd, "", stack);
- }
- }));
- }
+ .click(
+ action(() => {
+ // stack.config.fixed = !stack.config.fixed; // force the stack to have a fixed size
+ const dashboard = CurrentUserUtils.ActiveDashboard;
+ if (dashboard) {
+ dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
+ const docToAdd = Docs.Create.FreeformDocument([], {
+ _width: this.props.PanelWidth(),
+ _height: this.props.PanelHeight(),
+ _fitWidth: true,
+ _backgroundGridShow: true,
+ title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
+ });
+ this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
+ CollectionDockingView.AddSplit(docToAdd, '', stack);
+ }
+ })
+ );
+ };
render() {
return <div className="collectiondockingview-container" onPointerDown={this.onPointerDown} ref={this._containerRef} />;
}
}
-ScriptingGlobals.add(function openInLightbox(doc: any) { LightboxView.AddDocTab(doc, "lightbox"); },
- "opens up document in a lightbox", "(doc: any)");
-ScriptingGlobals.add(function openOnRight(doc: any) { return CollectionDockingView.AddSplit(doc, "right"); },
- "opens up document in tab on right side of the screen", "(doc: any)");
-ScriptingGlobals.add(function openInOverlay(doc: any) { return Doc.AddDocToList(CurrentUserUtils.MyOverlayDocs, undefined, doc); },
- "opens up document in screen overlay layer", "(doc: any)");
-ScriptingGlobals.add(function useRightSplit(doc: any, shiftKey?: boolean) { CollectionDockingView.ReplaceTab(doc, "right", undefined, shiftKey); }); \ No newline at end of file
+ScriptingGlobals.add(
+ function openInLightbox(doc: any) {
+ LightboxView.AddDocTab(doc, 'lightbox');
+ },
+ 'opens up document in a lightbox',
+ '(doc: any)'
+);
+ScriptingGlobals.add(
+ function openOnRight(doc: any) {
+ return CollectionDockingView.AddSplit(doc, 'right');
+ },
+ 'opens up document in tab on right side of the screen',
+ '(doc: any)'
+);
+ScriptingGlobals.add(
+ function openInOverlay(doc: any) {
+ return Doc.AddDocToList(CurrentUserUtils.MyOverlayDocs, undefined, doc);
+ },
+ 'opens up document in screen overlay layer',
+ '(doc: any)'
+);
+ScriptingGlobals.add(function useRightSplit(doc: any, shiftKey?: boolean) {
+ CollectionDockingView.ReplaceTab(doc, 'right', undefined, shiftKey);
+});
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 62d07b0e4..c0a61c90f 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -1,43 +1,41 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
-import 'golden-layout/src/css/goldenlayout-base.css';
-import 'golden-layout/src/css/goldenlayout-dark-theme.css';
import { clamp } from 'lodash';
-import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
-import { observer } from "mobx-react";
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { observer } from 'mobx-react';
import * as ReactDOM from 'react-dom';
-import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
-import { FieldId } from "../../../fields/RefField";
-import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from "../../../Utils";
-import { DocServer } from "../../DocServer";
+import { FieldId } from '../../../fields/RefField';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types';
+import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils';
+import { DocServer } from '../../DocServer';
import { DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { DocumentManager } from '../../util/DocumentManager';
-import { DragManager, dropActionType } from "../../util/DragManager";
+import { DragManager, dropActionType } from '../../util/DragManager';
import { SelectionManager } from '../../util/SelectionManager';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
-import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from '../../util/UndoManager';
import { Colors, Shadows } from '../global/globalEnums';
import { LightboxView } from '../LightboxView';
import { MainView } from '../MainView';
-import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
+import { DocFocusOptions, DocumentView, DocumentViewProps } from '../nodes/DocumentView';
import { DashFieldView } from '../nodes/formattedText/DashFieldView';
import { PinProps, PresBox, PresMovement } from '../nodes/trails';
import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
import { CollectionDockingView } from './CollectionDockingView';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import { CollectionView, CollectionViewType } from './CollectionView';
-import "./TabDocView.scss";
-import React = require("react");
+import './TabDocView.scss';
+import React = require('react');
import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
-const _global = (window /* browser */ || global /* node */) as any;
+const _global = (window /* browser */ || global) /* node */ as any;
interface TabDocViewProps {
documentId: FieldId;
@@ -54,9 +52,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
@observable _document: Doc | undefined;
@observable _view: DocumentView | undefined;
- @computed get layoutDoc() { return this._document && Doc.Layout(this._document); }
- @computed get tabColor() { return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor))); }
- @computed get tabTextColor() { return this._document?.type === DocumentType.PRES ? "black" : StrCast(this._document?._color, StrCast(this._document?.color, DefaultStyleProvider(this._document, undefined, StyleProp.Color))); }
+ @computed get layoutDoc() {
+ return this._document && Doc.Layout(this._document);
+ }
+ @computed get tabColor() {
+ return StrCast(this._document?._backgroundColor, StrCast(this._document?.backgroundColor, DefaultStyleProvider(this._document, undefined, StyleProp.BackgroundColor)));
+ }
+ @computed get tabTextColor() {
+ return this._document?.type === DocumentType.PRES ? 'black' : StrCast(this._document?._color, StrCast(this._document?.color, DefaultStyleProvider(this._document, undefined, StyleProp.Color)));
+ }
// @computed get renderBounds() {
// const bounds = this._document ? Cast(this._document._renderContentBounds, listSpec("number"), [0, 0, this.returnMiniSize(), this.returnMiniSize()]) : [0, 0, 0, 0];
// const xbounds = bounds[2] - bounds[0];
@@ -65,74 +69,91 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// return { l: bounds[0] + xbounds / 2 - dim / 2, t: bounds[1] + ybounds / 2 - dim / 2, cx: bounds[0] + xbounds / 2, cy: bounds[1] + ybounds / 2, dim };
// }
- get stack() { return (this.props as any).glContainer.parent.parent; }
- get tab() { return (this.props as any).glContainer.tab; }
- get view() { return this._view; }
+ get stack() {
+ return (this.props as any).glContainer.parent.parent;
+ }
+ get tab() {
+ return (this.props as any).glContainer.tab;
+ }
+ get view() {
+ return this._view;
+ }
_lastTab: any;
_lastView: DocumentView | undefined;
@action
init = (tab: any, doc: Opt<Doc>) => {
if (tab.contentItem === tab.header.parent.getActiveContentItem()) this._activated = true;
- if (tab.DashDoc !== doc && doc && tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
+ if (tab.DashDoc !== doc && doc && tab.hasOwnProperty('contentItem') && tab.contentItem.config.type !== 'stack') {
tab._disposers = {} as { [name: string]: IReactionDisposer };
tab.contentItem.config.fixed && (tab.contentItem.parent.config.fixed = true);
tab.DashDoc = doc;
const iconType: IconProp = Doc.toIcon(doc);
// setup the title element and set its size according to the # of chars in the title. Show the full title when clicked.
const titleEle = tab.titleElement[0];
- const iconWrap = document.createElement("div");
- const closeWrap = document.createElement("div");
+ const iconWrap = document.createElement('div');
+ const closeWrap = document.createElement('div');
titleEle.size = StrCast(doc.title).length + 3;
titleEle.value = doc.title;
titleEle.onkeydown = (e: KeyboardEvent) => {
e.stopPropagation();
};
- titleEle.onchange = undoBatch(action((e: any) => {
- titleEle.size = e.currentTarget.value.length + 3;
- Doc.GetProto(doc).title = e.currentTarget.value;
- }));
+ titleEle.onchange = undoBatch(
+ action((e: any) => {
+ titleEle.size = e.currentTarget.value.length + 3;
+ Doc.GetProto(doc).title = e.currentTarget.value;
+ })
+ );
if (tab.element[0].children[1].children.length === 1) {
- iconWrap.className = "lm_iconWrap lm_moreInfo";
+ iconWrap.className = 'lm_iconWrap lm_moreInfo';
const dragBtnDown = (e: React.PointerEvent) => {
- setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, action(e => {
- if (this.view) {
- SelectionManager.SelectView(this.view, false);
- let child = this.view.ContentDiv!.children[0];
- while (child.children.length) {
- const next = Array.from(child.children).find(c => c.className?.toString().includes("SVGAnimatedString") || typeof (c.className) === "string");
- if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
- if (next?.className?.toString().includes(DashFieldView.name)) break;
- if (next) child = next;
- else break;
+ setupMoveUpEvents(
+ this,
+ e,
+ e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY),
+ returnFalse,
+ action(e => {
+ if (this.view) {
+ SelectionManager.SelectView(this.view, false);
+ let child = this.view.ContentDiv!.children[0];
+ while (child.children.length) {
+ const next = Array.from(child.children).find(c => c.className?.toString().includes('SVGAnimatedString') || typeof c.className === 'string');
+ if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
+ if (next?.className?.toString().includes(DashFieldView.name)) break;
+ if (next) child = next;
+ else break;
+ }
+ simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+ } else {
+ this._activated = true;
+ setTimeout(() => this.view && SelectionManager.SelectView(this.view, false));
}
- simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
- }
- else { this._activated = true;
- setTimeout(() =>this.view && SelectionManager.SelectView(this.view, false));
- }
- }));
+ })
+ );
};
-
+
const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />;
- const closeIcon = <FontAwesomeIcon icon={"eye"} />;
+ const closeIcon = <FontAwesomeIcon icon={'eye'} />;
ReactDOM.render(docIcon, iconWrap);
ReactDOM.render(closeIcon, closeWrap);
tab.reactComponents = [iconWrap, closeWrap];
tab.element[0].prepend(iconWrap);
- tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
+ tab._disposers.layerDisposer = reaction(
+ () => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
({ layer, color }) => {
// console.log("TabDocView: " + this.tabColor);
// console.log("lightOrDark: " + lightOrDark(this.tabColor));
const textColor = lightOrDark(this.tabColor); //not working with StyleProp.Color
titleEle.style.color = textColor;
- titleEle.style.backgroundColor = "transparent";
+ titleEle.style.backgroundColor = 'transparent';
iconWrap.style.color = textColor;
closeWrap.style.color = textColor;
- tab.element[0].style.background = !layer ? color : "dimgrey";
- }, { fireImmediately: true });
+ tab.element[0].style.background = !layer ? color : 'dimgrey';
+ },
+ { fireImmediately: true }
+ );
}
// shifts the focus to this tab when another tab is dragged over it
tab.element[0].onmouseenter = (e: MouseEvent) => {
@@ -142,157 +163,167 @@ export class TabDocView extends React.Component<TabDocViewProps> {
}
};
-
// select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected
titleEle.onpointerdown = action((e: any) => {
- if (e.target.className !== "lm_iconWrap") {
+ if (e.target.className !== 'lm_iconWrap') {
if (this.view) SelectionManager.SelectView(this.view, false);
else this._activated = true;
if (Date.now() - titleEle.lastClick < 1000) titleEle.select();
titleEle.lastClick = Date.now();
- (document.activeElement !== titleEle) && titleEle.focus();
+ document.activeElement !== titleEle && titleEle.focus();
}
});
- tab._disposers.selectionDisposer = reaction(() => SelectionManager.Views().some(v => v.topMost && v.props.Document === doc),
- action((selected) => {
+ tab._disposers.selectionDisposer = reaction(
+ () => SelectionManager.Views().some(v => v.topMost && v.props.Document === doc),
+ action(selected => {
if (selected) this._activated = true;
const toggle = tab.element[0].children[1].children[0] as HTMLInputElement;
- selected && tab.contentItem !== tab.header.parent.getActiveContentItem() &&
- UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), "tab switch");
+ selected && tab.contentItem !== tab.header.parent.getActiveContentItem() && UndoManager.RunInBatch(() => tab.header.parent.setActiveContentItem(tab.contentItem), 'tab switch');
// toggle.style.fontWeight = selected ? "bold" : "";
// toggle.style.textTransform = selected ? "uppercase" : "";
- }));
-
+ })
+ );
// highlight the tab when the tab document is brushed in any part of the UI
- tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
- //titleEle.value = title;
- // titleEle.style.padding = degree ? 0 : 2;
- // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
- }, { fireImmediately: true });
+ tab._disposers.reactionDisposer = reaction(
+ () => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }),
+ ({ title, degree }) => {
+ //titleEle.value = title;
+ // titleEle.style.padding = degree ? 0 : 2;
+ // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
+ },
+ { fireImmediately: true }
+ );
// clean up the tab when it is closed
- tab.closeElement.off('click') //unbind the current click handler
+ tab.closeElement
+ .off('click') //unbind the current click handler
.click(function () {
Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
SelectionManager.DeselectAll();
- UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
+ UndoManager.RunInBatch(() => tab.contentItem.remove(), 'delete tab');
});
}
- }
+ };
/**
* Adds a document to the presentation view
**/
@action
- public static PinDoc(docs: Doc|Doc[], pinProps?: PinProps) {
- const docList = ((docs instanceof Doc) ? [docs]: docs);
- const batch = UndoManager.StartBatch("pinning doc");
+ public static PinDoc(docs: Doc | Doc[], pinProps?: PinProps) {
+ const docList = docs instanceof Doc ? [docs] : docs;
+ const batch = UndoManager.StartBatch('pinning doc');
// all docs will be added to the ActivePresentation as stored on CurrentUserUtils
const curPres = CurrentUserUtils.ActivePresentation;
- curPres && docList.forEach(doc => {
- // Edge Case 1: Cannot pin document to itself
- if (doc === curPres) { alert("Cannot pin presentation document to itself"); return; }
- const pinDoc = Doc.MakeAlias(doc);
- pinDoc.presentationTargetDoc = doc;
- pinDoc.title = doc.title + " - Slide";
- pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children. the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
- pinDoc.presMovement = PresMovement.Zoom;
- pinDoc.groupWithUp = false;
- pinDoc.context = curPres;
- // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
- pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
- pinDoc.treeViewHeaderWidth = "100%"; // forces the header to grow to be the same size as its largest sibling.
- pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
- pinDoc.treeViewFieldKey = "data"; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
- pinDoc.treeViewExpandedView = "data";// in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
- pinDoc.treeViewGrowsHorizontally = true;// the document expands horizontally when displayed as a tree view header
- pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
- const presArray: Doc[] = PresBox.Instance?.sortArray();
- const size: number = PresBox.Instance?._selectedArray.size;
- const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
- const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
- // If pinWithView option set then update scale and x / y props of slide
- if (pinProps?.pinWithView) {
- const viewProps = pinProps.pinWithView;
- pinDoc.presPinView = true;
- pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
- pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
- pinDoc.presPinViewScale = viewProps.scale;
- pinDoc.contentBounds = new List<number>([viewProps.bounds.left, viewProps.bounds.top, viewProps.bounds.left+viewProps.bounds.width, viewProps.bounds.top+viewProps.bounds.height]);
- }
- if (pinProps?.pinDocView) {
- const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(pinDoc.type as any) || pinDoc._viewType === CollectionViewType.Stacking;
- const pannable: boolean = ((pinDoc.type === DocumentType.COL && doc._viewType === CollectionViewType.Freeform) || doc.type === DocumentType.IMG);
- if (scrollable) {
- const scroll = doc._scrollTop;
- pinDoc.presPinView = true;
- pinDoc.presPinViewScroll = scroll;
- } else if ([DocumentType.AUDIO, DocumentType.VID].includes(doc.type as any)) {
- pinDoc.presPinView = true;
- pinDoc.presStartTime = doc._currentTimecode;
- pinDoc.presEndTime = NumCast(doc._currentTimecode) + 0.1;
- } else if (pannable) {
+ curPres &&
+ docList.forEach(doc => {
+ // Edge Case 1: Cannot pin document to itself
+ if (doc === curPres) {
+ alert('Cannot pin presentation document to itself');
+ return;
+ }
+ const pinDoc = Doc.MakeAlias(doc);
+ pinDoc.presentationTargetDoc = doc;
+ pinDoc.title = doc.title + ' - Slide';
+ pinDoc.data = new List<Doc>(); // the children of the alias' layout are the presentation slide children. the alias' data field might be children of a collection, PDF data, etc -- in any case we don't want the tree view to "see" this data
+ pinDoc.presMovement = PresMovement.Zoom;
+ pinDoc.groupWithUp = false;
+ pinDoc.context = curPres;
+ // these should potentially all be props passed down by the CollectionTreeView to the TreeView elements. That way the PresBox could configure all of its children at render time
+ pinDoc.treeViewRenderAsBulletHeader = true; // forces a tree view to render the document next to the bullet in the header area
+ pinDoc.treeViewHeaderWidth = '100%'; // forces the header to grow to be the same size as its largest sibling.
+ pinDoc.treeViewChildrenOnRoot = true; // tree view will look for hierarchical children on the root doc, not the data doc.
+ pinDoc.treeViewFieldKey = 'data'; // tree view will treat the 'data' field as the field where the hierarchical children are located instead of using the document's layout string field
+ pinDoc.treeViewExpandedView = 'data'; // in case the data doc has an expandedView set, this will mask that field and use the 'data' field when expanding the tree view
+ pinDoc.treeViewGrowsHorizontally = true; // the document expands horizontally when displayed as a tree view header
+ pinDoc.treeViewHideHeaderIfTemplate = true; // this will force the document to render itself as the tree view header
+ const presArray: Doc[] = PresBox.Instance?.sortArray();
+ const size: number = PresBox.Instance?._selectedArray.size;
+ const presSelected: Doc | undefined = presArray && size ? presArray[size - 1] : undefined;
+ const duration = NumCast(doc[`${Doc.LayoutFieldKey(pinDoc)}-duration`], null);
+ // If pinWithView option set then update scale and x / y props of slide
+ if (pinProps?.pinWithView) {
+ const viewProps = pinProps.pinWithView;
pinDoc.presPinView = true;
- pinDoc.presPinViewX = pinDoc._panX;
- pinDoc.presPinViewY = pinDoc._panY;
- pinDoc.presPinViewScale = pinDoc._viewScale;
- const pw = NumCast(pinProps.panelWidth);
- const ph = NumCast(pinProps.panelHeight);
- const ps = NumCast(pinDoc._viewScale);
- if (pw && ph && ps) {
- pinDoc.contentBounds = new List<number>([
- NumCast(pinDoc.panX)-pw/2/ps,
- NumCast(pinDoc.panY)-ph/2/ps,
- NumCast(pinDoc.panX)+pw/2/ps,
- NumCast(pinDoc.panY)+ph/2/ps]);
+ pinDoc.presPinViewX = viewProps.bounds.left + viewProps.bounds.width / 2;
+ pinDoc.presPinViewY = viewProps.bounds.top + viewProps.bounds.height / 2;
+ pinDoc.presPinViewScale = viewProps.scale;
+ pinDoc.contentBounds = new List<number>([viewProps.bounds.left, viewProps.bounds.top, viewProps.bounds.left + viewProps.bounds.width, viewProps.bounds.top + viewProps.bounds.height]);
+ }
+ if (pinProps?.pinDocView) {
+ const scrollable = [DocumentType.PDF, DocumentType.RTF, DocumentType.WEB].includes(pinDoc.type as any) || pinDoc._viewType === CollectionViewType.Stacking;
+ const pannable: boolean = (pinDoc.type === DocumentType.COL && doc._viewType === CollectionViewType.Freeform) || doc.type === DocumentType.IMG;
+ if (scrollable) {
+ const scroll = doc._scrollTop;
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewScroll = scroll;
+ } else if ([DocumentType.AUDIO, DocumentType.VID].includes(doc.type as any)) {
+ pinDoc.presPinView = true;
+ pinDoc.presStartTime = doc._currentTimecode;
+ pinDoc.presEndTime = NumCast(doc._currentTimecode) + 0.1;
+ } else if (pannable) {
+ pinDoc.presPinView = true;
+ pinDoc.presPinViewX = pinDoc._panX;
+ pinDoc.presPinViewY = pinDoc._panY;
+ pinDoc.presPinViewScale = pinDoc._viewScale;
+ const pw = NumCast(pinProps.panelWidth);
+ const ph = NumCast(pinProps.panelHeight);
+ const ps = NumCast(pinDoc._viewScale);
+ if (pw && ph && ps) {
+ pinDoc.contentBounds = new List<number>([NumCast(pinDoc.panX) - pw / 2 / ps, NumCast(pinDoc.panY) - ph / 2 / ps, NumCast(pinDoc.panX) + pw / 2 / ps, NumCast(pinDoc.panY) + ph / 2 / ps]);
+ }
+ } else if (doc.type === DocumentType.COMPARISON) {
+ const width = doc._clipWidth;
+ pinDoc.presPinClipWidth = width;
+ pinDoc.presPinView = true;
}
- } else if (doc.type === DocumentType.COMPARISON) {
- const width = doc._clipWidth;
- pinDoc.presPinClipWidth = width;
- pinDoc.presPinView = true;
}
- }
- pinDoc.onClick = ScriptField.MakeFunction("navigateToDoc(self.presentationTargetDoc, self)");
- Doc.AddDocToList(curPres, "data", pinDoc, presSelected);
- if (!pinProps?.audioRange && duration !== undefined) {
- pinDoc.mediaStart = "manual";
- pinDoc.mediaStop = "manual";
- pinDoc.presStartTime = NumCast(doc.clipStart);
- pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
- }
- //save position
- if (pinProps?.setPosition || pinDoc.isInkMask) {
- pinDoc.setPosition = true;
- pinDoc.y = doc.y;
- pinDoc.x = doc.x;
- pinDoc.presHideAfter = true;
- pinDoc.presHideBefore = true;
- pinDoc.title = doc.title + " (move)";
- pinDoc.presMovement = PresMovement.None;
- }
- if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
- PresBox.Instance?._selectedArray.clear();
- pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
- });
- if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+ pinDoc.onClick = ScriptField.MakeFunction('navigateToDoc(self.presentationTargetDoc, self)');
+ Doc.AddDocToList(curPres, 'data', pinDoc, presSelected);
+ if (!pinProps?.audioRange && duration !== undefined) {
+ pinDoc.mediaStart = 'manual';
+ pinDoc.mediaStop = 'manual';
+ pinDoc.presStartTime = NumCast(doc.clipStart);
+ pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
+ }
+ //save position
+ if (pinProps?.setPosition || pinDoc.isInkMask) {
+ pinDoc.setPosition = true;
+ pinDoc.y = doc.y;
+ pinDoc.x = doc.x;
+ pinDoc.presHideAfter = true;
+ pinDoc.presHideBefore = true;
+ pinDoc.title = doc.title + ' (move)';
+ pinDoc.presMovement = PresMovement.None;
+ }
+ if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
+ PresBox.Instance?._selectedArray.clear();
+ pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
+ });
+ if (
+ !Array.from(CollectionDockingView.Instance.tabMap)
+ .map(d => d.DashDoc)
+ .includes(curPres)
+ ) {
const docs = Cast(CurrentUserUtils.MyOverlayDocs.data, listSpec(Doc), []);
if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
- CollectionDockingView.AddSplit(curPres, "right");
+ CollectionDockingView.AddSplit(curPres, 'right');
setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
}
setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
}
componentDidMount() {
- new _global.ResizeObserver(action((entries: any) => {
- for (const entry of entries) {
- this._panelWidth = entry.contentRect.width;
- this._panelHeight = entry.contentRect.height;
- }
- })).observe(this.props.glContainer._element[0]);
- this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
+ new _global.ResizeObserver(
+ action((entries: any) => {
+ for (const entry of entries) {
+ this._panelWidth = entry.contentRect.width;
+ this._panelHeight = entry.contentRect.height;
+ }
+ })
+ ).observe(this.props.glContainer._element[0]);
+ this.props.glContainer.layoutManager.on('activeContentItemChanged', this.onActiveContentItemChanged);
this.props.glContainer.tab?.isActive && this.onActiveContentItemChanged(undefined);
// this._tabReaction = reaction(() => ({ selected: this.active(), title: this.tab?.titleElement[0] }),
// ({ selected, title }) => title && (title.style.backgroundColor = selected ? "white" : ""),
@@ -306,7 +337,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
this._tabReaction?.();
this._view && DocumentManager.Instance.RemoveView(this._view);
- this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
+ this.props.glContainer.layoutManager.off('activeContentItemChanged', this.onActiveContentItemChanged);
}
@action.bound
@@ -326,25 +357,31 @@ export class TabDocView extends React.Component<TabDocViewProps> {
// inPlace - will add the document to any collection along the path from the document to the docking view that has a field isInPlaceContainer. if none is found, inPlace adds a tab to current stack
addDocTab = (doc: Doc, location: string) => {
SelectionManager.DeselectAll();
- const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":");
- const locationParams = locationFields.length > 1 ? locationFields[1] : "";
+ const locationFields = doc._viewType === CollectionViewType.Docking ? ['dashboard'] : location.split(':');
+ const locationParams = locationFields.length > 1 ? locationFields[1] : '';
switch (locationFields[0]) {
- case "dashboard": return CurrentUserUtils.openDashboard(doc);
- case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
- case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
- case "replace": return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
+ case 'dashboard':
+ return CurrentUserUtils.openDashboard(doc);
+ case 'close':
+ return CollectionDockingView.CloseSplit(doc, locationParams);
+ case 'fullScreen':
+ return CollectionDockingView.OpenFullScreen(doc);
+ case 'replace':
+ return CollectionDockingView.ReplaceTab(doc, locationParams, this.stack);
// case "lightbox": {
// // TabDocView.PinDoc(doc, { hidePresBox: true });
// return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
// }
- case "lightbox": return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
- case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
- case "inPlace":
- case "add":
+ case 'lightbox':
+ return LightboxView.AddDocTab(doc, location, undefined, this.addDocTab);
+ case 'toggle':
+ return CollectionDockingView.ToggleSplit(doc, locationParams, this.stack);
+ case 'inPlace':
+ case 'add':
default:
return CollectionDockingView.AddSplit(doc, locationParams, this.stack);
}
- }
+ };
remDocTab = (doc: Doc | Doc[]) => {
if (doc === this._document) {
SelectionManager.DeselectAll();
@@ -352,11 +389,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
return true;
}
return false;
- }
+ };
getCurrentFrame = () => {
return NumCast(Cast(PresBox.Instance.childDocs[PresBox.Instance.itemIndex].presentationTargetDoc, Doc, null)._currentFrame);
- }
+ };
@action
focusFunc = (doc: Doc, options?: DocFocusOptions) => {
const shrinkwrap = options?.originalTarget === this._document && this.view?.ComponentView?.shrinkWrap;
@@ -364,104 +401,113 @@ export class TabDocView extends React.Component<TabDocViewProps> {
const focusSpeed = 1000;
shrinkwrap();
this._document._viewTransition = `transform ${focusSpeed}ms`;
- setTimeout(action(() => {
- this._document!._viewTransition = undefined;
- options?.afterFocus?.(false);
- }), focusSpeed);
+ setTimeout(
+ action(() => {
+ this._document!._viewTransition = undefined;
+ options?.afterFocus?.(false);
+ }),
+ focusSpeed
+ );
} else {
options?.afterFocus?.(false);
}
if (!this.tab.header.parent._activeContentItem || this.tab.header.parent._activeContentItem !== this.tab.contentItem) {
this.tab.header.parent.setActiveContentItem(this.tab.contentItem); // glr: Panning does not work when this is set - (this line is for trying to make a tab that is not topmost become topmost)
}
- }
+ };
active = () => this._isActive;
@observable _forceInvalidateScreenToLocal = 0;
ScreenToLocalTransform = () => {
this._forceInvalidateScreenToLocal;
const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont?.children?.[0] as HTMLElement);
return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY);
- }
+ };
PanelWidth = () => this._panelWidth;
PanelHeight = () => this._panelHeight;
miniMapColor = () => this.tabColor;
tabView = () => this._view;
- disableMinimap = () => !this._document || (this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform);
+ disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._viewType !== CollectionViewType.Freeform;
hideMinimap = () => this.disableMinimap() || BoolCast(this._document?.hideMinimap);
@computed get docView() {
- return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? (null) :
- <><DocumentView key={this._document[Id]} ref={action((r: DocumentView) => {
- this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
- this._view = r;
- this._lastView = this._view;
- })}
- renderDepth={0}
- Document={this._document}
- DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
- ContainingCollectionView={undefined}
- ContainingCollectionDoc={undefined}
- onBrowseClick={MainView.Instance.exploreMode}
- isContentActive={returnTrue}
- PanelWidth={this.PanelWidth}
- PanelHeight={this.PanelHeight}
- styleProvider={DefaultStyleProvider}
- docFilters={CollectionDockingView.Instance.childDocFilters}
- docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
- searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
- addDocument={undefined}
- removeDocument={this.remDocTab}
- addDocTab={this.addDocTab}
- ScreenToLocalTransform={this.ScreenToLocalTransform}
- dontCenter={"y"}
- rootSelected={returnTrue}
- whenChildContentsActiveChanged={emptyFunction}
- focus={this.focusFunc}
- docViewPath={returnEmptyDoclist}
- bringToFront={emptyFunction}
- pinToPres={TabDocView.PinDoc} />
- <TabMinimapView key="minimap"
- hideMinimap={this.hideMinimap}
- addDocTab={this.addDocTab}
- PanelHeight={this.PanelHeight}
+ return !this._activated || !this._document || this._document._viewType === CollectionViewType.Docking ? null : (
+ <>
+ <DocumentView
+ key={this._document[Id]}
+ ref={action((r: DocumentView) => {
+ this._lastView && DocumentManager.Instance.RemoveView(this._lastView);
+ this._view = r;
+ this._lastView = this._view;
+ })}
+ renderDepth={0}
+ Document={this._document}
+ DataDoc={!Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ onBrowseClick={MainView.Instance.exploreMode}
+ isContentActive={returnTrue}
PanelWidth={this.PanelWidth}
- background={this.miniMapColor}
- document={this._document}
- tabView={this.tabView} />
- <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? "Open minimap" : "Close minimap"}</div>}>
- <div className="miniMap-hidden"
+ PanelHeight={this.PanelHeight}
+ styleProvider={DefaultStyleProvider}
+ docFilters={CollectionDockingView.Instance.childDocFilters}
+ docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
+ searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
+ addDocument={undefined}
+ removeDocument={this.remDocTab}
+ addDocTab={this.addDocTab}
+ ScreenToLocalTransform={this.ScreenToLocalTransform}
+ dontCenter={'y'}
+ rootSelected={returnTrue}
+ whenChildContentsActiveChanged={emptyFunction}
+ focus={this.focusFunc}
+ docViewPath={returnEmptyDoclist}
+ bringToFront={emptyFunction}
+ pinToPres={TabDocView.PinDoc}
+ />
+ <TabMinimapView key="minimap" hideMinimap={this.hideMinimap} addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />
+ <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? 'Open minimap' : 'Close minimap'}</div>}>
+ <div
+ className="miniMap-hidden"
style={{
- display: this.disableMinimap() || this._document._viewType !== "freeform" ? "none" : undefined,
+ display: this.disableMinimap() || this._document._viewType !== 'freeform' ? 'none' : undefined,
color: this._document.hideMinimap ? Colors.BLACK : Colors.WHITE,
backgroundColor: this._document.hideMinimap ? Colors.LIGHT_GRAY : Colors.MEDIUM_BLUE,
- boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined
+ boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined,
}}
onPointerDown={e => e.stopPropagation()}
- onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} >
- <FontAwesomeIcon icon={"globe-asia"} size="lg" />
+ onClick={action(e => {
+ e.stopPropagation();
+ this._document!.hideMinimap = !this._document!.hideMinimap;
+ })}>
+ <FontAwesomeIcon icon={'globe-asia'} size="lg" />
</div>
</Tooltip>
- </>;
+ </>
+ );
}
render() {
return (
- <div className="collectionDockingView-content" style={{
- fontFamily: Doc.UserDoc().renderStyle === "comic" ? "Comic Sans MS" : undefined,
- height: "100%", width: "100%"
- }} ref={ref => {
- if (this._mainCont = ref) {
- if (this._lastTab) {
- this._view && DocumentManager.Instance.RemoveView(this._view);
+ <div
+ className="collectionDockingView-content"
+ style={{
+ fontFamily: Doc.UserDoc().renderStyle === 'comic' ? 'Comic Sans MS' : undefined,
+ height: '100%',
+ width: '100%',
+ }}
+ ref={ref => {
+ if ((this._mainCont = ref)) {
+ if (this._lastTab) {
+ this._view && DocumentManager.Instance.RemoveView(this._view);
+ }
+ this._lastTab = this.tab;
+ (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
+ DocServer.GetRefField(this.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
+ new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
}
- this._lastTab = this.tab;
- (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
- DocServer.GetRefField(this.props.documentId).then(action(doc => doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document)));
- new _global.ResizeObserver(action((entries: any) => this._forceInvalidateScreenToLocal++)).observe(ref);
- }
- }} >
+ }}>
{this.docView}
- </div >
+ </div>
);
}
}
@@ -479,29 +525,38 @@ interface TabMinimapViewProps {
export class TabMinimapView extends React.Component<TabMinimapViewProps> {
static miniStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
if (doc) {
- switch (property.split(":")[0]) {
- default: return DefaultStyleProvider(doc, props, property);
- case StyleProp.PointerEvents: return "none";
+ switch (property.split(':')[0]) {
+ default:
+ return DefaultStyleProvider(doc, props, property);
+ case StyleProp.PointerEvents:
+ return 'none';
case StyleProp.DocContents:
const background = ((type: DocumentType) => {
switch (type) {
- case DocumentType.PDF: return "pink";
- case DocumentType.AUDIO: return "lightgreen";
- case DocumentType.WEB: return "brown";
- case DocumentType.IMG: return "blue";
- case DocumentType.MAP: return "orange";
- case DocumentType.VID: return "purple";
- case DocumentType.RTF: return "yellow";
- case DocumentType.COL: return undefined;
- default: return "gray";
+ case DocumentType.PDF:
+ return 'pink';
+ case DocumentType.AUDIO:
+ return 'lightgreen';
+ case DocumentType.WEB:
+ return 'brown';
+ case DocumentType.IMG:
+ return 'blue';
+ case DocumentType.MAP:
+ return 'orange';
+ case DocumentType.VID:
+ return 'purple';
+ case DocumentType.RTF:
+ return 'yellow';
+ case DocumentType.COL:
+ return undefined;
+ default:
+ return 'gray';
}
})(doc.type as DocumentType);
- return !background ?
- undefined :
- <div style={{ width: doc[WidthSym](), height: doc[HeightSym](), position: "absolute", display: "block", background }} />;
+ return !background ? undefined : <div style={{ width: doc[WidthSym](), height: doc[HeightSym](), position: 'absolute', display: 'block', background }} />;
}
}
- }
+ };
@computed get renderBounds() {
const compView = this.props.tabView()?.ComponentView as CollectionFreeFormView;
const bounds = compView?.freeformData?.(true)?.bounds;
@@ -517,20 +572,27 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
const doc = this.props.document;
const renderBounds = this.renderBounds ?? { l: 0, r: 0, t: 0, b: 0, dim: 1 };
const miniSize = this.returnMiniSize();
- doc && setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
- doc._panX = clamp(NumCast(doc._panX) + delta[0] / miniSize * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
- doc._panY = clamp(NumCast(doc._panY) + delta[1] / miniSize * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
- return false;
- }), emptyFunction, emptyFunction);
- }
+ doc &&
+ setupMoveUpEvents(
+ this,
+ e,
+ action((e: PointerEvent, down: number[], delta: number[]) => {
+ doc._panX = clamp(NumCast(doc._panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
+ doc._panY = clamp(NumCast(doc._panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
+ return false;
+ }),
+ emptyFunction,
+ emptyFunction
+ );
+ };
render() {
- if (!this.renderBounds) return (null);
- const miniWidth = this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim * 100;
- const miniHeight = this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim * 100;
- const miniLeft = 50 + (NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim * 100 - miniWidth / 2;
- const miniTop = 50 + (NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim * 100 - miniHeight / 2;
+ if (!this.renderBounds) return null;
+ const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100;
+ const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._viewScale, 1) / this.renderBounds.dim) * 100;
+ const miniLeft = 50 + ((NumCast(this.props.document._panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2;
+ const miniTop = 50 + ((NumCast(this.props.document._panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2;
const miniSize = this.returnMiniSize();
- return this.props.hideMinimap() ? (null) :
+ return this.props.hideMinimap() ? null : (
<div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
<CollectionFreeFormView
Document={this.props.document}
@@ -567,9 +629,10 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
fitContentsToBox={returnTrue}
/>
- <div className="miniOverlay" onPointerDown={this.miniDown} >
- <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% `, }} />
+ <div className="miniOverlay" onPointerDown={this.miniDown}>
+ <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% ` }} />
</div>
- </div>;
+ </div>
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index b64e9dac1..19401c7f0 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -1,4 +1,5 @@
-@import "../../global/globalCssVariables.scss";
+@import '../../global/globalCssVariables.scss';
+@import '../../../../../node_modules/react-table/react-table.css';
.collectionSchemaView-container {
border-width: $COLLECTION_BORDER_WIDTH;
border-color: $medium-gray;
@@ -218,8 +219,6 @@
}
}
-
-
.collectionSchemaView-header {
height: 100%;
color: gray;
@@ -289,8 +288,6 @@ button.add-column {
}
}
-
-
.keys-dropdown {
position: relative;
//width: 100%;
@@ -300,13 +297,12 @@ button.add-column {
padding: 3px;
height: 28px;
font-weight: bold;
- letter-spacing: "2px";
- text-transform: "uppercase";
+ letter-spacing: '2px';
+ text-transform: 'uppercase';
&:focus {
font-weight: normal;
}
}
-
}
.columnMenu-colors {
display: flex;
@@ -338,7 +334,6 @@ button.add-column {
margin-right: 5px;
font-size: 10px;
border-radius: 3px;
-
}
.keys-options-wrapper {
@@ -348,7 +343,7 @@ button.add-column {
top: 100%;
z-index: 21;
background-color: #ffffff;
- box-shadow: 0px 3px 4px rgba(0,0,0,30%);
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 30%);
padding: 1px;
.key-option {
cursor: pointer;
@@ -473,8 +468,8 @@ button.add-column {
}
.collectionSchemaView-cellContents-docButton {
float: right;
- width: "15px";
- height: "15px";
+ width: '15px';
+ height: '15px';
}
.collectionSchemaView-dropdownWrapper {
border: grey;
@@ -490,10 +485,10 @@ button.add-column {
display: inline-block;
//float: right;
height: 100%;
- display: "flex";
+ display: 'flex';
font-size: 13;
- justify-content: "center";
- align-items: "center";
+ justify-content: 'center';
+ align-items: 'center';
}
}
.collectionSchemaView-dropdownContainer {
@@ -601,4 +596,4 @@ button.add-column {
font-size: 10.5px;
margin-left: 50px;
margin-top: 10px;
-} \ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 9eba788a9..c4ee1805f 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,30 +1,29 @@
-import React = require("react");
+import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, untracked } from "mobx";
-import { observer } from "mobx-react";
-import Measure from "react-measure";
-import { Resize } from "react-table";
-import "react-table/react-table.css";
-import { Doc, Opt } from "../../../../fields/Doc";
-import { List } from "../../../../fields/List";
-import { listSpec } from "../../../../fields/Schema";
-import { PastelSchemaPalette, SchemaHeaderField } from "../../../../fields/SchemaHeaderField";
-import { Cast, NumCast } from "../../../../fields/Types";
-import { TraceMobx } from "../../../../fields/util";
-import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from "../../../../Utils";
-import { DocUtils } from "../../../documents/Documents";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { SnappingManager } from "../../../util/SnappingManager";
-import { Transform } from "../../../util/Transform";
-import { undoBatch } from "../../../util/UndoManager";
-import { ContextMenu } from "../../ContextMenu";
-import { ContextMenuProps } from "../../ContextMenuItem";
+import { action, computed, observable, untracked } from 'mobx';
+import { observer } from 'mobx-react';
+import Measure from 'react-measure';
+import { Resize } from 'react-table';
+import { Doc, Opt } from '../../../../fields/Doc';
+import { List } from '../../../../fields/List';
+import { listSpec } from '../../../../fields/Schema';
+import { PastelSchemaPalette, SchemaHeaderField } from '../../../../fields/SchemaHeaderField';
+import { Cast, NumCast } from '../../../../fields/Types';
+import { TraceMobx } from '../../../../fields/util';
+import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
+import { DocUtils } from '../../../documents/Documents';
+import { SelectionManager } from '../../../util/SelectionManager';
+import { SnappingManager } from '../../../util/SnappingManager';
+import { Transform } from '../../../util/Transform';
+import { undoBatch } from '../../../util/UndoManager';
+import { ContextMenu } from '../../ContextMenu';
+import { ContextMenuProps } from '../../ContextMenuItem';
import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss';
-import { DocumentView } from "../../nodes/DocumentView";
-import { DefaultStyleProvider } from "../../StyleProvider";
-import { CollectionSubView } from "../CollectionSubView";
-import "./CollectionSchemaView.scss";
-import { SchemaTable } from "./SchemaTable";
+import { DocumentView } from '../../nodes/DocumentView';
+import { DefaultStyleProvider } from '../../StyleProvider';
+import { CollectionSubView } from '../CollectionSubView';
+import './CollectionSchemaView.scss';
+import { SchemaTable } from './SchemaTable';
// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
export enum ColumnType {
@@ -35,14 +34,21 @@ export enum ColumnType {
Doc,
Image,
List,
- Date
+ Date,
}
// this map should be used for keys that should have a const type of value
const columnTypes: Map<string, ColumnType> = new Map([
- ["title", ColumnType.String],
- ["x", ColumnType.Number], ["y", ColumnType.Number], ["_width", ColumnType.Number], ["_height", ColumnType.Number],
- ["_nativeWidth", ColumnType.Number], ["_nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean],
- ["_curPage", ColumnType.Number], ["_currentTimecode", ColumnType.Number], ["zIndex", ColumnType.Number]
+ ['title', ColumnType.String],
+ ['x', ColumnType.Number],
+ ['y', ColumnType.Number],
+ ['_width', ColumnType.Number],
+ ['_height', ColumnType.Number],
+ ['_nativeWidth', ColumnType.Number],
+ ['_nativeHeight', ColumnType.Number],
+ ['isPrototype', ColumnType.Boolean],
+ ['_curPage', ColumnType.Number],
+ ['_currentTimecode', ColumnType.Number],
+ ['zIndex', ColumnType.Number],
]);
@observer
@@ -51,7 +57,7 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _previewDoc: Doc | undefined = undefined;
@observable _focusedTable: Doc = this.props.Document;
- @observable _col: any = "";
+ @observable _col: any = '';
@observable _menuWidth = 0;
@observable _headerOpen = false;
@observable _headerIsEditing = false;
@@ -60,19 +66,33 @@ export class CollectionSchemaView extends CollectionSubView() {
@observable _pointerY = 0;
@observable _openTypes: boolean = false;
- @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
- @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
- @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth(); }
- @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
- @computed get scale() { return this.props.ScreenToLocalTransform().Scale; }
- @computed get columns() { return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); }
- set columns(columns: SchemaHeaderField[]) { this.props.Document._schemaHeaders = new List<SchemaHeaderField>(columns); }
+ @computed get previewWidth() {
+ return () => NumCast(this.props.Document.schemaPreviewWidth);
+ }
+ @computed get previewHeight() {
+ return () => this.props.PanelHeight() - 2 * this.borderWidth;
+ }
+ @computed get tableWidth() {
+ return this.props.PanelWidth() - 2 * this.borderWidth - Number(SCHEMA_DIVIDER_WIDTH) - this.previewWidth();
+ }
+ @computed get borderWidth() {
+ return Number(COLLECTION_BORDER_WIDTH);
+ }
+ @computed get scale() {
+ return this.props.ScreenToLocalTransform().Scale;
+ }
+ @computed get columns() {
+ return Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []);
+ }
+ set columns(columns: SchemaHeaderField[]) {
+ this.props.Document._schemaHeaders = new List<SchemaHeaderField>(columns);
+ }
@computed get menuCoordinates() {
let searchx = 0;
let searchy = 0;
if (this.props.Document._searchDoc) {
- const el = document.getElementsByClassName("collectionSchemaView-searchContainer")[0];
+ const el = document.getElementsByClassName('collectionSchemaView-searchContainer')[0];
if (el !== undefined) {
const rect = el.getBoundingClientRect();
searchx = rect.x;
@@ -93,13 +113,13 @@ export class CollectionSchemaView extends CollectionSubView() {
// then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu
// is displayed (unlikely) it won't show up until something else changes.
//TODO Types
- untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => keys[key] = false))));
+ untracked(() => docs.map(doc => Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)))));
- this.columns.forEach(key => keys[key.heading] = true);
+ this.columns.forEach(key => (keys[key.heading] = true));
return Array.from(Object.keys(keys));
}
- @action setHeaderIsEditing = (isEditing: boolean) => this._headerIsEditing = isEditing;
+ @action setHeaderIsEditing = (isEditing: boolean) => (this._headerIsEditing = isEditing);
@undoBatch
setColumnType = action((columnField: SchemaHeaderField, type: ColumnType): void => {
@@ -124,7 +144,7 @@ export class CollectionSchemaView extends CollectionSubView() {
columns[index] = columnField;
this.columns = columns; // need to set the columns to trigger rerender
}
- }
+ };
@undoBatch
@action
@@ -137,80 +157,109 @@ export class CollectionSchemaView extends CollectionSubView() {
column.setDesc(descending);
columns[index] = column;
this.columns = columns;
- }
+ };
renderTypes = (col: any) => {
- if (columnTypes.get(col.heading)) return (null);
+ if (columnTypes.get(col.heading)) return null;
const type = col.type;
- const anyType = <div className={"columnMenu-option" + (type === ColumnType.Any ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Any)}>
- <FontAwesomeIcon icon={"align-justify"} size="sm" />
- Any
- </div>;
-
- const numType = <div className={"columnMenu-option" + (type === ColumnType.Number ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Number)}>
- <FontAwesomeIcon icon={"hashtag"} size="sm" />
- Number
- </div>;
-
- const textType = <div className={"columnMenu-option" + (type === ColumnType.String ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.String)}>
- <FontAwesomeIcon icon={"font"} size="sm" />
- Text
- </div>;
-
- const boolType = <div className={"columnMenu-option" + (type === ColumnType.Boolean ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
- <FontAwesomeIcon icon={"check-square"} size="sm" />
- Checkbox
- </div>;
-
- const listType = <div className={"columnMenu-option" + (type === ColumnType.List ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.List)}>
- <FontAwesomeIcon icon={"list-ul"} size="sm" />
- List
- </div>;
-
- const docType = <div className={"columnMenu-option" + (type === ColumnType.Doc ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
- <FontAwesomeIcon icon={"file"} size="sm" />
- Document
- </div>;
-
- const imageType = <div className={"columnMenu-option" + (type === ColumnType.Image ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Image)}>
- <FontAwesomeIcon icon={"image"} size="sm" />
- Image
- </div>;
-
- const dateType = <div className={"columnMenu-option" + (type === ColumnType.Date ? " active" : "")} onClick={() => this.setColumnType(col, ColumnType.Date)}>
- <FontAwesomeIcon icon={"calendar"} size="sm" />
- Date
- </div>;
-
-
- const allColumnTypes = <div className="columnMenu-types">
- {anyType}
- {numType}
- {textType}
- {boolType}
- {listType}
- {docType}
- {imageType}
- {dateType}
- </div>;
-
- const justColType = type === ColumnType.Any ? anyType : type === ColumnType.Number ? numType :
- type === ColumnType.String ? textType : type === ColumnType.Boolean ? boolType :
- type === ColumnType.List ? listType : type === ColumnType.Doc ? docType :
- type === ColumnType.Date ? dateType : imageType;
+ const anyType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Any ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Any)}>
+ <FontAwesomeIcon icon={'align-justify'} size="sm" />
+ Any
+ </div>
+ );
+
+ const numType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Number ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Number)}>
+ <FontAwesomeIcon icon={'hashtag'} size="sm" />
+ Number
+ </div>
+ );
+
+ const textType = (
+ <div className={'columnMenu-option' + (type === ColumnType.String ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.String)}>
+ <FontAwesomeIcon icon={'font'} size="sm" />
+ Text
+ </div>
+ );
+
+ const boolType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Boolean ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Boolean)}>
+ <FontAwesomeIcon icon={'check-square'} size="sm" />
+ Checkbox
+ </div>
+ );
+
+ const listType = (
+ <div className={'columnMenu-option' + (type === ColumnType.List ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.List)}>
+ <FontAwesomeIcon icon={'list-ul'} size="sm" />
+ List
+ </div>
+ );
+
+ const docType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Doc ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Doc)}>
+ <FontAwesomeIcon icon={'file'} size="sm" />
+ Document
+ </div>
+ );
+
+ const imageType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Image ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Image)}>
+ <FontAwesomeIcon icon={'image'} size="sm" />
+ Image
+ </div>
+ );
+
+ const dateType = (
+ <div className={'columnMenu-option' + (type === ColumnType.Date ? ' active' : '')} onClick={() => this.setColumnType(col, ColumnType.Date)}>
+ <FontAwesomeIcon icon={'calendar'} size="sm" />
+ Date
+ </div>
+ );
+
+ const allColumnTypes = (
+ <div className="columnMenu-types">
+ {anyType}
+ {numType}
+ {textType}
+ {boolType}
+ {listType}
+ {docType}
+ {imageType}
+ {dateType}
+ </div>
+ );
+
+ const justColType =
+ type === ColumnType.Any
+ ? anyType
+ : type === ColumnType.Number
+ ? numType
+ : type === ColumnType.String
+ ? textType
+ : type === ColumnType.Boolean
+ ? boolType
+ : type === ColumnType.List
+ ? listType
+ : type === ColumnType.Doc
+ ? docType
+ : type === ColumnType.Date
+ ? dateType
+ : imageType;
return (
- <div className="collectionSchema-headerMenu-group" onClick={action(() => this._openTypes = !this._openTypes)}>
+ <div className="collectionSchema-headerMenu-group" onClick={action(() => (this._openTypes = !this._openTypes))}>
<div>
- <label style={{ cursor: "pointer" }}>Column type:</label>
- <FontAwesomeIcon icon={"caret-down"} size="lg" style={{ float: "right", transform: `rotate(${this._openTypes ? "180deg" : 0})`, transition: "0.2s all ease" }} />
+ <label style={{ cursor: 'pointer' }}>Column type:</label>
+ <FontAwesomeIcon icon={'caret-down'} size="lg" style={{ float: 'right', transform: `rotate(${this._openTypes ? '180deg' : 0})`, transition: '0.2s all ease' }} />
</div>
{this._openTypes ? allColumnTypes : justColType}
- </div >
+ </div>
);
- }
+ };
renderSorting = (col: any) => {
const sort = col.desc;
@@ -218,11 +267,11 @@ export class CollectionSchemaView extends CollectionSubView() {
<div className="collectionSchema-headerMenu-group">
<label>Sort by:</label>
<div className="columnMenu-sort">
- <div className={"columnMenu-option" + (sort === true ? " active" : "")} onClick={() => this.setColumnSort(col, true)}>
+ <div className={'columnMenu-option' + (sort === true ? ' active' : '')} onClick={() => this.setColumnSort(col, true)}>
<FontAwesomeIcon icon="sort-amount-down" size="sm" />
Sort descending
</div>
- <div className={"columnMenu-option" + (sort === false ? " active" : "")} onClick={() => this.setColumnSort(col, false)}>
+ <div className={'columnMenu-option' + (sort === false ? ' active' : '')} onClick={() => this.setColumnSort(col, false)}>
<FontAwesomeIcon icon="sort-amount-up" size="sm" />
Sort ascending
</div>
@@ -233,42 +282,42 @@ export class CollectionSchemaView extends CollectionSubView() {
</div>
</div>
);
- }
+ };
renderColors = (col: any) => {
const selected = col.color;
- const pink = PastelSchemaPalette.get("pink2");
- const purple = PastelSchemaPalette.get("purple2");
- const blue = PastelSchemaPalette.get("bluegreen1");
- const yellow = PastelSchemaPalette.get("yellow4");
- const red = PastelSchemaPalette.get("red2");
- const gray = "#f1efeb";
+ const pink = PastelSchemaPalette.get('pink2');
+ const purple = PastelSchemaPalette.get('purple2');
+ const blue = PastelSchemaPalette.get('bluegreen1');
+ const yellow = PastelSchemaPalette.get('yellow4');
+ const red = PastelSchemaPalette.get('red2');
+ const gray = '#f1efeb';
return (
<div className="collectionSchema-headerMenu-group">
<label>Color:</label>
<div className="columnMenu-colors">
- <div className={"columnMenu-colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.setColumnColor(col, pink!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.setColumnColor(col, purple!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.setColumnColor(col, blue!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.setColumnColor(col, yellow!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.setColumnColor(col, red!)}></div>
- <div className={"columnMenu-colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.setColumnColor(col, gray)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === pink ? ' active' : '')} style={{ backgroundColor: pink }} onClick={() => this.setColumnColor(col, pink!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === purple ? ' active' : '')} style={{ backgroundColor: purple }} onClick={() => this.setColumnColor(col, purple!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === blue ? ' active' : '')} style={{ backgroundColor: blue }} onClick={() => this.setColumnColor(col, blue!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === yellow ? ' active' : '')} style={{ backgroundColor: yellow }} onClick={() => this.setColumnColor(col, yellow!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === red ? ' active' : '')} style={{ backgroundColor: red }} onClick={() => this.setColumnColor(col, red!)}></div>
+ <div className={'columnMenu-colorPicker' + (selected === gray ? ' active' : '')} style={{ backgroundColor: gray }} onClick={() => this.setColumnColor(col, gray)}></div>
</div>
</div>
);
- }
+ };
@undoBatch
@action
changeColumns = (oldKey: string, newKey: string, addNew: boolean, filter?: string) => {
const columns = this.columns;
if (columns === undefined) {
- this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]);
+ this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, 'f1efeb')]);
} else {
if (addNew) {
- columns.push(new SchemaHeaderField(newKey, "f1efeb"));
+ columns.push(new SchemaHeaderField(newKey, 'f1efeb'));
this.columns = columns;
} else {
const index = columns.map(c => c.heading).indexOf(oldKey);
@@ -278,15 +327,14 @@ export class CollectionSchemaView extends CollectionSubView() {
columns[index] = column;
this.columns = columns;
if (filter) {
- Doc.setDocFilter(this.props.Document, newKey, filter, "match");
- }
- else {
+ Doc.setDocFilter(this.props.Document, newKey, filter, 'match');
+ } else {
this.props.Document._docFilters = undefined;
}
}
}
}
- }
+ };
@action
openHeader = (col: any, screenx: number, screeny: number) => {
@@ -294,10 +342,12 @@ export class CollectionSchemaView extends CollectionSubView() {
this._headerOpen = true;
this._pointerX = screenx;
this._pointerY = screeny;
- }
+ };
@action
- closeHeader = () => { this._headerOpen = false; }
+ closeHeader = () => {
+ this._headerOpen = false;
+ };
@undoBatch
@action
@@ -313,16 +363,16 @@ export class CollectionSchemaView extends CollectionSubView() {
}
}
this.closeHeader();
- }
+ };
getPreviewTransform = (): Transform => {
- return this.props.ScreenToLocalTransform().translate(- this.borderWidth - NumCast(COLLECTION_BORDER_WIDTH) - this.tableWidth, - this.borderWidth);
- }
+ return this.props.ScreenToLocalTransform().translate(-this.borderWidth - NumCast(COLLECTION_BORDER_WIDTH) - this.tableWidth, -this.borderWidth);
+ };
@action
onHeaderClick = (e: React.PointerEvent) => {
e.stopPropagation();
- }
+ };
@action
onWheel(e: React.WheelEvent) {
@@ -332,40 +382,45 @@ export class CollectionSchemaView extends CollectionSubView() {
@computed get renderMenuContent() {
TraceMobx();
- return <div className="collectionSchema-header-menuOptions">
- {this.renderTypes(this._col)}
- {this.renderColors(this._col)}
- <div className="collectionSchema-headerMenu-group">
- <button onClick={() => { this.deleteColumn(this._col.heading); }}>
- Hide Column
- </button>
+ return (
+ <div className="collectionSchema-header-menuOptions">
+ {this.renderTypes(this._col)}
+ {this.renderColors(this._col)}
+ <div className="collectionSchema-headerMenu-group">
+ <button
+ onClick={() => {
+ this.deleteColumn(this._col.heading);
+ }}>
+ Hide Column
+ </button>
+ </div>
</div>
- </div>;
+ );
}
private createTarget = (ele: HTMLDivElement) => {
this._previewCont = ele;
super.CreateDropTarget(ele);
- }
+ };
isFocused = (doc: Doc, outsideReaction: boolean): boolean => this.props.isSelected(outsideReaction) && doc === this._focusedTable;
- @action setFocused = (doc: Doc) => this._focusedTable = doc;
+ @action setFocused = (doc: Doc) => (this._focusedTable = doc);
@action setPreviewDoc = (doc: Opt<Doc>) => {
SelectionManager.SelectSchemaViewDoc(doc);
this._previewDoc = doc;
- }
+ };
//toggles preview side-panel of schema
@action
toggleExpander = () => {
this.props.Document.schemaPreviewWidth = this.previewWidth() === 0 ? Math.min(this.tableWidth / 3, 200) : 0;
- }
+ };
onDividerDown = (e: React.PointerEvent) => {
setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, this.toggleExpander);
- }
+ };
@action
onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => {
const nativeWidth = this._previewCont!.getBoundingClientRect();
@@ -375,136 +430,146 @@ export class CollectionSchemaView extends CollectionSubView() {
const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
this.props.Document.schemaPreviewWidth = width;
return false;
- }
+ };
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey) {
if (this.props.isSelected(true)) e.stopPropagation();
else this.props.select(false);
}
- }
+ };
@computed
- get previewDocument(): Doc | undefined { return this._previewDoc; }
+ get previewDocument(): Doc | undefined {
+ return this._previewDoc;
+ }
@computed
get dividerDragger() {
- return this.previewWidth() === 0 ? (null) :
- <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} >
+ return this.previewWidth() === 0 ? null : (
+ <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown}>
<div className="collectionSchemaView-dividerDragger" />
- </div>;
+ </div>
+ );
}
@computed
get previewPanel() {
- return <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
- {!this.previewDocument ? (null) :
- <DocumentView
- Document={this.previewDocument}
- DataDoc={undefined}
- fitContentsToBox={returnTrue}
- dontCenter={"y"}
- focus={DocUtils.DefaultFocus}
- renderDepth={this.props.renderDepth}
- rootSelected={this.rootSelected}
- PanelWidth={this.previewWidth}
- PanelHeight={this.previewHeight}
- isContentActive={returnTrue}
- isDocumentActive={returnFalse}
- ScreenToLocalTransform={this.getPreviewTransform}
- docFilters={this.childDocFilters}
- docRangeFilters={this.childDocRangeFilters}
- searchFilterDocs={this.searchFilterDocs}
- styleProvider={DefaultStyleProvider}
- docViewPath={returnEmptyDoclist}
- ContainingCollectionDoc={this.props.CollectionView?.props.Document}
- ContainingCollectionView={this.props.CollectionView}
- moveDocument={this.props.moveDocument}
- addDocument={this.props.addDocument}
- removeDocument={this.props.removeDocument}
- whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- bringToFront={returnFalse}
- />}
- </div>;
+ return (
+ <div ref={this.createTarget} style={{ width: `${this.previewWidth()}px` }}>
+ {!this.previewDocument ? null : (
+ <DocumentView
+ Document={this.previewDocument}
+ DataDoc={undefined}
+ fitContentsToBox={returnTrue}
+ dontCenter={'y'}
+ focus={DocUtils.DefaultFocus}
+ renderDepth={this.props.renderDepth}
+ rootSelected={this.rootSelected}
+ PanelWidth={this.previewWidth}
+ PanelHeight={this.previewHeight}
+ isContentActive={returnTrue}
+ isDocumentActive={returnFalse}
+ ScreenToLocalTransform={this.getPreviewTransform}
+ docFilters={this.childDocFilters}
+ docRangeFilters={this.childDocRangeFilters}
+ searchFilterDocs={this.searchFilterDocs}
+ styleProvider={DefaultStyleProvider}
+ docViewPath={returnEmptyDoclist}
+ ContainingCollectionDoc={this.props.CollectionView?.props.Document}
+ ContainingCollectionView={this.props.CollectionView}
+ moveDocument={this.props.moveDocument}
+ addDocument={this.props.addDocument}
+ removeDocument={this.props.removeDocument}
+ whenChildContentsActiveChanged={this.props.whenChildContentsActiveChanged}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ bringToFront={returnFalse}
+ />
+ )}
+ </div>
+ );
}
@computed
get schemaTable() {
- return <SchemaTable
- Document={this.props.Document}
- PanelHeight={this.props.PanelHeight}
- PanelWidth={this.props.PanelWidth}
- childDocs={this.childDocs}
- CollectionView={this.props.CollectionView}
- ContainingCollectionView={this.props.ContainingCollectionView}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc}
- fieldKey={this.props.fieldKey}
- renderDepth={this.props.renderDepth}
- moveDocument={this.props.moveDocument}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform}
- active={this.props.isContentActive}
- onDrop={this.onExternalDrop}
- addDocTab={this.props.addDocTab}
- pinToPres={this.props.pinToPres}
- isSelected={this.props.isSelected}
- isFocused={this.isFocused}
- setFocused={this.setFocused}
- setPreviewDoc={this.setPreviewDoc}
- deleteDocument={this.props.removeDocument}
- addDocument={this.props.addDocument}
- dataDoc={this.props.DataDoc}
- columns={this.columns}
- documentKeys={this.documentKeys}
- headerIsEditing={this._headerIsEditing}
- openHeader={this.openHeader}
- onClick={this.onTableClick}
- onPointerDown={emptyFunction}
- onResizedChange={this.onResizedChange}
- setColumns={this.setColumns}
- reorderColumns={this.reorderColumns}
- changeColumns={this.changeColumns}
- setHeaderIsEditing={this.setHeaderIsEditing}
- changeColumnSort={this.setColumnSort}
- />;
+ return (
+ <SchemaTable
+ Document={this.props.Document}
+ PanelHeight={this.props.PanelHeight}
+ PanelWidth={this.props.PanelWidth}
+ childDocs={this.childDocs}
+ CollectionView={this.props.CollectionView}
+ ContainingCollectionView={this.props.ContainingCollectionView}
+ ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+ fieldKey={this.props.fieldKey}
+ renderDepth={this.props.renderDepth}
+ moveDocument={this.props.moveDocument}
+ ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+ active={this.props.isContentActive}
+ onDrop={this.onExternalDrop}
+ addDocTab={this.props.addDocTab}
+ pinToPres={this.props.pinToPres}
+ isSelected={this.props.isSelected}
+ isFocused={this.isFocused}
+ setFocused={this.setFocused}
+ setPreviewDoc={this.setPreviewDoc}
+ deleteDocument={this.props.removeDocument}
+ addDocument={this.props.addDocument}
+ dataDoc={this.props.DataDoc}
+ columns={this.columns}
+ documentKeys={this.documentKeys}
+ headerIsEditing={this._headerIsEditing}
+ openHeader={this.openHeader}
+ onClick={this.onTableClick}
+ onPointerDown={emptyFunction}
+ onResizedChange={this.onResizedChange}
+ setColumns={this.setColumns}
+ reorderColumns={this.reorderColumns}
+ changeColumns={this.changeColumns}
+ setHeaderIsEditing={this.setHeaderIsEditing}
+ changeColumnSort={this.setColumnSort}
+ />
+ );
}
@computed
public get schemaToolbar() {
- return <div className="collectionSchemaView-toolbar">
- <div className="collectionSchemaView-toolbar-item">
- <div id="preview-schema-checkbox-div">
- <input type="checkbox" key={"Show Preview"} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />
- Show Preview
+ return (
+ <div className="collectionSchemaView-toolbar">
+ <div className="collectionSchemaView-toolbar-item">
+ <div id="preview-schema-checkbox-div">
+ <input type="checkbox" key={'Show Preview'} checked={this.previewWidth() !== 0} onChange={this.toggleExpander} />
+ Show Preview
+ </div>
</div>
</div>
- </div>;
+ );
}
onSpecificMenu = (e: React.MouseEvent) => {
- if ((e.target as any)?.className?.includes?.("collectionSchemaView-cell") || (e.target instanceof HTMLSpanElement)) {
+ if ((e.target as any)?.className?.includes?.('collectionSchemaView-cell') || e.target instanceof HTMLSpanElement) {
const cm = ContextMenu.Instance;
- const options = cm.findByDescription("Options...");
- const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
- optionItems.push({ description: "remove", event: () => this._previewDoc && this.props.removeDocument?.(this._previewDoc), icon: "trash" });
- !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
+ const options = cm.findByDescription('Options...');
+ const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
+ optionItems.push({ description: 'remove', event: () => this._previewDoc && this.props.removeDocument?.(this._previewDoc), icon: 'trash' });
+ !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'compass' });
cm.displayMenu(e.clientX, e.clientY);
(e.nativeEvent as any).SchemaHandled = true; // not sure why this is needed, but if you right-click quickly on a cell, the Document/Collection contextMenu handlers still fire without this.
e.stopPropagation();
}
- }
+ };
@action
onTableClick = (e: React.MouseEvent): void => {
- if (!(e.target as any)?.className?.includes?.("collectionSchemaView-cell") && !(e.target instanceof HTMLSpanElement)) {
+ if (!(e.target as any)?.className?.includes?.('collectionSchemaView-cell') && !(e.target instanceof HTMLSpanElement)) {
this.setPreviewDoc(undefined);
} else {
e.stopPropagation();
}
this.setFocused(this.props.Document);
this.closeHeader();
- }
+ };
onResizedChange = (newResized: Resize[], event: any) => {
const columns = this.columns;
@@ -515,23 +580,23 @@ export class CollectionSchemaView extends CollectionSubView() {
columns[index] = column;
});
this.columns = columns;
- }
+ };
@action
- setColumns = (columns: SchemaHeaderField[]) => this.columns = columns
+ setColumns = (columns: SchemaHeaderField[]) => (this.columns = columns);
@undoBatch
reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => {
const columns = [...columnsValues];
const oldIndex = columns.indexOf(toMove);
const relIndex = columns.indexOf(relativeTo);
- const newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex;
+ const newIndex = oldIndex > relIndex && !before ? relIndex + 1 : oldIndex < relIndex && before ? relIndex - 1 : relIndex;
if (oldIndex === newIndex) return;
columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
this.columns = columns;
- }
+ };
onZoomMenu = (e: React.WheelEvent) => this.props.isContentActive(true) && e.stopPropagation();
@@ -539,35 +604,44 @@ export class CollectionSchemaView extends CollectionSubView() {
TraceMobx();
if (!this.props.isContentActive()) setTimeout(() => this.closeHeader(), 0);
const menuContent = this.renderMenuContent;
- const menu = <div className="collectionSchema-header-menu"
- onWheel={e => this.onZoomMenu(e)}
- onPointerDown={e => this.onHeaderClick(e)}
- style={{ transform: `translate(${(this.menuCoordinates[0])}px, ${(this.menuCoordinates[1])}px)` }}>
- <Measure offset onResize={action((r: any) => {
- const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
- this._menuWidth = dim[0]; this._menuHeight = dim[1];
- })}>
- {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
- </Measure>
- </div>;
- return <div className={"collectionSchemaView" + (this.props.Document._searchDoc ? "-searchContainer" : "-container")}
- style={{
- overflow: this.props.scrollOverflow === true ? "scroll" : undefined, backgroundColor: "white",
- pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined,
- width: this.props.PanelWidth() || "100%", height: this.props.PanelHeight() || "100%", position: "relative",
- }} >
- <div className="collectionSchemaView-tableContainer"
- style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
- onContextMenu={this.onSpecificMenu}
- onPointerDown={this.onPointerDown}
- onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}
- onDrop={e => this.onExternalDrop(e, {})}
- ref={this.createTarget}>
- {this.schemaTable}
+ const menu = (
+ <div className="collectionSchema-header-menu" onWheel={e => this.onZoomMenu(e)} onPointerDown={e => this.onHeaderClick(e)} style={{ transform: `translate(${this.menuCoordinates[0]}px, ${this.menuCoordinates[1]}px)` }}>
+ <Measure
+ offset
+ onResize={action((r: any) => {
+ const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
+ this._menuWidth = dim[0];
+ this._menuHeight = dim[1];
+ })}>
+ {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
+ </Measure>
</div>
- {this.dividerDragger}
- {!this.previewWidth() ? (null) : this.previewPanel}
- {this._headerOpen && this.props.isContentActive() ? menu : null}
- </div>;
+ );
+ return (
+ <div
+ className={'collectionSchemaView' + (this.props.Document._searchDoc ? '-searchContainer' : '-container')}
+ style={{
+ overflow: this.props.scrollOverflow === true ? 'scroll' : undefined,
+ backgroundColor: 'white',
+ pointerEvents: this.props.Document._searchDoc !== undefined && !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'none' : undefined,
+ width: this.props.PanelWidth() || '100%',
+ height: this.props.PanelHeight() || '100%',
+ position: 'relative',
+ }}>
+ <div
+ className="collectionSchemaView-tableContainer"
+ style={{ width: `calc(100% - ${this.previewWidth()}px)` }}
+ onContextMenu={this.onSpecificMenu}
+ onPointerDown={this.onPointerDown}
+ onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}
+ onDrop={e => this.onExternalDrop(e, {})}
+ ref={this.createTarget}>
+ {this.schemaTable}
+ </div>
+ {this.dividerDragger}
+ {!this.previewWidth() ? null : this.previewPanel}
+ {this._headerOpen && this.props.isContentActive() ? menu : null}
+ </div>
+ );
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 28874220a..539fb5c99 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -14,7 +14,7 @@ import { WebField } from '../../../../fields/URLField';
import { aggregateBounds, Utils } from '../../../../Utils';
import { DocumentType } from '../../../documents/DocumentTypes';
import { CurrentUserUtils } from '../../../util/CurrentUserUtils';
-import { ScriptingGlobals } from "../../../util/ScriptingGlobals";
+import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { SelectionManager } from '../../../util/SelectionManager';
import { undoBatch, UndoManager } from '../../../util/UndoManager';
import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
@@ -34,23 +34,23 @@ import { FontIconBadge } from './FontIconBadge';
import './FontIconBox.scss';
export enum ButtonType {
- TextButton = "textBtn",
- MenuButton = "menuBtn",
- DropdownList = "drpdownList",
- DropdownButton = "drpdownBtn",
- ClickButton = "clickBtn",
- DoubleButton = "dblBtn",
- ToggleButton = "tglBtn",
- ColorButton = "colorBtn",
- ToolButton = "toolBtn",
- NumberButton = "numBtn",
- EditableText = "editableText"
+ TextButton = 'textBtn',
+ MenuButton = 'menuBtn',
+ DropdownList = 'drpdownList',
+ DropdownButton = 'drpdownBtn',
+ ClickButton = 'clickBtn',
+ DoubleButton = 'dblBtn',
+ ToggleButton = 'tglBtn',
+ ColorButton = 'colorBtn',
+ ToolButton = 'toolBtn',
+ NumberButton = 'numBtn',
+ EditableText = 'editableText',
}
export enum NumButtonType {
- Slider = "slider",
- DropdownOptions = "list",
- Inline = "inline"
+ Slider = 'slider',
+ DropdownOptions = 'list',
+ Inline = 'inline',
}
export interface ButtonProps extends FieldViewProps {
@@ -58,29 +58,39 @@ export interface ButtonProps extends FieldViewProps {
}
@observer
export class FontIconBox extends DocComponent<ButtonProps>() {
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FontIconBox, fieldKey); }
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(FontIconBox, fieldKey);
+ }
showTemplate = (): void => {
const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
- dragFactory && this.props.addDocTab(dragFactory, "add:right");
- }
- dragAsTemplate = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); };
- useAsPrototype = (): void => { this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)'); };
+ dragFactory && this.props.addDocTab(dragFactory, 'add:right');
+ };
+ dragAsTemplate = (): void => {
+ this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)');
+ };
+ useAsPrototype = (): void => {
+ this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)');
+ };
specificContextMenu = (): void => {
if (!Doc.noviceMode) {
const cm = ContextMenu.Instance;
- cm.addItem({ description: "Show Template", event: this.showTemplate, icon: "tag" });
- cm.addItem({ description: "Use as Render Template", event: this.dragAsTemplate, icon: "tag" });
- cm.addItem({ description: "Use as Prototype", event: this.useAsPrototype, icon: "tag" });
+ cm.addItem({ description: 'Show Template', event: this.showTemplate, icon: 'tag' });
+ cm.addItem({ description: 'Use as Render Template', event: this.dragAsTemplate, icon: 'tag' });
+ cm.addItem({ description: 'Use as Prototype', event: this.useAsPrototype, icon: 'tag' });
}
- }
+ };
- static GetShowLabels() { return BoolCast(Doc.UserDoc()._showLabel); }
- static SetShowLabels(show:boolean) { Doc.UserDoc()._showLabel = show; }
+ static GetShowLabels() {
+ return BoolCast(Doc.UserDoc()._showLabel);
+ }
+ static SetShowLabels(show: boolean) {
+ Doc.UserDoc()._showLabel = show;
+ }
// Determining UI Specs
@observable private label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
- @observable private icon = StrCast(this.dataDoc.icon, "user") as any;
+ @observable private icon = StrCast(this.dataDoc.icon, 'user') as any;
@observable private dropdown: boolean = BoolCast(this.rootDoc.dropDownOpen);
@observable private buttonList: string[] = StrListCast(this.rootDoc.btnList);
@observable private type = StrCast(this.rootDoc.btnType);
@@ -92,11 +102,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
* - Expandable button (CollectionLinearView)
* - Button inside of CollectionLinearView vs. outside of CollectionLinearView
* - Action button
- * - Dropdown button
+ * - Dropdown button
* - Color button
* - Dropdown list
* - Number button
- **/
+ **/
_batch: UndoManager.Batch | undefined = undefined;
/**
@@ -110,25 +120,30 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
// Script for checking the outcome of the toggle
const checkResult: number = numScript?.script.run({ value: 0, _readOnly_: true }).result || 0;
- const label = !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label">
- {this.label}
- </div>;
+ const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
if (numBtnType === NumButtonType.Slider) {
- const dropdown = <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()} >
- <input type="range" step="1" min={NumCast(this.rootDoc.numBtnMin, 0)} max={NumCast(this.rootDoc.numBtnMax, 100)} value={checkResult}
- className={"menu-slider"} id="slider"
- onPointerDown={() => this._batch = UndoManager.StartBatch("presDuration")}
- onPointerUp={() => this._batch?.end()}
- onChange={e => { e.stopPropagation(); setValue(Number(e.target.value)); }}
- />
- </div>;
+ const dropdown = (
+ <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()}>
+ <input
+ type="range"
+ step="1"
+ min={NumCast(this.rootDoc.numBtnMin, 0)}
+ max={NumCast(this.rootDoc.numBtnMax, 100)}
+ value={checkResult}
+ className={'menu-slider'}
+ id="slider"
+ onPointerDown={() => (this._batch = UndoManager.StartBatch('presDuration'))}
+ onPointerUp={() => this._batch?.end()}
+ onChange={e => {
+ e.stopPropagation();
+ setValue(Number(e.target.value));
+ }}
+ />
+ </div>
+ );
return (
- <div
- className={`menuButton ${this.type} ${numBtnType}`}
- onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
- >
+ <div className={`menuButton ${this.type} ${numBtnType}`} onClick={action(() => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen))}>
{checkResult}
{label}
{this.rootDoc.dropDownOpen ? dropdown : null}
@@ -141,62 +156,56 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
items.push(i);
}
}
- const list = items.map((value) => {
- return <div className="list-item" key={`${value}`}
- style={{
- backgroundColor: value === checkResult ? Colors.LIGHT_BLUE : undefined
- }}
- onClick={() => setValue(value)}>
- {value}
- </div>;
+ const list = items.map(value => {
+ return (
+ <div
+ className="list-item"
+ key={`${value}`}
+ style={{
+ backgroundColor: value === checkResult ? Colors.LIGHT_BLUE : undefined,
+ }}
+ onClick={() => setValue(value)}>
+ {value}
+ </div>
+ );
});
return (
- <div
- className={`menuButton ${this.type} ${numBtnType}`}
- >
- <div className={`button`} onClick={action((e) => setValue(Number(checkResult) - 1))}>
- <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"minus"} />
+ <div className={`menuButton ${this.type} ${numBtnType}`}>
+ <div className={`button`} onClick={action(e => setValue(Number(checkResult) - 1))}>
+ <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'minus'} />
</div>
<div
className={`button ${'number'}`}
- onPointerDown={(e) => {
+ onPointerDown={e => {
e.stopPropagation();
e.preventDefault();
}}
- onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}
- >
- <input
- style={{ width: 30 }}
- className="button-input"
- type="number"
- value={checkResult}
- onChange={action((e) => setValue(Number(e.target.value)))}
- />
+ onClick={action(() => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen))}>
+ <input style={{ width: 30 }} className="button-input" type="number" value={checkResult} onChange={action(e => setValue(Number(e.target.value)))} />
</div>
- <div className={`button`} onClick={action((e) => setValue(Number(checkResult) + 1))}>
- <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"plus"} />
+ <div className={`button`} onClick={action(e => setValue(Number(checkResult) + 1))}>
+ <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'plus'} />
</div>
- {this.rootDoc.dropDownOpen ?
+ {this.rootDoc.dropDownOpen ? (
<div>
- <div className="menuButton-dropdownList"
- style={{ left: "25%" }}>
+ <div className="menuButton-dropdownList" style={{ left: '25%' }}>
{list}
</div>
- <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
- </div> : null}
-
+ <div
+ className="dropbox-background"
+ onClick={e => {
+ e.stopPropagation();
+ this.rootDoc.dropDownOpen = false;
+ }}
+ />
+ </div>
+ ) : null}
</div>
);
} else {
- return (
- <div>
-
- </div>
- );
+ return <div></div>;
}
-
-
}
/**
@@ -207,20 +216,21 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
return (
- <div className={`menuButton ${this.type} ${active}`}
+ <div
+ className={`menuButton ${this.type} ${active}`}
style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
- onClick={action(() => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen)}>
+ onClick={action(() => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen))}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
- {!this.label || !FontIconBox.GetShowLabels() ? (null) : <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
- <div
- className="menuButton-dropdown"
- style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
+ {!this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
+ {' '}
+ {this.label}{' '}
+ </div>
+ )}
+ <div className="menuButton-dropdown" style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
<FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
</div>
- {this.rootDoc.dropDownOpen ?
- <div className="menuButton-dropdownBox">
- {/* DROPDOWN BOX CONTENTS */}
- </div> : null}
+ {this.rootDoc.dropDownOpen ? <div className="menuButton-dropdownBox">{/* DROPDOWN BOX CONTENTS */}</div> : null}
</div>
);
}
@@ -234,12 +244,14 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
const script = ScriptCast(this.rootDoc.script);
- if (!script) { return null; }
+ if (!script) {
+ return null;
+ }
let noviceList: string[] = [];
let text: string | undefined;
let dropdown = true;
- let icon: IconProp = "caret-down";
+ let icon: IconProp = 'caret-down';
try {
if (script.script.originalScript.startsWith('setView')) {
const selected = SelectionManager.Docs().lastElement();
@@ -248,100 +260,110 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
text = StrCast(selected._viewType);
} else {
dropdown = false;
- text = selected.type === DocumentType.RTF ? "Text" : StrCast(selected.type);
+ text = selected.type === DocumentType.RTF ? 'Text' : StrCast(selected.type);
icon = Doc.toIcon(selected);
}
} else {
dropdown = false;
- icon = "globe-asia";
- text = "User Default";
+ icon = 'globe-asia';
+ text = 'User Default';
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
} else if (script.script.originalScript.startsWith('setFont')) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
- noviceList = ["Roboto", "Times New Roman", "Arial", "Georgia",
- "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"];
+ noviceList = ['Roboto', 'Times New Roman', 'Arial', 'Georgia', 'Comic Sans MS', 'Tahoma', 'Impact', 'Crimson Text'];
}
} catch (e) {
console.log(e);
}
// Get items to place into the list
- const list = this.buttonList.map((value) => {
+ const list = this.buttonList.map(value => {
if (Doc.noviceMode && !noviceList.includes(value)) {
return;
}
- return <div className="list-item" key={`${value}`}
- style={{
- fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
- backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined
- }}
- onClick={() => script.script.run({ value }).result}>
- {value[0].toUpperCase() + value.slice(1)}
- </div>;
+ return (
+ <div
+ className="list-item"
+ key={`${value}`}
+ style={{
+ fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
+ backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined,
+ }}
+ onClick={() => script.script.run({ value }).result}>
+ {value[0].toUpperCase() + value.slice(1)}
+ </div>
+ );
});
- const label = !this.label || !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label" style={{ bottom: 0, position: "absolute", color: color, backgroundColor: backgroundColor }}>
- {this.label}
- </div>;
+ const label =
+ !this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ bottom: 0, position: 'absolute', color: color, backgroundColor: backgroundColor }}>
+ {this.label}
+ </div>
+ );
return (
- <div className={`menuButton ${this.type} ${active}`}
- style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }}
- onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
- {dropdown ? (null) : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
- <div className="menuButton-dropdown-header">
- {text && text[0].toUpperCase() + text.slice(1)}
- </div>
+ <div
+ className={`menuButton ${this.type} ${active}`}
+ style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : 'flex' }}
+ onClick={dropdown ? () => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen) : undefined}>
+ {dropdown ? null : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
+ <div className="menuButton-dropdown-header">{text && text[0].toUpperCase() + text.slice(1)}</div>
{label}
- {!dropdown ? (null) : <div className="menuButton-dropDown">
- <FontAwesomeIcon icon={icon} color={color} size="sm" />
- </div>}
- {this.rootDoc.dropDownOpen ?
+ {!dropdown ? null : (
+ <div className="menuButton-dropDown">
+ <FontAwesomeIcon icon={icon} color={color} size="sm" />
+ </div>
+ )}
+ {this.rootDoc.dropDownOpen ? (
<div>
- <div className="menuButton-dropdownList"
- style={{ left: 0 }}>
+ <div className="menuButton-dropdownList" style={{ left: 0 }}>
{list}
</div>
- <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.rootDoc.dropDownOpen = false; }} />
+ <div
+ className="dropbox-background"
+ onClick={e => {
+ e.stopPropagation();
+ this.rootDoc.dropDownOpen = false;
+ }}
+ />
</div>
- : null}
+ ) : null}
</div>
);
}
@observable colorPickerClosed: boolean = true;
- @computed get colorScript() { return ScriptCast(this.rootDoc.script); }
+ @computed get colorScript() {
+ return ScriptCast(this.rootDoc.script);
+ }
colorPicker = (curColor: string) => {
const change = (value: ColorState) => {
const s = this.colorScript;
s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)();
};
- const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
- '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
- '#FFFFFF', '#f1efeb', "transparent"];
- return <SketchPicker
- onChange={change}
- color={curColor}
- presetColors={presets} />;
- }
+ const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent'];
+ return <SketchPicker onChange={change} color={curColor} presetColors={presets} />;
+ };
/**
* Color button
*/
@computed get colorButton() {
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? "transparent";
-
- const label = !this.label || !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label" style={{ color, backgroundColor }}>
- {this.label}
- </div>;
-
- // dropdown caret seems superfluous since clicking the color button does the same thing
+ const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? 'transparent';
+
+ const label =
+ !this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ color, backgroundColor }}>
+ {this.label}
+ </div>
+ );
+
+ // dropdown caret seems superfluous since clicking the color button does the same thing
// const dropdownCaret = <div
// className="menuButton-dropDown"
// style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
@@ -349,26 +371,30 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
// </div>;
setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView
return (
- <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? "Label" : "")} ${this.colorPickerClosed}`}
+ <div
+ className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')} ${this.colorPickerClosed}`}
style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
- onClick={action(() => this.colorPickerClosed = !this.colorPickerClosed)}
+ onClick={action(() => (this.colorPickerClosed = !this.colorPickerClosed))}
onPointerDown={e => e.stopPropagation()}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
<div className="colorButton-color" style={{ backgroundColor: curColor }} />
{label}
{/* {dropdownCaret} */}
- {this.colorPickerClosed ? (null) :
+ {this.colorPickerClosed ? null : (
<div>
- <div className="menuButton-dropdownBox"
- onPointerDown={e => e.stopPropagation()}
- onClick={e => e.stopPropagation()}>
+ <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()} onClick={e => e.stopPropagation()}>
{this.colorPicker(curColor)}
</div>
- <div className="dropbox-background" onPointerDown={action((e) => {
- e.preventDefault();
- e.stopPropagation(); this.colorPickerClosed = true;
- })} />
- </div>}
+ <div
+ className="dropbox-background"
+ onPointerDown={action(e => {
+ e.preventDefault();
+ e.stopPropagation();
+ this.colorPickerClosed = true;
+ })}
+ />
+ </div>
+ )}
</div>
);
}
@@ -382,27 +408,26 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
// Button label
- const label = !this.label || !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label" style={{ color, backgroundColor }}>
- {this.label}
- </div>;
+ const label =
+ !this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ color, backgroundColor }}>
+ {this.label}
+ </div>
+ );
if (switchToggle) {
return (
<div className={`menuButton ${this.type} ${'switch'}`}>
{buttonText ? buttonText : null}
<label className="switch">
- <input type="checkbox"
- checked={backgroundColor === Colors.MEDIUM_BLUE}
- />
+ <input type="checkbox" checked={backgroundColor === Colors.MEDIUM_BLUE} />
<span className="slider round" />
</label>
</div>
);
} else {
return (
- <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? "Label" : "")}`}
- style={{ opacity: 1, backgroundColor, color }}>
+ <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')}`} style={{ opacity: 1, backgroundColor, color }}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
{label}
</div>
@@ -410,8 +435,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
}
}
-
-
/**
* Default
*/
@@ -420,12 +443,15 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
const active: string = StrCast(this.rootDoc.dropDownOpen);
return (
- <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu}
- style={{ backgroundColor: "transparent", borderBottomLeftRadius: this.dropdown ? 0 : undefined }}>
+ <div className={`menuButton ${this.type}`} onContextMenu={this.specificContextMenu} style={{ backgroundColor: 'transparent', borderBottomLeftRadius: this.dropdown ? 0 : undefined }}>
<div className="menuButton-wrap">
- <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={"black"} size={"sm"} />
- {!this.label || !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}> {this.label} </div>}
+ <FontAwesomeIcon className={`menuButton-icon-${this.type}`} icon={this.icon} color={'black'} size={'sm'} />
+ {!this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
+ {' '}
+ {this.label}{' '}
+ </div>
+ )}
</div>
</div>
);
@@ -435,14 +461,14 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
// Script for running the toggle
const script = ScriptCast(this.rootDoc.script);
// Function to run the script
- const checkResult = script?.script.run({ value: "", _readOnly_: true }).result;
+ const checkResult = script?.script.run({ value: '', _readOnly_: true }).result;
const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
return (
<div className="menuButton editableText">
- <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"lock"} />
- <div style={{ width: "calc(100% - .875em)", paddingLeft: "4px" }}>
- <EditableView GetValue={() => script?.script.run({ value: "", _readOnly_: true }).result} SetValue={setValue} contents={checkResult} />
+ <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={'lock'} />
+ <div style={{ width: 'calc(100% - .875em)', paddingLeft: '4px' }}>
+ <EditableView GetValue={() => script?.script.run({ value: '', _readOnly_: true }).result} SetValue={setValue} contents={checkResult} />
</div>
</div>
);
@@ -451,15 +477,19 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
render() {
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const label = !this.label || !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label" style={{ color, backgroundColor }}>
- {this.label}
- </div>;
+ const label =
+ !this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ color, backgroundColor }}>
+ {this.label}
+ </div>
+ );
- const menuLabel = !this.label || !FontIconBox.GetShowLabels() ? (null) :
- <div className="fontIconBox-label" style={{ color, backgroundColor: "transparent" }}>
- {this.label}
- </div>;
+ const menuLabel =
+ !this.label || !FontIconBox.GetShowLabels() ? null : (
+ <div className="fontIconBox-label" style={{ color, backgroundColor: 'transparent' }}>
+ {this.label}
+ </div>
+ );
const buttonText = StrCast(this.rootDoc.buttonText);
@@ -471,11 +501,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
button = (
<div className={`menuButton ${this.type}`} style={{ color, backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
- {buttonText ?
- <div className="button-text">
- {buttonText}
- </div>
- : null}
+ {buttonText ? <div className="button-text">{buttonText}</div> : null}
{label}
</div>
);
@@ -498,7 +524,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
break;
case ButtonType.ToolButton:
button = (
- <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? "Label" : "")}`} style={{ opacity: 1, backgroundColor, color }}>
+ <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')}`} style={{ opacity: 1, backgroundColor, color }}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
{label}
</div>
@@ -510,48 +536,45 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
break;
case ButtonType.ClickButton:
button = (
- <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? "Label" : "")}`} style={{ color, backgroundColor, opacity: 1 }}>
+ <div className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')}`} style={{ color, backgroundColor, opacity: 1 }}>
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
{label}
</div>
);
break;
case ButtonType.MenuButton:
- const trailsIcon = <img src={`/assets/${"presTrails.png"}`}
- style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />;
+ const trailsIcon = <img src={`/assets/${'presTrails.png'}`} style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? '0%' : '100%'})` }} />;
button = (
<div className={`menuButton ${this.type}`} style={{ color, backgroundColor }}>
- {this.icon === "pres-trail" ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />}
+ {this.icon === 'pres-trail' ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />}
{menuLabel}
- <FontIconBadge value={Cast(this.Document.badgeValue,"string",null)} />
- </div >
+ <FontIconBadge value={Cast(this.Document.badgeValue, 'string', null)} />
+ </div>
);
break;
default:
break;
}
- return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? button :
- button !== null ?
- <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
- {button}
- </Tooltip > : null
+ return !this.layoutDoc.toolTip || this.type === ButtonType.DropdownList || this.type === ButtonType.ColorButton || this.type === ButtonType.NumberButton || this.type === ButtonType.EditableText ? (
+ button
+ ) : button !== null ? (
+ <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>{button}</Tooltip>
+ ) : null;
}
}
-
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setView(view: string) {
const selected = SelectionManager.Docs().lastElement();
- selected ? selected._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
+ selected ? (selected._viewType = view) : console.log('[FontIconBox.tsx] changeView failed');
});
-
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) {
const selected = SelectionManager.Docs().lastElement();
if (checkResult) {
- return selected?._backgroundColor ?? "transparent";
+ return selected?._backgroundColor ?? 'transparent';
}
if (selected) selected._backgroundColor = color;
});
@@ -563,7 +586,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole
}
Doc.SharingDoc().userColor = undefined;
Doc.GetProto(Doc.SharingDoc()).userColor = color;
- Doc.UserDoc().showTitle = color === "transparent" ? undefined : StrCast(Doc.UserDoc().showTitle, "creationDate");
+ Doc.UserDoc().showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().showTitle, 'creationDate');
});
// toggle: Set overlay status of selected document
@@ -571,9 +594,9 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
if (checkResult) {
if (NumCast(selected?.Document.z) >= 1) return Colors.MEDIUM_BLUE;
- return "transparent";
+ return 'transparent';
}
- selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
+ selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
});
/** TEXT
@@ -590,7 +613,7 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) {
- SelectionManager.Docs().map(doc => doc._fontFamily = font);
+ SelectionManager.Docs().map(doc => (doc._fontFamily = font));
const editorView = RichTextMenu.Instance.TextView?.EditorView;
if (checkResult) {
return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
@@ -599,32 +622,36 @@ ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) {
else Doc.UserDoc().fontFamily = font;
});
-ScriptingGlobals.add(function getActiveTextInfo(info: "family" | "size" | "color" | "highlight") {
+ScriptingGlobals.add(function getActiveTextInfo(info: 'family' | 'size' | 'color' | 'highlight') {
const editorView = RichTextMenu.Instance.TextView?.EditorView;
const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection();
switch (info) {
- case "family": return style?.activeFamilies[0];
- case "size": return style?.activeSizes[0];
- case "color": return style?.activeColors[0];
- case "highlight": return style?.activeHighlights[0];
+ case 'family':
+ return style?.activeFamilies[0];
+ case 'size':
+ return style?.activeSizes[0];
+ case 'color':
+ return style?.activeColors[0];
+ case 'highlight':
+ return style?.activeHighlights[0];
}
});
-ScriptingGlobals.add(function setAlignment(align: "left" | "right" | "center", checkResult?: boolean) {
+ScriptingGlobals.add(function setAlignment(align: 'left' | 'right' | 'center', checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
- return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : "transparent";
+ return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : 'transparent';
}
if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align);
else Doc.UserDoc().textAlign = align;
});
-ScriptingGlobals.add(function setBulletList(mapStyle: "bullet" | "decimal", checkResult?: boolean) {
+ScriptingGlobals.add(function setBulletList(mapStyle: 'bullet' | 'decimal', checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
if (active === mapStyle) return Colors.MEDIUM_BLUE;
- return "transparent";
+ return 'transparent';
}
editorView?.state && RichTextMenu.Instance.changeListType(mapStyle);
});
@@ -662,17 +689,17 @@ ScriptingGlobals.add(function setFontHighlight(color?: string, checkResult?: boo
ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
- return RichTextMenu.Instance.fontSize.replace("px", "");
+ return RichTextMenu.Instance.fontSize.replace('px', '');
}
- if (typeof size === "number") size = size.toString();
- if (size && Number(size).toString() === size) size += "px";
+ if (typeof size === 'number') size = size.toString();
+ if (size && Number(size).toString() === size) size += 'px';
if (editorView) RichTextMenu.Instance.setFontSize(size);
else Doc.UserDoc()._fontSize = size;
});
ScriptingGlobals.add(function toggleNoAutoLinkAnchor(checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
- return (editorView ? RichTextMenu.Instance.noAutoLink : false) ? Colors.MEDIUM_BLUE : "transparent";
+ return (editorView ? RichTextMenu.Instance.noAutoLink : false) ? Colors.MEDIUM_BLUE : 'transparent';
}
if (editorView) RichTextMenu.Instance?.toggleNoAutoLinkAnchor();
});
@@ -680,31 +707,30 @@ ScriptingGlobals.add(function toggleNoAutoLinkAnchor(checkResult?: boolean) {
ScriptingGlobals.add(function toggleBold(checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
- return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === "bold") ? Colors.MEDIUM_BLUE : "transparent";
+ return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === 'bold') ? Colors.MEDIUM_BLUE : 'transparent';
}
if (editorView) RichTextMenu.Instance?.toggleBold();
- else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === "bold" ? undefined : "bold";
+ else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold';
});
ScriptingGlobals.add(function toggleUnderline(checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
- return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === "underline") ? Colors.MEDIUM_BLUE : "transparent";
+ return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === 'underline') ? Colors.MEDIUM_BLUE : 'transparent';
}
if (editorView) RichTextMenu.Instance?.toggleUnderline();
- else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === "underline" ? undefined : "underline";
+ else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline';
});
ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
if (checkResult) {
- return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === "italics") ? Colors.MEDIUM_BLUE : "transparent";
+ return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === 'italics') ? Colors.MEDIUM_BLUE : 'transparent';
}
if (editorView) RichTextMenu.Instance?.toggleItalics();
- else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === "italics" ? undefined : "italics";
+ else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics';
});
-
export function checkInksToGroup() {
// console.log("getting here to inks group");
if (CurrentUserUtils.ActiveTool === InkTool.Write) {
@@ -725,15 +751,17 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
// TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
const selected = ffView.unprocessedDocs;
// loop through selected an get the bound
- const bounds: { x: number, y: number, width?: number, height?: number }[] = []
-
- selected.map(action(d => {
- const x = NumCast(d.x);
- const y = NumCast(d.y);
- const width = d[WidthSym]();
- const height = d[HeightSym]();
- bounds.push({ x, y, width, height });
- }))
+ const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
+
+ selected.map(
+ action(d => {
+ const x = NumCast(d.x);
+ const y = NumCast(d.y);
+ const width = d[WidthSym]();
+ const height = d[HeightSym]();
+ bounds.push({ x, y, width, height });
+ })
+ );
const aggregBounds = aggregateBounds(bounds, 0, 0);
const marqViewRef = ffView._marqueeViewRef.current;
@@ -746,21 +774,23 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
marqViewRef._lastY = aggregBounds.b;
}
- selected.map(action(d => {
- const dx = NumCast(d.x);
- const dy = NumCast(d.y);
- delete d.x;
- delete d.y;
- delete d.activeFrame;
- delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
- delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
- // calculate pos based on bounds
- if (marqViewRef?.Bounds) {
- d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
- d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
- }
- return d;
- }));
+ selected.map(
+ action(d => {
+ const dx = NumCast(d.x);
+ const dy = NumCast(d.y);
+ delete d.x;
+ delete d.y;
+ delete d.activeFrame;
+ delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+ delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+ // calculate pos based on bounds
+ if (marqViewRef?.Bounds) {
+ d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
+ d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
+ }
+ return d;
+ })
+ );
ffView.props.removeDocument?.(selected);
// TODO: nda - this is the code to actually get a new grouped collection
const newCollection = marqViewRef?.getCollection(selected, undefined, true);
@@ -774,13 +804,12 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
// TODO: nda - will probably need to go through and only remove the unprocessed selected docs
ffView.unprocessedDocs = [];
- InkTranscription.Instance.transcribeInk(newCollection, selected, false, ffView);
+ InkTranscription.Instance.transcribeInk(newCollection, selected, false);
});
}
CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
}
-
/** INK
* setActiveTool
* setStrokeWidth
@@ -790,10 +819,9 @@ export function createInkGroup(inksToGroup?: Doc[], isSubGroup?: boolean) {
ScriptingGlobals.add(function setActiveTool(tool: string, checkResult?: boolean) {
InkTranscription.Instance?.createInkGroup();
if (checkResult) {
- return ((CurrentUserUtils.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool) ?
- Colors.MEDIUM_BLUE : "transparent";
+ return (CurrentUserUtils.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool ? Colors.MEDIUM_BLUE : 'transparent';
}
- if (["circle", "square", "line"].includes(tool)) {
+ if (['circle', 'square', 'line'].includes(tool)) {
if (GestureOverlay.Instance.InkShape === tool) {
CurrentUserUtils.ActiveTool = InkTool.None;
GestureOverlay.Instance.InkShape = InkTool.None;
@@ -801,16 +829,17 @@ ScriptingGlobals.add(function setActiveTool(tool: string, checkResult?: boolean)
CurrentUserUtils.ActiveTool = InkTool.Pen;
GestureOverlay.Instance.InkShape = tool;
}
- } else if (tool) { // pen or eraser
+ } else if (tool) {
+ // pen or eraser
if (CurrentUserUtils.ActiveTool === tool && !GestureOverlay.Instance.InkShape) {
CurrentUserUtils.ActiveTool = InkTool.None;
} else if (tool == InkTool.Write) {
// console.log("write mode selected - create groupDoc here!", tool)
CurrentUserUtils.ActiveTool = tool;
- GestureOverlay.Instance.InkShape = "";
+ GestureOverlay.Instance.InkShape = '';
} else {
CurrentUserUtils.ActiveTool = tool as any;
- GestureOverlay.Instance.InkShape = "";
+ GestureOverlay.Instance.InkShape = '';
}
} else {
CurrentUserUtils.ActiveTool = InkTool.None;
@@ -827,7 +856,9 @@ ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean
return ActiveFillColor();
}
SetActiveFillColor(StrCast(color));
- SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.fillColor = color);
+ SelectionManager.Docs()
+ .filter(doc => doc.type === DocumentType.INK)
+ .map(doc => (doc.fillColor = color));
});
ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolean) {
@@ -839,7 +870,9 @@ ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolea
return ActiveInkWidth();
}
SetActiveInkWidth(width.toString());
- SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.strokeWidth = Number(width));
+ SelectionManager.Docs()
+ .filter(doc => doc.type === DocumentType.INK)
+ .map(doc => (doc.strokeWidth = Number(width)));
});
// toggle: Set overlay status of selected document
@@ -852,10 +885,11 @@ ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boole
return ActiveInkColor();
}
SetActiveInkColor(StrCast(color));
- SelectionManager.Docs().filter(doc => doc.type === DocumentType.INK).map(doc => doc.color = String(color));
+ SelectionManager.Docs()
+ .filter(doc => doc.type === DocumentType.INK)
+ .map(doc => (doc.color = String(color)));
});
-
/** WEB
* webSetURL
**/
@@ -870,21 +904,20 @@ ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) {
}
});
ScriptingGlobals.add(function webForward(checkResult?: boolean) {
- const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
+ const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
if (checkResult) {
- return selected?.forward(checkResult) ? undefined : "lightGray";
+ return selected?.forward(checkResult) ? undefined : 'lightGray';
}
selected?.forward();
});
ScriptingGlobals.add(function webBack(checkResult?: boolean) {
- const selected = (SelectionManager.Views().lastElement()?.ComponentView as WebBox);
+ const selected = SelectionManager.Views().lastElement()?.ComponentView as WebBox;
if (checkResult) {
- return selected?.back(checkResult) ? undefined : "lightGray";
+ return selected?.back(checkResult) ? undefined : 'lightGray';
}
selected?.back();
});
-
/** Schema
* toggleSchemaPreview
**/
@@ -893,9 +926,8 @@ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
if (checkResult && selected) {
const result: boolean = NumCast(selected.schemaPreviewWidth) > 0;
if (result) return Colors.MEDIUM_BLUE;
- else return "transparent";
- }
- else if (selected) {
+ else return 'transparent';
+ } else if (selected) {
if (NumCast(selected.schemaPreviewWidth) > 0) {
selected.schemaPreviewWidth = 0;
} else {
@@ -908,11 +940,11 @@ ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) {
* groupBy
*/
ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) {
- SelectionManager.Docs().map(doc => doc._fontFamily = key);
+ SelectionManager.Docs().map(doc => (doc._fontFamily = key));
const editorView = RichTextMenu.Instance.TextView?.EditorView;
if (checkResult) {
return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
}
if (editorView) RichTextMenu.Instance.setFontFamily(key);
else Doc.UserDoc().fontFamily = key;
-}); \ No newline at end of file
+});