From b1376d401e709515cee078cc08b05fd3fb89caeb Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 24 Apr 2024 18:12:30 -0400 Subject: completing eslint pass --- src/client/apis/GoogleAuthenticationManager.tsx | 119 ++++++------ .../apis/google_docs/GooglePhotosClientUtils.ts | 2 +- src/client/documents/Documents.ts | 37 ++-- src/client/util/CalendarManager.tsx | 5 +- src/client/util/CaptureManager.tsx | 17 +- src/client/util/CurrentUserUtils.ts | 24 +-- src/client/util/DictationManager.ts | 63 ++++--- src/client/util/GroupMemberView.tsx | 32 ++-- src/client/util/History.ts | 34 ++-- .../util/Import & Export/ImportMetadataEntry.tsx | 40 ++-- src/client/util/KeyCodes.ts | 2 +- src/client/util/LinkFollower.ts | 2 +- src/client/util/PingManager.ts | 6 +- src/client/util/RTFMarkup.tsx | 25 +-- src/client/util/ReplayMovements.ts | 22 +-- src/client/util/ScriptManager.ts | 10 +- src/client/util/Scripting.ts | 4 +- src/client/util/SelectionManager.ts | 16 +- src/client/util/ServerStats.tsx | 45 +++-- src/client/util/SharingManager.tsx | 5 +- src/client/util/TrackMovements.ts | 24 +-- src/client/util/Transform.ts | 14 +- src/client/util/TypedEvent.ts | 18 +- src/client/util/bezierFit.ts | 6 +- .../util/reportManager/ReportManagerComponents.tsx | 131 +++++++------ .../util/reportManager/reportManagerSchema.ts | 1 + .../util/reportManager/reportManagerUtils.ts | 17 +- src/client/views/animationtimeline/Timeline.tsx | 60 +++--- .../views/animationtimeline/TimelineOverview.tsx | 16 +- .../views/collections/CollectionCalendarView.tsx | 30 ++- .../views/collections/CollectionCarouselView.tsx | 7 +- .../views/collections/CollectionDockingView.tsx | 6 +- .../collections/CollectionNoteTakingViewColumn.tsx | 39 ++-- .../CollectionNoteTakingViewDivider.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 6 +- .../views/collections/CollectionTreeView.tsx | 21 +-- src/client/views/collections/KeyRestrictionRow.tsx | 32 +++- .../CollectionFreeFormBackgroundGrid.tsx | 1 + .../CollectionFreeFormInfoState.tsx | 31 ++-- .../CollectionFreeFormLayoutEngines.tsx | 8 +- .../CollectionFreeFormRemoteCursors.tsx | 72 ++++---- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 12 +- .../collectionGrid/CollectionGridView.tsx | 52 ++++-- .../collectionLinear/CollectionLinearView.tsx | 3 +- .../views/collections/collectionLinear/index.ts | 2 +- .../CollectionMulticolumnView.tsx | 57 ++++-- .../CollectionMultirowView.tsx | 24 ++- .../collectionMulticolumn/MulticolumnResizer.tsx | 24 +-- .../MulticolumnWidthLabel.tsx | 2 +- .../collectionMulticolumn/MultirowHeightLabel.tsx | 3 +- .../collectionMulticolumn/MultirowResizer.tsx | 26 +-- .../collectionSchema/SchemaColumnHeader.tsx | 18 +- .../collections/collectionSchema/SchemaRowBox.tsx | 23 +-- src/client/views/global/globalEnums.tsx | 52 +++--- src/client/views/linking/LinkMenuGroup.tsx | 27 ++- src/client/views/linking/LinkMenuItem.tsx | 10 +- .../views/linking/LinkRelationshipSearch.tsx | 63 ------- src/client/views/nodes/AudioBox.tsx | 11 +- .../views/nodes/DataVizBox/SchemaCSVPopUp.tsx | 62 +++---- .../views/nodes/DataVizBox/components/PieChart.tsx | 197 ++++++++++---------- src/client/views/nodes/DataVizBox/utils/D3Utils.ts | 29 +-- src/client/views/nodes/DocumentLinksButton.tsx | 6 +- src/client/views/nodes/EquationBox.tsx | 11 +- src/client/views/nodes/FaceRectangle.tsx | 10 +- .../views/nodes/FontIconBox/ButtonInterface.ts | 2 +- src/client/views/nodes/FontIconBox/TrailsIcon.tsx | 86 ++++----- src/client/views/nodes/LinkAnchorBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 83 +++++---- src/client/views/nodes/LinkDescriptionPopup.tsx | 33 ++-- src/client/views/nodes/LinkDocPreview.tsx | 64 ++++--- src/client/views/nodes/LoadingBox.tsx | 4 +- .../views/nodes/MapBox/AnimationSpeedIcons.tsx | 39 ++-- src/client/views/nodes/MapBox/AnimationUtility.ts | 57 +++--- .../views/nodes/MapBox/DirectionsAnchorMenu.tsx | 11 +- src/client/views/nodes/MapBox/GeocoderControl.tsx | 7 +- src/client/views/nodes/MapBox/MapAnchorMenu.tsx | 99 +++++----- src/client/views/nodes/MapBox/MapboxApiUtility.ts | 76 ++++---- src/client/views/nodes/MapBox/MarkerIcons.tsx | 3 +- .../views/nodes/MapboxMapBox/MapboxContainer.tsx | 28 +-- src/client/views/nodes/RadialMenu.tsx | 140 +++++--------- src/client/views/nodes/RadialMenuItem.tsx | 4 +- .../views/nodes/RecordingBox/ProgressBar.tsx | 205 +++++++++++---------- .../views/nodes/RecordingBox/RecordingBox.tsx | 17 +- .../views/nodes/RecordingBox/RecordingView.tsx | 41 ++--- src/client/views/nodes/RecordingBox/index.ts | 4 +- src/client/views/nodes/ScriptingBox.tsx | 162 ++++++++-------- src/client/views/nodes/SliderBox-components.tsx | 114 ++++++------ src/client/views/nodes/VideoBox.tsx | 42 +++-- src/client/views/nodes/audio/AudioWaveform.tsx | 8 +- src/client/views/nodes/audio/WaveCanvas.tsx | 12 +- src/client/views/nodes/calendarBox/CalendarBox.tsx | 7 +- .../nodes/formattedText/DashDocCommentView.tsx | 159 ++++++++-------- .../views/nodes/formattedText/DashDocView.tsx | 123 +++++++------ .../views/nodes/formattedText/EquationEditor.tsx | 3 +- .../views/nodes/formattedText/EquationView.tsx | 93 +++++----- .../views/nodes/formattedText/FootnoteView.tsx | 8 +- .../formattedText/FormattedTextBoxComment.tsx | 24 ++- .../views/nodes/formattedText/OrderedListView.tsx | 9 +- .../views/nodes/formattedText/ParagraphNodeSpec.ts | 101 +++++----- .../views/nodes/formattedText/RichTextRules.ts | 15 +- .../views/nodes/formattedText/SummaryView.tsx | 24 +-- .../views/nodes/generativeFill/GenerativeFill.tsx | 21 ++- .../nodes/generativeFill/GenerativeFillButtons.tsx | 10 +- .../GenerativeFillMathHelpers.ts | 8 +- .../generativeFillUtils/ImageHandler.ts | 36 ++-- .../generativeFillUtils/PointerHandler.ts | 18 +- .../views/nodes/importBox/ImportElementBox.tsx | 3 +- src/client/views/nodes/trails/index.ts | 6 +- src/client/views/pdf/AnchorMenu.tsx | 14 +- src/mobile/ImageUpload.tsx | 3 +- 110 files changed, 1913 insertions(+), 1891 deletions(-) delete mode 100644 src/client/views/linking/LinkRelationshipSearch.tsx (limited to 'src') diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index 855f48f7e..5269f763b 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -1,14 +1,14 @@ -import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; -import { observer } from "mobx-react"; -import * as React from "react"; -import { Opt } from "../../fields/Doc"; -import { Networking } from "../Network"; -import { ScriptingGlobals } from "../util/ScriptingGlobals"; -import { MainViewModal } from "../views/MainViewModal"; -import "./GoogleAuthenticationManager.scss"; +import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Opt } from '../../fields/Doc'; +import { Networking } from '../Network'; +import { ScriptingGlobals } from '../util/ScriptingGlobals'; +import { MainViewModal } from '../views/MainViewModal'; +import './GoogleAuthenticationManager.scss'; -const AuthenticationUrl = "https://accounts.google.com/o/oauth2/v2/auth"; -const prompt = "Paste authorization code here..."; +const AuthenticationUrl = 'https://accounts.google.com/o/oauth2/v2/auth'; +const prompt = 'Paste authorization code here...'; @observer export class GoogleAuthenticationManager extends React.Component<{}> { @@ -23,11 +23,11 @@ export class GoogleAuthenticationManager extends React.Component<{}> { private disposer: Opt; private set isOpen(value: boolean) { - runInAction(() => this.openState = value); + runInAction(() => (this.openState = value)); } private set shouldShowPasteTarget(value: boolean) { - runInAction(() => this.showPasteTargetState = value); + runInAction(() => (this.showPasteTargetState = value)); } public cancel() { @@ -35,7 +35,7 @@ export class GoogleAuthenticationManager extends React.Component<{}> { } public fetchOrGenerateAccessToken = async (displayIfFound = false) => { - let response: any = await Networking.FetchFromServer("/readGoogleAccessToken"); + let response: any = await Networking.FetchFromServer('/readGoogleAccessToken'); // if this is an authentication url, activate the UI to register the new access token if (new RegExp(AuthenticationUrl).test(response)) { this.isOpen = true; @@ -47,7 +47,7 @@ export class GoogleAuthenticationManager extends React.Component<{}> { async authenticationCode => { if (authenticationCode && /\d{1}\/[\w-]{55}/.test(authenticationCode)) { this.disposer?.(); - const response = await Networking.PostToServer("/writeGoogleAccessToken", { authenticationCode }); + const response = await Networking.PostToServer('/writeGoogleAccessToken', { authenticationCode }); runInAction(() => { this.success = true; this.credentials = response; @@ -71,7 +71,7 @@ export class GoogleAuthenticationManager extends React.Component<{}> { this.isOpen = true; } return response.access_token; - } + }; resetState = action((visibleForMS: number = 3000, fadesOutInMS: number = 500) => { if (!visibleForMS && !fadesOutInMS) { @@ -89,14 +89,20 @@ export class GoogleAuthenticationManager extends React.Component<{}> { this.displayLauncher = false; this.shouldShowPasteTarget = false; if (visibleForMS > 0 && fadesOutInMS > 0) { - setTimeout(action(() => { - this.isOpen = false; - setTimeout(action(() => { - this.success = undefined; - this.displayLauncher = true; - this.credentials = undefined; - }), fadesOutInMS); - }), visibleForMS); + setTimeout( + action(() => { + this.isOpen = false; + setTimeout( + action(() => { + this.success = undefined; + this.displayLauncher = true; + this.credentials = undefined; + }), + fadesOutInMS + ); + }), + visibleForMS + ); } }); @@ -108,61 +114,44 @@ export class GoogleAuthenticationManager extends React.Component<{}> { private get renderPrompt() { return (
- - {this.displayLauncher ? : (null)} - {this.showPasteTargetState ? this.authenticationCode = e.currentTarget.value)} - placeholder={prompt} - /> : (null)} - {this.credentials ? + {this.displayLauncher ? ( + + ) : null} + {this.showPasteTargetState ? (this.authenticationCode = e.currentTarget.value))} placeholder={prompt} /> : null} + {this.credentials ? ( <> - - Welcome to Dash, {this.credentials.userInfo.name} - + + Welcome to Dash, {this.credentials.userInfo.name}
{ - await Networking.FetchFromServer("/revokeGoogleAccessToken"); + await Networking.FetchFromServer('/revokeGoogleAccessToken'); this.resetState(0, 0); - }} - >Disconnect Account
- : (null)} + }}> + Disconnect Account +
+ + ) : null} ); } private get dialogueBoxStyle() { - const borderColor = this.success === undefined ? "black" : this.success ? "green" : "red"; - return { borderColor, transition: "0.2s borderColor ease", zIndex: 1002 }; + const borderColor = this.success === undefined ? 'black' : this.success ? 'green' : 'red'; + return { borderColor, transition: '0.2s borderColor ease', zIndex: 1002 }; } render() { - return ( - this.isOpen = false)} - /> - ); + return (this.isOpen = false))} />; } - } -ScriptingGlobals.add("GoogleAuthenticationManager", GoogleAuthenticationManager); \ No newline at end of file +ScriptingGlobals.add('GoogleAuthenticationManager', GoogleAuthenticationManager); diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 07a2708ec..1eb977813 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -291,7 +291,7 @@ export namespace GooglePhotos { response.results.map( item => new Promise(resolve => { - Query.GetImage(item.mediaItem.id).then(item => resolve(item.baseUrl)); + Query.GetImage(item.mediaItem.id).then(itm => resolve(itm.baseUrl)); }) ) ); diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f827ea81c..cf397e85a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,9 +1,13 @@ +/* eslint-disable prefer-destructuring */ +/* eslint-disable default-param-last */ +/* eslint-disable no-use-before-define */ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { saveAs } from 'file-saver'; import * as JSZip from 'jszip'; import { action, reaction, runInAction } from 'mobx'; import { basename } from 'path'; import { ClientUtils, OmitKeys } from '../../ClientUtils'; +// eslint-disable-next-line import/extensions import * as JSZipUtils from '../../JSZipUtils'; import { decycle } from '../../decycler/decycler'; import { DateField } from '../../fields/DateField'; @@ -81,6 +85,7 @@ export enum FInfoFieldType { string = 'string', boolean = 'boolean', number = 'number', + // eslint-disable-next-line @typescript-eslint/no-shadow Doc = 'Doc', enumeration = 'enum', date = 'date', @@ -1360,9 +1365,9 @@ export namespace DocUtils { if (key === LinkedTo) { // links are not a field value, so handled here. value is an expression of form ([field=]idToDoc("...")) const allLinks = LinkManager.Instance.getAllRelatedLinks(doc); - const matchLink = (value: string, anchor: Doc) => { - const linkedToExp = (value ?? '').split('='); - if (linkedToExp.length === 1) return Field.toScriptString(anchor) === value; + const matchLink = (val: string, anchor: Doc) => { + const linkedToExp = (val ?? '').split('='); + if (linkedToExp.length === 1) return Field.toScriptString(anchor) === val; return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1]; }; // prettier-ignore @@ -1493,17 +1498,17 @@ export namespace DocUtils { if (!linkSettings.link_relationship) linkSettings.link_relationship = target.type === DocumentType.RTF ? 'Commentary:Comments On' : 'link'; if (target.doc === Doc.UserDoc()) return undefined; - const makeLink = action((linkDoc: Doc, showPopup?: number[]) => { - if (showPopup) { + const makeLink = action((linkDoc: Doc, showAt?: number[]) => { + if (showAt) { LinkManager.Instance.currentLink = linkDoc; TaskCompletionBox.textDisplayed = 'Link Created'; - TaskCompletionBox.popupX = showPopup[0]; - TaskCompletionBox.popupY = showPopup[1] - 33; + TaskCompletionBox.popupX = showAt[0]; + TaskCompletionBox.popupY = showAt[1] - 33; TaskCompletionBox.taskCompleted = true; - LinkDescriptionPopup.Instance.popupX = showPopup[0]; - LinkDescriptionPopup.Instance.popupY = showPopup[1]; + LinkDescriptionPopup.Instance.popupX = showAt[0]; + LinkDescriptionPopup.Instance.popupY = showAt[1]; LinkDescriptionPopup.Instance.display = true; const rect = document.body.getBoundingClientRect(); @@ -1811,7 +1816,7 @@ export namespace DocUtils { batch.end(); return doc; } - export function findTemplate(templateName: string, type: string, signature: string) { + export function findTemplate(templateName: string, type: string) { let docLayoutTemplate: Opt; const iconViews = DocListCast(Cast(Doc.UserDoc().template_icons, Doc, null)?.data); const templBtns = DocListCast(Cast(Doc.UserDoc().template_buttons, Doc, null)?.data); @@ -1841,7 +1846,7 @@ export namespace DocUtils { const templateName = templateSignature.replace(/\(.*\)/, ''); doc.layout_fieldKey = 'layout_' + (templateSignature || (docLayoutTemplate?.title ?? '')); // eslint-disable-next-line no-param-reassign - docLayoutTemplate = docLayoutTemplate || findTemplate(templateName, StrCast(doc.isGroup && doc.transcription ? 'transcription' : doc.type), templateSignature); + docLayoutTemplate = docLayoutTemplate || findTemplate(templateName, StrCast(doc.isGroup && doc.transcription ? 'transcription' : doc.type)); const customName = 'layout_' + templateSignature; const _width = NumCast(doc._width); @@ -2166,12 +2171,16 @@ export namespace DocUtils { const docs: { [id: string]: any } = {}; const links: { [id: string]: any } = {}; - Array.from(map.entries()).forEach(f => (docs[f[0]] = f[1])); - Array.from(linkMap.entries()).forEach(l => (links[l[0]] = l[1])); + Array.from(map.entries()).forEach(f => { + docs[f[0]] = f[1]; + }); + Array.from(linkMap.entries()).forEach(l => { + links[l[0]] = l[1]; + }); const jsonDocs = JSON.stringify({ id: clone[Id], docs, links }, decycle(replacer)); const zip = new JSZip(); - var count = 0; + let count = 0; const promArr = Array.from(proms) .filter(url => url?.startsWith('/files')) .map(url => url.replace('/', '')); // window.location.origin)); diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx index 46aa4d238..8e3936d34 100644 --- a/src/client/util/CalendarManager.tsx +++ b/src/client/util/CalendarManager.tsx @@ -54,7 +54,6 @@ export class CalendarManager extends ObservableReactComponent<{}> { @observable private targetDoc: Doc | undefined = undefined; // the target document @observable private targetDocView: DocumentView | undefined = undefined; // the DocumentView of the target doc @observable private dialogueBoxOpacity = 1; // for the modal - @observable private overlayOpacity = 0.4; // for the modal @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used @@ -205,14 +204,12 @@ export class CalendarManager extends ObservableReactComponent<{}> { if (docs.length) { docs.forEach(doc => doc && Doc.BrushDoc(doc)); this.dialogueBoxOpacity = 0.1; - this.overlayOpacity = 0.1; } })} onPointerLeave={action(() => { if (docs.length) { docs.forEach(doc => doc && Doc.UnBrushDoc(doc)); this.dialogueBoxOpacity = 1; - this.overlayOpacity = 0.4; } })}> {contents} @@ -352,6 +349,6 @@ export class CalendarManager extends ObservableReactComponent<{}> { } render() { - return ; + return ; } } diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx index 2939ba581..a03c80f2a 100644 --- a/src/client/util/CaptureManager.tsx +++ b/src/client/util/CaptureManager.tsx @@ -1,3 +1,5 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; @@ -13,18 +15,22 @@ import { SelectionManager } from './SelectionManager'; @observer export class CaptureManager extends React.Component<{}> { + // eslint-disable-next-line no-use-before-define public static Instance: CaptureManager; static _settingsStyle = addStyleSheet(); @observable _document: any = undefined; @observable isOpen: boolean = false; // whether the CaptureManager is to be displayed or not. + // eslint-disable-next-line react/sort-comp constructor(props: {}) { super(props); makeObservable(this); CaptureManager.Instance = this; } - public close = action(() => (this.isOpen = false)); + public close = action(() => { + this.isOpen = false; + }); public open = action((doc: Doc) => { this.isOpen = true; this._document = doc; @@ -99,15 +105,15 @@ export class CaptureManager extends React.Component<{}> {
-
+
Conversation Capture
-
+
{this.visibilityContent} {this.linksContent}
- +
{this.closeButtons}
@@ -119,11 +125,10 @@ export class CaptureManager extends React.Component<{}> { ); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index acbd0c0b9..65dce34a5 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -67,7 +67,7 @@ export class CurrentUserUtils { // initializes experimental advanced template views - slideView, headerView static setupUserDocumentCreatorButtons(doc: Doc, userDocTemplates: Opt) { - const userTemplates = DocListCast(userDocTemplates?.data).filter(doc => !Doc.IsSystem(doc)); + const userTemplates = DocListCast(userDocTemplates?.data).filter(fdoc => !Doc.IsSystem(fdoc)); const reqdOpts:DocumentOptions = { title: "User Tools", _xMargin: 0, _layout_showTitle: "title", _chromeHidden: true, hidden: false, _dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true, @@ -87,7 +87,7 @@ export class CurrentUserUtils { { opts: { title: "Open Detail On Right", targetScriptKey: "onChildDoubleClick"}, script: `openDoc(this.doubleClickView.${OpenWhere.addRight})`}]; const reqdClickList = reqdTempOpts.map(opts => { const allOpts = {...reqdClickOpts, ...opts.opts}; - const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(doc => doc.title === opts.opts.title): undefined; + const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(fdoc => fdoc.title === opts.opts.title): undefined; return DocUtils.AssignOpts(clickDoc, allOpts) ?? Docs.Create.ScriptingDocument(ScriptField.MakeScript(opts.script, allOpts),allOpts); }); @@ -110,7 +110,7 @@ export class CurrentUserUtils { const reqdClickList = reqdTempOpts.map(opts => { const title = opts.opts.title?.toString(); const allOpts = {...reqdClickOpts, ...opts.opts}; - const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(doc => doc.title === title): undefined; + const clickDoc = tempClicks ? DocListCast(tempClicks.data).find(fdoc => fdoc.title === title): undefined; const script = ScriptField.MakeScript(opts.script, {heading:Doc.name, checked:"boolean", containingTreeView:Doc.name}); const scriptDoc = Docs.Create.ScriptingDocument(script, allOpts, title) return DocUtils.AssignOpts(clickDoc, allOpts) ?? MakeTemplate(scriptDoc); @@ -130,7 +130,7 @@ export class CurrentUserUtils { { title: "Topic", backgroundColor: "lightblue", icon: "book-open" , _layout_showTitle: "title"}]; const reqdNoteList = [...reqdTempOpts.map(opts => { const reqdOpts = {...opts, isSystem:true, width:200, layout_autoHeight: true, layout_fitWidth: true}; - const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(doc => doc.title === opts.title): undefined; + const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(fdoc => fdoc.title === opts.title): undefined; return DocUtils.AssignOpts(noteTemp, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts)); }), ... DocListCast(tempNotes?.data).filter(note => !reqdTempOpts.find(reqd => reqd.title === note.title))]; @@ -249,7 +249,7 @@ export class CurrentUserUtils { Docs.Create.TextDocument("", { title: "text", _layout_fitWidth:true, _height: 100, isSystem: true, _text_fontFamily: StrCast(Doc.UserDoc().fontFamily), _text_fontSize: StrCast(Doc.UserDoc().fontSize) }) ], {...opts, title: "Slide View Template"})); const plotlyApi = () => { - let plotly = Doc.MyPublishedDocs.find(doc => doc.title === "@plotly"); + let plotly = Doc.MyPublishedDocs.find(fdoc => fdoc.title === "@plotly"); if (!plotly) { plotly = Docs.Create.TextDocument( `await import("https://cdn.plot.ly/plotly-2.27.0.min.js"); @@ -289,7 +289,7 @@ export class CurrentUserUtils { return slide; } const mermaidsApi = () => { - let mermaids = Doc.MyPublishedDocs.find(doc => doc.title === "@mermaids"); + let mermaids = Doc.MyPublishedDocs.find(fdoc => fdoc.title === "@mermaids"); if (!mermaids) { mermaids = Docs.Create.TextDocument( `const mdef = (await import("https://cdn.jsdelivr.net/npm/mermaid@10.8.0/dist/mermaid.esm.min.mjs")).default; @@ -416,7 +416,7 @@ pie title Minerals in my tap water /// Initalizes the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc, dragCreatorDoc?:Doc):Doc { const creatorBtns = CurrentUserUtils.creatorBtnDescriptors(doc).map((reqdOpts) => { - const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(doc => doc.title === reqdOpts.title): undefined; + const btn = dragCreatorDoc ? DocListCast(dragCreatorDoc.data).find(fdoc => fdoc.title === reqdOpts.title): undefined; const opts:DocumentOptions = {...OmitKeys(reqdOpts, ["funcs", "scripts", "backgroundColor"]).omit, _width: 60, _height: 60, _dragOnlyWithinContainer: true, btnType: ButtonType.ToolButton, backgroundColor: reqdOpts.backgroundColor ?? Colors.DARK_GRAY, color: Colors.WHITE, isSystem: true, @@ -460,7 +460,7 @@ pie title Minerals in my tap water this.setupLeftSidebarPanel(doc); const myLeftSidebarMenu = DocCast(doc[field]); const menuBtns = CurrentUserUtils.leftSidebarMenuBtnDescriptions(doc).map(({ title, target, icon, toolTip, hidden, scripts, funcs }) => { - const btnDoc = myLeftSidebarMenu ? DocListCast(myLeftSidebarMenu.data).find(doc => doc.title === title) : undefined; + const btnDoc = myLeftSidebarMenu ? DocListCast(myLeftSidebarMenu.data).find(fdoc => fdoc.title === title) : undefined; const reqdBtnOpts:DocumentOptions = { title, icon, target, toolTip, hidden, btnType: ButtonType.MenuButton, isSystem: true, undoIgnoreFields: new List(['height', 'data_columnHeaders']), dontRegisterView: true, _width: 60, _height: 60, _dragOnlyWithinContainer: true, @@ -614,7 +614,7 @@ pie title Minerals in my tap water static setupDockedButtons(doc: Doc, field="myDockedBtns") { const dockedBtns = DocCast(doc[field]); const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string|undefined}, funcs?: {[key:string]:string}) => - DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(doc => doc.title === opts.title), opts) ?? + DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(fdoc => fdoc.title === opts.title), opts) ?? CurrentUserUtils.createToolButton(opts), scripts, funcs); const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet @@ -780,7 +780,7 @@ pie title Minerals in my tap water childDontRegisterViews: true, flexGap: 0, _height: 30, ignoreClick: !params.scripts?.onClick, linearView_SubMenu: true, linearView_Expandable: true, embedContainer: menuDoc}; - const items = (menuBtnDoc?:Doc) => !menuBtnDoc ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menuBtnDoc) ); + const items = (menutBtn?:Doc) => !menutBtn ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menutBtn) ); const creator = params.btnType === ButtonType.MultiToggleButton ? this.multiToggleList : this.linearButtonList; const btnDoc = DocUtils.AssignScripts( DocUtils.AssignDocField(menuDoc, StrCast(params.title), (opts) => creator(opts, items(menuBtnDoc)), reqdSubMenuOpts, items(menuBtnDoc)), params.scripts, params.funcs); @@ -802,7 +802,7 @@ pie title Minerals in my tap water Doc.UserDoc().workspaceReplayingState = undefined; const dockedBtns = DocCast(doc[field]); const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string|undefined}, funcs?: {[key:string]:any}) => - DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(doc => doc.title === opts.title), opts) ?? + DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(fdoc => fdoc.title === opts.title), opts) ?? CurrentUserUtils.createToolButton(opts), scripts, funcs); const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet @@ -964,7 +964,7 @@ pie title Minerals in my tap water case FInfoFieldType.Doc: opts.fieldValues = new List(options.values as any); break; default: opts.fieldValues = new List(options.values as any); break;// string, pointerEvents, dimUnit, dropActionType } - DocUtils.AssignDocField(infos, pair[0], opts => Doc.assign(new Doc(), OmitKeys(opts,["values"]).omit), opts); + DocUtils.AssignDocField(infos, pair[0], docOpts => Doc.assign(new Doc(), OmitKeys(docOpts,["values"]).omit), opts); } }); } diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 207d3ea0b..08fd80882 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-use-before-define */ import * as interpreter from 'words-to-numbers'; // @ts-ignore bcz: how are you supposed to include these definitions since dom-speech-recognition isn't a module? import type {} from '@types/dom-speech-recognition'; @@ -6,7 +7,7 @@ import { Doc, Opt } from '../../fields/Doc'; import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; import { listSpec } from '../../fields/Schema'; -import { Cast, CastCtor, DocCast } from '../../fields/Types'; +import { Cast, CastCtor } from '../../fields/Types'; import { AudioField, ImageField } from '../../fields/URLField'; import { DocumentType } from '../documents/DocumentTypes'; import { Docs } from '../documents/Documents'; @@ -14,6 +15,7 @@ import { DictationOverlay } from '../views/DictationOverlay'; import { DocumentView, OpenWhere } from '../views/nodes/DocumentView'; import { SelectionManager } from './SelectionManager'; import { UndoManager } from './UndoManager'; +import { DocData } from '../../fields/DocSymbols'; /** * This namespace provides a singleton instance of a manager that @@ -64,9 +66,10 @@ export namespace DictationManager { export let isListening = false; let isManuallyStopped = false; - let current: string | undefined = undefined; + let current: string | undefined; let sessionResults: string[] = []; + // eslint-disable-next-line new-cap const recognizer: Opt = webkitSpeechRecognition ? new webkitSpeechRecognition() : undefined; export type InterimResultHandler = (results: string) => any; @@ -87,7 +90,7 @@ export namespace DictationManager { let pendingListen: Promise | string | undefined; export const listen = async (options?: Partial) => { - if (pendingListen instanceof Promise) return pendingListen.then(pl => innerListen(options)); + if (pendingListen instanceof Promise) return pendingListen.then(() => innerListen(options)); return innerListen(options); }; const innerListen = async (options?: Partial) => { @@ -150,29 +153,29 @@ export namespace DictationManager { recognizer.start(); - return new Promise((resolve, reject) => { + return new Promise(resolve => { recognizer.onerror = (e: any) => { // e is SpeechRecognitionError but where is that defined? if (!(indefinite && e.error === 'no-speech')) { recognizer.stop(); resolve(e); - //reject(e); } }; recognizer.onresult = (e: SpeechRecognitionEvent) => { current = synthesize(e, intra); - let matchedTerminator: string | undefined; - if (options?.terminators && (matchedTerminator = options.terminators.find(end => (current ? current.trim().toLowerCase().endsWith(end.toLowerCase()) : false)))) { + const matchedTerminator = options?.terminators?.find(end => (current ? current.trim().toLowerCase().endsWith(end.toLowerCase()) : false)); + if (options?.terminators && matchedTerminator) { current = matchedTerminator; recognizer.abort(); return complete(); } !isManuallyStopped && handler?.(current); - //isManuallyStopped && complete(); + // isManuallyStopped && complete() + return undefined; }; - recognizer.onend = (e: Event) => { + recognizer.onend = () => { if (!indefinite || isManuallyStopped) { return complete(); } @@ -182,6 +185,7 @@ export namespace DictationManager { current = undefined; } recognizer.start(); + return undefined; }; const complete = () => { @@ -202,7 +206,7 @@ export namespace DictationManager { }); }; - export const stop = (salvageSession = true) => { + export const stop = (/* salvageSession = true */) => { if (!isListening || !recognizer) { return; } @@ -212,7 +216,7 @@ export namespace DictationManager { }; const synthesize = (e: SpeechRecognitionEvent, delimiter?: string) => { - const results = e.results; + const { results } = e; const transcripts: string[] = []; for (let i = 0; i < results.length; i++) { transcripts.push(results.item(i).item(0).transcript.trim()); @@ -233,22 +237,25 @@ export namespace DictationManager { export const RegisterIndependent = (key: string, value: IndependentEntry) => Independent.set(key, value); export const RegisterDependent = (entry: DependentEntry) => Dependent.push(entry); - export const execute = async (phrase: string) => { - return UndoManager.RunInBatch(async () => { + export const execute = async (phrase: string) => + UndoManager.RunInBatch(async () => { console.log('PHRASE: ' + phrase); const targets = SelectionManager.Views; if (!targets || !targets.length) { - return; + return undefined; } + // eslint-disable-next-line no-param-reassign phrase = phrase.toLowerCase(); const entry = Independent.get(phrase); if (entry) { let success = false; - const restrictTo = entry.restrictTo; + const { restrictTo } = entry; + // eslint-disable-next-line no-restricted-syntax for (const target of targets) { if (!restrictTo || validate(target, restrictTo)) { + // eslint-disable-next-line no-await-in-loop await entry.action(target); success = true; } @@ -256,16 +263,19 @@ export namespace DictationManager { return success; } - for (const entry of Dependent) { - const regex = entry.expression; + // eslint-disable-next-line no-restricted-syntax + for (const depEntry of Dependent) { + const regex = depEntry.expression; const matches = regex.exec(phrase); regex.lastIndex = 0; if (matches !== null) { let success = false; - const restrictTo = entry.restrictTo; + const { restrictTo } = depEntry; + // eslint-disable-next-line no-restricted-syntax for (const target of targets) { if (!restrictTo || validate(target, restrictTo)) { - await entry.action(target, matches); + // eslint-disable-next-line no-await-in-loop + await depEntry.action(target, matches); success = true; } } @@ -275,7 +285,6 @@ export namespace DictationManager { return false; }, 'Execute Command'); - }; const ConstructorMap = new Map([ [DocumentType.COL, listSpec(Doc)], @@ -294,6 +303,7 @@ export namespace DictationManager { }; const validate = (target: DocumentView, types: DocumentType[]) => { + // eslint-disable-next-line no-restricted-syntax for (const type of types) { if (tryCast(target, type)) { return true; @@ -318,7 +328,9 @@ export namespace DictationManager { [ 'clear', { - action: (target: DocumentView) => (Doc.GetProto(target.Document).data = new List()), + action: (target: DocumentView) => { + Doc.GetProto(target.Document).data = new List(); + }, restrictTo: [DocumentType.COL], }, ], @@ -328,7 +340,7 @@ export namespace DictationManager { { action: (target: DocumentView) => { const newBox = Docs.Create.TextDocument('', { _width: 400, _height: 200, title: 'My Outline', _layout_autoHeight: true }); - const proto = DocCast(newBox.proto); + const proto = newBox[DocData]; const prompt = 'Press alt + r to start dictating here...'; const head = 3; const anchor = head + prompt.length; @@ -341,7 +353,7 @@ export namespace DictationManager { ], ]); - const Dependent = new Array( + const Dependent = [ { expression: /create (\w+) documents of type (image|nested collection)/g, action: (target: DocumentView, matches: RegExpExecArray) => { @@ -361,6 +373,7 @@ export namespace DictationManager { case 'nested collection': created = Docs.Create.FreeformDocument([], {}); break; + default: } created && Doc.AddDocToList(dataDoc, fieldKey, created); } @@ -375,7 +388,7 @@ export namespace DictationManager { mode && (target.Document._type_collection = mode); }, restrictTo: [DocumentType.COL], - } - ); + }, + ]; } } diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx index 894583711..c703c3f98 100644 --- a/src/client/util/GroupMemberView.tsx +++ b/src/client/util/GroupMemberView.tsx @@ -1,4 +1,7 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Button, IconButton, Size, Type } from 'browndash-components'; import { action, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; @@ -8,7 +11,6 @@ import { StrCast } from '../../fields/Types'; import { MainViewModal } from '../views/MainViewModal'; import { GroupManager, UserOptions } from './GroupManager'; import './GroupMemberView.scss'; -import { Button, IconButton, Size, Type } from 'browndash-components'; import { SettingsManager } from './SettingsManager'; interface GroupMemberViewProps { @@ -38,20 +40,23 @@ export class GroupMemberView extends React.Component { className="group-title" style={{ marginLeft: !hasEditAccess ? '-14%' : 0 }} value={StrCast(this.group.title || this.group.groupName)} - onChange={e => (this.group.title = e.currentTarget.value)} - disabled={!hasEditAccess}> -
-
{GroupManager.Instance.hasEditAccess(this.group) ? (
(this.onDataDoc = e.target.checked)} ref={this.checkRef} style={{ margin: '0 10px 0 15px' }} type="checkbox" title={'Add to Data Document?'} checked={this.onDataDoc} /> -
- ''} oneLine={true} /> + { + this.onDataDoc = e.target.checked; + }} + ref={this.checkRef} + style={{ margin: '0 10px 0 15px' }} + type="checkbox" + title="Add to Data Document?" + checked={this.onDataDoc} + /> +
+ ''} oneLine />
-
- ''} oneLine={true} /> +
+ ''} oneLine />
-
this.props.remove(this)} title={'Delete Entry'}> +
this.props.remove(this)} title="Delete Entry"> , sourceDoc: Doc, finished?: () => void, traverseBacklink?: boolean) { const getView = (doc: Doc) => DocumentManager.Instance.getFirstDocumentView(DocCast(doc.layout_unrendered ? doc.annotationOn : doc)); - const isAnchor = (sourceDoc: Doc, anchor: Doc) => Doc.AreProtosEqual(anchor, sourceDoc) || Doc.AreProtosEqual(anchor.annotationOn as Doc, sourceDoc); + const isAnchor = (source: Doc, anchor: Doc) => Doc.AreProtosEqual(anchor, source) || Doc.AreProtosEqual(anchor.annotationOn as Doc, source); const linkDocs = link ? [link] : LinkManager.Links(sourceDoc); const fwdLinks = linkDocs.filter(l => isAnchor(sourceDoc, l.link_anchor_1 as Doc)); // link docs where 'sourceDoc' is link_anchor_1 const backLinks = linkDocs.filter(l => isAnchor(sourceDoc, l.link_anchor_2 as Doc)); // link docs where 'sourceDoc' is link_anchor_2 diff --git a/src/client/util/PingManager.ts b/src/client/util/PingManager.ts index 7638e2ce0..e5e69c5ac 100644 --- a/src/client/util/PingManager.ts +++ b/src/client/util/PingManager.ts @@ -1,8 +1,10 @@ import { action, makeObservable, observable, runInAction } from 'mobx'; import { Networking } from '../Network'; import { CurrentUserUtils } from './CurrentUserUtils'; + export class PingManager { // create static instance and getter for global use + // eslint-disable-next-line no-use-before-define @observable static _instance: PingManager; @observable IsBeating = true; static get Instance(): PingManager { @@ -29,7 +31,9 @@ export class PingManager { sendPing = async (): Promise => { try { const res = await Networking.PostToServer('/ping', { date: new Date() }); - runInAction(() => (CurrentUserUtils.ServerVersion = res.message)); + runInAction(() => { + CurrentUserUtils.ServerVersion = res.message; + }); !this.IsBeating && this.setIsBeating(true); } catch { if (this.IsBeating) { diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx index 35b1579df..05fb849fd 100644 --- a/src/client/util/RTFMarkup.tsx +++ b/src/client/util/RTFMarkup.tsx @@ -6,23 +6,16 @@ import { SettingsManager } from './SettingsManager'; @observer export class RTFMarkup extends React.Component<{}> { + // eslint-disable-next-line no-use-before-define static Instance: RTFMarkup; @observable private isOpen = false; // whether the SharingManager modal is open or not - @action - public open = () => (this.isOpen = true); - - @action - public close = () => (this.isOpen = false); - constructor(props: {}) { super(props); makeObservable(this); RTFMarkup.Instance = this; } - @observable _stats: { [key: string]: any } | undefined = undefined; - /** * @returns the main interface of the SharingManager. */ @@ -30,11 +23,11 @@ export class RTFMarkup extends React.Component<{}> { return (

- {`(@wiki:phrase)`} + (@wiki:phrase) {` display wikipedia page for entered text (terminate with carriage return)`}

- {`(( any text ))`} + (( any text )) {` submit text to Chat GPT to have results appended afterward`}

@@ -129,13 +122,23 @@ export class RTFMarkup extends React.Component<{}> { ); } + @action + public open = () => { + this.isOpen = true; + }; + + @action + public close = () => { + this.isOpen = false; + }; + render() { return ( ); diff --git a/src/client/util/ReplayMovements.ts b/src/client/util/ReplayMovements.ts index b881f18b4..2c8fdf483 100644 --- a/src/client/util/ReplayMovements.ts +++ b/src/client/util/ReplayMovements.ts @@ -14,6 +14,7 @@ export class ReplayMovements { private isPlaying: boolean; // create static instance and getter for global use + // eslint-disable-next-line no-use-before-define @observable static _instance: ReplayMovements; static get Instance(): ReplayMovements { return ReplayMovements._instance; @@ -90,7 +91,7 @@ export class ReplayMovements { loadPresentation = (presentation: Presentation) => { const { movements } = presentation; if (movements === null) { - throw '[recordingApi.ts] followMovements() failed: no presentation data'; + throw new Error('[recordingApi.ts] followMovements() failed: no presentation data'); } movements.forEach((movement, i) => { @@ -106,9 +107,7 @@ export class ReplayMovements { // returns undefined if the docView isn't open on the screen getCollectionFFView = (doc: Doc) => { const isInView = DocumentManager.Instance.getDocumentView(doc); - if (isInView) { - return isInView.ComponentView as CollectionFreeFormView; - } + return isInView?.ComponentView as CollectionFreeFormView; }; // will open the doc in a tab then return the CollectionFFView that holds it @@ -136,9 +135,9 @@ export class ReplayMovements { if (movements === null) return new Map(); // generate a set of all unique docIds const docIdtoFirstMove = new Map(); - for (const move of movements) { + movements.forEach(move => { if (!docIdtoFirstMove.has(move.doc)) docIdtoFirstMove.set(move.doc, move); - } + }); return docIdtoFirstMove; }; @@ -151,10 +150,10 @@ export class ReplayMovements { // console.info('playMovements', presentation, timeViewed, docIdtoDoc); if (presentation.movements === null || presentation.movements.length === 0) { - //|| this.playFFView === null) { - return new Error('[recordingApi.ts] followMovements() failed: no presentation data'); + // || this.playFFView === null) { + return '[recordingApi.ts] followMovements() failed: no presentation data'; } - if (this.isPlaying) return; + if (this.isPlaying) return undefined; this.isPlaying = true; Doc.UserDoc().presentationMode = 'watching'; @@ -170,10 +169,10 @@ export class ReplayMovements { // for the open tabs, set it to the first move const docIdtoFirstMove = this.getFirstMovements(filteredMovements); - for (const [doc, firstMove] of docIdtoFirstMove) { + Array.from(docIdtoFirstMove).forEach(([doc, firstMove]) => { const colFFView = this.getCollectionFFView(doc); if (colFFView) this.zoomAndPan(firstMove, colFFView); - } + }); }; handleFirstMovements(); @@ -197,5 +196,6 @@ export class ReplayMovements { } }, timeDiff); }); + return undefined; }; } diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts index 87509f2ea..9158f6c0b 100644 --- a/src/client/util/ScriptManager.ts +++ b/src/client/util/ScriptManager.ts @@ -7,8 +7,10 @@ import { ScriptingGlobals } from './ScriptingGlobals'; export class ScriptManager { static _initialized = false; + // eslint-disable-next-line no-use-before-define private static _instance: ScriptManager; public static get Instance(): ScriptManager { + // eslint-disable-next-line no-return-assign return this._instance || (this._instance = new this()); } private constructor() { @@ -58,14 +60,16 @@ export class ScriptManager { const params = Cast(scriptDoc['data-params'], listSpec('string'), []); const paramNames = params.reduce((o: string, p: string) => { + let out = o; if (params.indexOf(p) === params.length - 1) { - o = o + p.split(':')[0].trim(); + out += p.split(':')[0].trim(); } else { - o = o + p.split(':')[0].trim() + ','; + out += p.split(':')[0].trim() + ','; } - return o; + return out; }, '' as string); + // eslint-disable-next-line no-new-func const f = new Function(paramNames, StrCast(scriptDoc.script)); Object.defineProperty(f, 'name', { value: StrCast(scriptDoc.name), writable: false }); diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index de5e8b92e..f7d7ba6a4 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -124,7 +124,7 @@ class ScriptingCompilerHost { return 'node_modules/typescript/lib/lib.d.ts'; // No idea what this means... } writeFile(fileName: string, content: string) { - const file = this.files.find(file => file.fileName === fileName); + const file = this.files.find(f => f.fileName === fileName); if (file) { file.content = content; } else { @@ -147,7 +147,7 @@ class ScriptingCompilerHost { return this.files.some(file => file.fileName === fileName); } readFile(fileName: string): string | undefined { - const file = this.files.find(file => file.fileName === fileName); + const file = this.files.find(f => f.fileName === fileName); if (file) { return file.content; } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 36b926053..1328e90e9 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -11,6 +11,7 @@ import { ScriptingGlobals } from './ScriptingGlobals'; import { UndoManager } from './UndoManager'; export class SelectionManager { + // eslint-disable-next-line no-use-before-define private static _manager: SelectionManager; private static get Instance() { return SelectionManager._manager ?? new SelectionManager(); @@ -61,7 +62,9 @@ export class SelectionManager { dv.IsSelected = false; dv._props.whenChildContentsActiveChanged(false); }); - runInAction(() => (this.Instance.SelectedViews.length = 0)); + runInAction(() => { + this.Instance.SelectedViews.length = 0; + }); if (found) this.SelectView(found, false); }; @@ -71,17 +74,20 @@ export class SelectionManager { public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore } +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function SelectionManager_selectedDocType(type: string, expertMode: boolean, checkContext?: boolean) { if (Doc.noviceMode && expertMode) return false; if (type === 'tab') { return SelectionManager.Views.lastElement()?._props.renderDepth === 0; } - let selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement()); + const selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(SelectionManager.SelectedSchemaDoc ?? SelectionManager.Docs.lastElement()); return selected?.type === type || selected?.type_collection === type || !type; }); +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function deselectAll() { SelectionManager.DeselectAll(); }); +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function undo() { SelectionManager.DeselectAll(); return UndoManager.Undo(); @@ -89,17 +95,19 @@ ScriptingGlobals.add(function undo() { export function ShowUndoStack() { SelectionManager.DeselectAll(); - var buffer = ''; + let buffer = ''; UndoManager.undoStack.forEach((batch, i) => { buffer += 'Batch => ' + UndoManager.undoStackNames[i] + '\n'; - ///batch.forEach(undo => (buffer += ' ' + undo.prop + '\n')); + // /batch.forEach(undo => (buffer += ' ' + undo.prop + '\n')); }); alert(buffer); } +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function redo() { SelectionManager.DeselectAll(); return UndoManager.Redo(); }); +// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) { const docs = SelectionManager.Views.map(dv => dv.Document).filter( d => !Doc.AreProtosEqual(d, container) && !d.annotationOn && d.type !== DocumentType.KVP && (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null)) diff --git a/src/client/util/ServerStats.tsx b/src/client/util/ServerStats.tsx index c8df9182d..891561245 100644 --- a/src/client/util/ServerStats.tsx +++ b/src/client/util/ServerStats.tsx @@ -1,44 +1,28 @@ -import { action, computed, makeObservable, observable } from 'mobx'; +import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { MainViewModal } from '../views/MainViewModal'; import './SharingManager.scss'; import { PingManager } from './PingManager'; -import { StrCast } from '../../fields/Types'; -import { Doc } from '../../fields/Doc'; import { SettingsManager } from './SettingsManager'; @observer export class ServerStats extends React.Component<{}> { + // eslint-disable-next-line no-use-before-define public static Instance: ServerStats; @observable private isOpen = false; // whether the SharingManager modal is open or not + @observable _stats: { [key: string]: any } | undefined = undefined; // private get linkVisible() { // return this.targetDoc ? this.targetDoc["acl-" + PublicKey] !== SharingPermissions.None : false; // } - @action - public open = async () => { - /** - * Populates the list of users. - */ - fetch('/stats').then((res: Response) => res.text().then(action(stats => (this._stats = JSON.parse(stats))))); - - this.isOpen = true; - }; - - public close = action(() => { - this.isOpen = false; - }); - constructor(props: {}) { super(props); makeObservable(this); ServerStats.Instance = this; } - @observable _stats: { [key: string]: any } | undefined = undefined; - /** * @returns the main interface of the SharingManager. */ @@ -63,7 +47,28 @@ export class ServerStats extends React.Component<{}> { ); } + // eslint-disable-next-line react/sort-comp + public close = action(() => { + this.isOpen = false; + }); + public open = async () => { + /** + * Populates the list of users. + */ + fetch('/stats').then((res: Response) => + res.text().then( + action(stats => { + this._stats = JSON.parse(stats); + }) + ) + ); + + runInAction(() => { + this.isOpen = true; + }); + }; + render() { - return ; + return ; } } diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 6676e4e03..5b4ac5aff 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -78,7 +78,6 @@ export class SharingManager extends React.Component<{}> { @observable private targetDocView: DocumentView | undefined = undefined; // the DocumentView of the document being shared // @observable private copied = false; @observable private dialogueBoxOpacity = 1; // for the modal - @observable private overlayOpacity = 0.4; // for the modal @observable private selectedUsers: UserOptions[] | null = null; // users (individuals/groups) selected to share with @observable private permissions: SharingPermissions = SharingPermissions.Edit; // the permission with which to share with other users @observable private individualSort: 'ascending' | 'descending' | 'none' = 'none'; // sorting options for the list of individuals @@ -661,14 +660,12 @@ export class SharingManager extends React.Component<{}> { if (docs.length) { docs.forEach(doc => doc && Doc.BrushDoc(doc)); this.dialogueBoxOpacity = 0.1; - this.overlayOpacity = 0.1; } })} onPointerLeave={action(() => { if (docs.length) { docs.forEach(doc => doc && Doc.UnBrushDoc(doc)); this.dialogueBoxOpacity = 1; - this.overlayOpacity = 0.4; } })}> {contents} @@ -742,6 +739,6 @@ export class SharingManager extends React.Component<{}> { } render() { - return ; + return ; } } diff --git a/src/client/util/TrackMovements.ts b/src/client/util/TrackMovements.ts index f9c2d522f..25a3c9ad8 100644 --- a/src/client/util/TrackMovements.ts +++ b/src/client/util/TrackMovements.ts @@ -1,8 +1,7 @@ -import { IReactionDisposer, makeObservable, observable, observe, reaction } from 'mobx'; +import { IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { NumCast } from '../../fields/Types'; import { Doc, DocListCast } from '../../fields/Doc'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { Id } from '../../fields/FieldSymbols'; import { CollectionViewType } from '../documents/DocumentTypes'; export type Movement = { @@ -33,6 +32,7 @@ export class TrackMovements { private tabChangeDisposeFunc: IReactionDisposer | null; // create static instance and getter for global use + // eslint-disable-next-line no-use-before-define @observable static _instance: TrackMovements; static get Instance(): TrackMovements { return TrackMovements._instance; @@ -92,12 +92,13 @@ export class TrackMovements { // so that the size comparisons are correct, we must filter to only the FFViews const isFFView = (doc: Doc) => doc && doc._type_collection === CollectionViewType.Freeform; const tabbedFFViews = new Set(); - for (const DashDoc of tabbedDocs) { + tabbedDocs.forEach(DashDoc => { if (isFFView(DashDoc)) tabbedFFViews.add(DashDoc); - } + }); // new tab was added - need to add it if (tabbedFFViews.size > this.recordingFFViews.size) { + // eslint-disable-next-line no-restricted-syntax for (const DashDoc of tabbedDocs) { if (!this.recordingFFViews.has(DashDoc)) { if (isFFView(DashDoc)) { @@ -111,6 +112,7 @@ export class TrackMovements { } // tab was removed - need to remove it from recordingFFViews else if (tabbedFFViews.size < this.recordingFFViews.size) { + // eslint-disable-next-line no-restricted-syntax for (const [doc] of this.recordingFFViews) { if (!tabbedFFViews.has(doc)) { this.removeRecordingFFView(doc); @@ -208,11 +210,11 @@ export class TrackMovements { return; } - for (const [id, disposeFunc] of this.recordingFFViews) { + Array.from(this.recordingFFViews).forEach(([id, disposeFunc]) => { // console.info('calling dispose func : docId', id); disposeFunc(); - this.recordingFFViews.delete(id); - } + this.recordingFFViews?.delete(id); + }); }; private trackMovement = (panX: number, panY: number, doc: Doc, scale: number = 0) => { @@ -241,9 +243,9 @@ export class TrackMovements { // method that concatenates an array of presentatations into one public concatPresentations = (presentations: Presentation[]): Presentation => { // these three will lead to the combined presentation - let combinedMovements: Movement[] = []; + const combinedMovements: Movement[] = []; let sumTime = 0; - let combinedMetas: any[] = []; + const combinedMetas: any[] = []; presentations.forEach(presentation => { const { movements, totalTime, meta } = presentation; @@ -251,9 +253,7 @@ export class TrackMovements { // update movements if they had one if (movements) { // add the summed time to the movements - const addedTimeMovements = movements.map(move => { - return { ...move, time: move.time + sumTime }; - }); + const addedTimeMovements = movements.map(move => ({ ...move, time: move.time + sumTime })); // concat the movements already in the combined presentation with these new ones combinedMovements.push(...addedTimeMovements); } diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts index dca37c960..1a07dd6ae 100644 --- a/src/client/util/Transform.ts +++ b/src/client/util/Transform.ts @@ -116,20 +116,14 @@ export class Transform { preTransformed = (transform: Transform): Transform => this.copy().preTransform(transform); - transformPoint = (x: number, y: number): [number, number] => { - x *= this._scale; - x += this._translateX; - y *= this._scale; - y += this._translateY; - return [x, y]; - }; + transformPoint = (x: number, y: number): [number, number] => [x * this._scale + this._translateX, y * this._scale + this._translateY]; transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale]; transformBounds(x: number, y: number, width: number, height: number): { x: number; y: number; width: number; height: number } { - [x, y] = this.transformPoint(x, y); - [width, height] = this.transformDirection(width, height); - return { x, y, width, height }; + const [tx, ty] = this.transformPoint(x, y); + const [twidth, theight] = this.transformDirection(width, height); + return { x: tx, y: ty, width: twidth, height: theight }; } inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale, -this._rotate); diff --git a/src/client/util/TypedEvent.ts b/src/client/util/TypedEvent.ts index 90fd299c1..9ef2aa8d7 100644 --- a/src/client/util/TypedEvent.ts +++ b/src/client/util/TypedEvent.ts @@ -14,27 +14,27 @@ export class TypedEvent { on = (listener: Listener): Disposable => { this.listeners.push(listener); return { - dispose: () => this.off(listener) + dispose: () => this.off(listener), }; - } + }; once = (listener: Listener): void => { this.listenersOncer.push(listener); - } + }; off = (listener: Listener) => { const callbackIndex = this.listeners.indexOf(listener); if (callbackIndex > -1) this.listeners.splice(callbackIndex, 1); - } + }; emit = (event: T) => { /** Update any general listeners */ - this.listeners.forEach((listener) => listener(event)); + this.listeners.forEach(listener => listener(event)); /** Clear the `once` queue */ - this.listenersOncer.forEach((listener) => listener(event)); + this.listenersOncer.forEach(listener => listener(event)); this.listenersOncer = []; - } + }; - pipe = (te: TypedEvent): Disposable => this.on((e) => te.emit(e)); -} \ No newline at end of file + pipe = (te: TypedEvent): Disposable => this.on(e => te.emit(e)); +} diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts index 6bbf55e5a..d6f3f2340 100644 --- a/src/client/util/bezierFit.ts +++ b/src/client/util/bezierFit.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-use-before-define */ /* eslint-disable prefer-destructuring */ /* eslint-disable no-param-reassign */ /* eslint-disable camelcase */ @@ -242,6 +243,7 @@ function splitCubic(p: Point[], t: number, left: Point[], right: Point[]) { * is robust: a near-tangential intersection will yield zero or two * intersections. */ +// eslint-disable-next-line @typescript-eslint/no-unused-vars function recursively_intersect(a: Point[], t0: number, t1: number, deptha: number, b: Point[], u0: number, u1: number, depthb: number, parameters: number[][]) { if (deptha > 0) { const a1 = new Array(4); @@ -538,8 +540,8 @@ function FitCubic(d: Point[], first: number, last: number, tHat1: Point, tHat2: for (let i = 0; i < maxIterations; i++) { const uPrime = ReparameterizeBezier(d, first, last, u, bezCurve); // Improved parameter values GenerateBezier(d, first, last, uPrime, tHat1, tHat2, bezCurve); - const { maxError } = ComputeMaxError(d, first, last, bezCurve, uPrime); - if (maxError < error) { + const { maxError: maximumError } = ComputeMaxError(d, first, last, bezCurve, uPrime); + if (maximumError < error) { result.push(bezCurve[1]); result.push(bezCurve[2]); result.push(bezCurve[3]); diff --git a/src/client/util/reportManager/ReportManagerComponents.tsx b/src/client/util/reportManager/ReportManagerComponents.tsx index 1e226bf6d..cecebc648 100644 --- a/src/client/util/reportManager/ReportManagerComponents.tsx +++ b/src/client/util/reportManager/ReportManagerComponents.tsx @@ -1,9 +1,15 @@ +/* eslint-disable react/require-default-props */ +/* eslint-disable prefer-destructuring */ +/* eslint-disable jsx-a11y/label-has-associated-control */ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable no-use-before-define */ import * as React from 'react'; -import { Issue } from './reportManagerSchema'; -import { darkColors, dashBlue, getLabelColors, isDarkMode, lightColors } from './reportManagerUtils'; import ReactMarkdown from 'react-markdown'; import rehypeRaw from 'rehype-raw'; import remarkGfm from 'remark-gfm'; +import { darkColors, dashBlue, getLabelColors, isDarkMode, lightColors } from './reportManagerUtils'; +import { Issue } from './reportManagerSchema'; import { StrCast } from '../../../fields/Types'; import { Doc } from '../../../fields/Doc'; @@ -18,7 +24,7 @@ interface FilterProps { } // filter ui for issues (horizontal list of tags) -export const Filter = ({ items, activeValue, setActiveValue }: FilterProps) => { +export function Filter({ items, activeValue, setActiveValue }: FilterProps) { // establishing theme const darkMode = isDarkMode(StrCast(Doc.UserDoc().userBackgroundColor)); const colors = darkMode ? darkColors : lightColors; @@ -28,7 +34,7 @@ export const Filter = ({ items, activeValue, setActiveValue }: return (

{ setActiveValue(null); }} @@ -38,25 +44,23 @@ export const Filter = ({ items, activeValue, setActiveValue }: borderColor={activeValue === null ? StrCast(Doc.UserDoc().userColor) : colors.border} border /> - {items.map(item => { - return ( - { - setActiveValue(item); - }} - fontSize="12px" - backgroundColor={activeValue === item ? StrCast(Doc.UserDoc().userColor) : 'transparent'} - color={activeValue === item ? activeTagTextColor : colors.textGrey} - border - borderColor={activeValue === item ? StrCast(Doc.UserDoc().userColor) : colors.border} - /> - ); - })} + {items.map(item => ( + { + setActiveValue(item); + }} + fontSize="12px" + backgroundColor={activeValue === item ? StrCast(Doc.UserDoc().userColor) : 'transparent'} + color={activeValue === item ? activeTagTextColor : colors.textGrey} + border + borderColor={activeValue === item ? StrCast(Doc.UserDoc().userColor) : colors.border} + /> + ))}
); -}; +} interface IssueCardProps { issue: Issue; @@ -64,7 +68,7 @@ interface IssueCardProps { } // Component for the issue cards list on the left -export const IssueCard = ({ issue, onSelect }: IssueCardProps) => { +export function IssueCard({ issue, onSelect }: IssueCardProps) { const [textColor, setTextColor] = React.useState(''); const [bgColor, setBgColor] = React.useState('transparent'); const [borderColor, setBorderColor] = React.useState('transparent'); @@ -103,14 +107,14 @@ export const IssueCard = ({ issue, onSelect }: IssueCardProps) => {

{issue.title}

); -}; +} interface IssueViewProps { issue: Issue; } // Detailed issue view that displays on the right -export const IssueView = ({ issue }: IssueViewProps) => { +export function IssueView({ issue }: IssueViewProps) { const [issueBody, setIssueBody] = React.useState(''); // Parses the issue body into a formatted markdown (main functionality is replacing urls with tags) @@ -127,15 +131,16 @@ export const IssueView = ({ issue }: IssueViewProps) => { parts.map(async part => { if (imgTagRegex.test(part) || videoTagRegex.test(part) || audioTagRegex.test(part)) { return `\n${await parseFileTag(part)}\n`; - } else if (fileRegex.test(part)) { + } + if (fileRegex.test(part)) { const tag = await parseDashFiles(part); return tag; - } else if (localRegex.test(part)) { + } + if (localRegex.test(part)) { const tag = await parseLocalFiles(part); return tag; - } else { - return part; } + return part; }) ); @@ -143,7 +148,7 @@ export const IssueView = ({ issue }: IssueViewProps) => { }; // Extracts the src from an image tag and either returns the raw url if not accessible or a new image tag - const parseFileTag = async (tag: string): Promise => { + const parseFileTag = async (tag: string): Promise => { const regex = /src="([^"]+)"/; let url = ''; const match = tag.match(regex); @@ -160,18 +165,19 @@ export const IssueView = ({ issue }: IssueViewProps) => { case '.png': case '.jpeg': case '.gif': - return await getDisplayedFile(url, 'image'); + return getDisplayedFile(url, 'image'); // video case '.mp4': case '.mpeg': case '.webm': case '.mov': - return await getDisplayedFile(url, 'video'); - //audio + return getDisplayedFile(url, 'video'); + // audio case '.mp3': case '.wav': case '.ogg': - return await getDisplayedFile(url, 'audio'); + return getDisplayedFile(url, 'audio'); + default: } return tag; }; @@ -183,14 +189,15 @@ export const IssueView = ({ issue }: IssueViewProps) => { const dashAudioRegex = /https:\/\/browndash\.com\/files[/\\]audio/; if (dashImgRegex.test(url)) { - return await getDisplayedFile(url, 'image'); - } else if (dashVideoRegex.test(url)) { - return await getDisplayedFile(url, 'video'); - } else if (dashAudioRegex.test(url)) { - return await getDisplayedFile(url, 'audio'); - } else { - return url; + return getDisplayedFile(url, 'image'); } + if (dashVideoRegex.test(url)) { + return getDisplayedFile(url, 'video'); + } + if (dashAudioRegex.test(url)) { + return getDisplayedFile(url, 'audio'); + } + return url; }; // Returns the corresponding HTML tag for a src url @@ -200,31 +207,37 @@ export const IssueView = ({ issue }: IssueViewProps) => { const dashAudioRegex = /http:\/\/localhost:1050\.com\/files[/\\]audio/; if (imgRegex.test(url)) { - return await getDisplayedFile(url, 'image'); - } else if (dashVideoRegex.test(url)) { - return await getDisplayedFile(url, 'video'); - } else if (dashAudioRegex.test(url)) { - return await getDisplayedFile(url, 'audio'); - } else { - return url; + return getDisplayedFile(url, 'image'); + } + if (dashVideoRegex.test(url)) { + return getDisplayedFile(url, 'video'); + } + if (dashAudioRegex.test(url)) { + return getDisplayedFile(url, 'audio'); } + return url; }; - const getDisplayedFile = async (url: string, fileType: 'image' | 'video' | 'audio'): Promise => { + const getDisplayedFile = async (url: string, fileType: 'image' | 'video' | 'audio'): Promise => { switch (fileType) { - case 'image': + case 'image': { const imgValid = await isImgValid(url); if (!imgValid) return `\n${url} (This image could not be loaded)\n`; return `\n${url}\nIssue asset\n`; - case 'video': + } + case 'video': { const videoValid = await isVideoValid(url); if (!videoValid) return `\n${url} (This video could not be loaded)\n`; return `\n${url}\n