diff --git a/.eslintrc b/.eslintrc index c0d2b2cc5f3..7eb3798364b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,9 +1,16 @@ { - "extends": ["eslint:recommended", "plugin:react/recommended"], - "parser": "@babel/eslint-parser", + "root": true, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended", + "prettier" + ], + "parser": "@typescript-eslint/parser", "parserOptions": { "requireConfigFile": false, - "ecmaVersion": 2018, + "ecmaVersion": 2019, "ecmaFeatures": { "jsx": true, "modules": true, @@ -15,7 +22,8 @@ "commonjs": true, "es6": true }, - "plugins": ["react"], + "ignorePatterns": ["*.scss.d.ts"], + "plugins": ["react", "react-hooks", "@typescript-eslint"], "globals": { "process": true }, @@ -25,113 +33,59 @@ } }, "rules": { - "react/jsx-no-undef": 0, + "react-hooks/exhaustive-deps": "error", + "react/jsx-boolean-value": ["error", "never", { "always": [] }], + "react/no-arrow-function-lifecycle": "error", + "react/no-invalid-html-attribute": "error", + "react/jsx-no-useless-fragment": "error", + "react/jsx-no-constructed-context-values": "error", + "react/jsx-fragments": ["error", "syntax"], + "react/jsx-no-duplicate-props": ["error", { "ignoreCase": true }], + "react/jsx-pascal-case": [ + "error", + { + "allowAllCaps": true, + "ignore": [] + } + ], + "react/no-danger": "warn", + "react/no-did-update-set-state": "error", + "react/no-will-update-set-state": "error", + "react/self-closing-comp": "error", + "react/jsx-no-undef": ["error", { "allowGlobals": true }], /*Possible Errors */ - "no-cond-assign": [1, "except-parens"], - "no-console": 0, - "no-constant-condition": 1, - "no-control-regex": 1, - "no-debugger": 1, - "no-dupe-args": 1, - "no-dupe-keys": 1, - "no-duplicate-case": 0, - "no-empty-character-class": 1, - "no-empty": 0, - "no-ex-assign": 1, - "no-extra-boolean-cast": 1, - "no-extra-parens": 0, - "no-extra-semi": 1, - "no-func-assign": 1, + "no-console": "off", "no-inner-declarations": [1, "functions"], - "no-invalid-regexp": 1, - "no-irregular-whitespace": 1, - "no-negated-in-lhs": 1, - "no-obj-calls": 1, - "no-regex-spaces": 1, - "no-reserved-keys": 0, - "no-sparse-arrays": 1, - "no-unexpected-multiline": 1, - "no-unreachable": 1, - "use-isnan": 1, - "valid-jsdoc": 0, - "valid-typeof": 1, /* Best Practices */ - "accessor-pairs": 0, - "block-scoped-var": 0, // see Babel section - "complexity": 0, - "consistent-return": 0, - "curly": 0, - "default-case": 0, - "dot-notation": [ - 0, - { - "allowKeywords": true, - "allowPattern": "" - } - ], - "dot-location": [1, "property"], - "eqeqeq": 1, - "guard-for-in": 0, - "no-alert": 1, - "no-caller": 1, - "no-div-regex": 1, - "no-else-return": 0, - "no-eq-null": 0, - "no-eval": 1, - "no-extend-native": 1, - "no-extra-bind": 0, + "eqeqeq": ["error"], + "no-alert": ["error"], + "no-caller": ["error"], + "no-div-regex": ["error"], + "no-eval": ["error"], + "no-extend-native": ["error"], "no-fallthrough": 0, - "no-floating-decimal": 1, - "no-implied-eval": 1, - "no-iterator": 1, - "no-labels": 1, - "no-lone-blocks": 1, - "no-loop-func": 1, - "no-multi-spaces": 0, - "no-multi-str": 0, - "no-native-reassign": 1, - "no-new-func": 1, - "no-new-wrappers": 1, - "no-new": 1, - "no-octal-escape": 1, - "no-octal": 1, - "no-param-reassign": 0, - "no-process-env": 0, - "no-proto": 1, - "no-redeclare": 1, - "no-return-assign": 1, - "no-script-url": 1, - "no-self-compare": 0, - "no-sequences": 1, - "no-throw-literal": 0, - "no-unused-expressions": 0, - "no-void": 0, - "no-warning-comments": [ - 0, - { - "terms": ["todo", "tofix"], - "location": "start" - } - ], - "no-with": 1, - "radix": 1, - "vars-on-top": 0, - "wrap-iife": [1, "inside"], - "yoda": [0, "never"], + "no-implied-eval": ["error"], + "no-iterator": ["error"], + "no-labels": ["error"], + "no-lone-blocks": ["error"], + "no-loop-func": ["error"], + "no-new-func": ["error"], + "no-new-wrappers": ["error"], + "no-new": ["error"], + "no-octal-escape": ["error"], + "no-proto": ["error"], + "no-return-assign": ["error"], + "no-script-url": ["error"], + "no-sequences": ["error"], + "radix": "error", /* Strict Mode */ "strict": [0, "global"], /* Variables */ - "no-catch-shadow": 0, - "no-delete-var": 1, "no-label-var": 1, - "no-shadow-restricted-names": 1, - "no-shadow": 0, - "no-undef-init": 1, - "no-undefined": 0, "no-unused-vars": [ 1, { @@ -139,107 +93,37 @@ "args": "none" } ], - "no-use-before-define": 0, - /* Node.js */ - "handle-callback-err": 0, - "no-mixed-requires": 1, - "no-new-require": 1, - "no-path-concat": 1, - "no-process-exit": 1, - "no-restricted-modules": [1, ""], // add any unwanted Node.js core modules - "no-sync": 1, - - /* Stylistic Issues */ - "array-bracket-spacing": [0, "never"], - "brace-style": [ - 0, - "1tbs", - { - "allowSingleLine": true - } - ], "camelcase": [ 0, { "properties": "always" } ], - "comma-spacing": [ - 0, - { - "before": false, - "after": true - } - ], - "comma-style": [1, "last"], - "comma-dangle": 0, - "computed-property-spacing": 0, - "consistent-this": 0, - "eol-last": 0, - "func-names": 0, - "func-style": 0, - "indent": [0, 4, { "SwitchCase": 1 }], - "key-spacing": [ - 0, - { - "beforeColon": false, - "afterColon": true - } - ], - "linebreak-style": 0, - "max-nested-callbacks": [0, 3], - "new-cap": 0, // see Babel section - "new-parens": 1, - "newline-after-var": 0, - "no-array-constructor": 1, - "no-continue": 0, - "no-inline-comments": 0, - "no-lonely-if": 0, - "no-mixed-spaces-and-tabs": 0, - "no-multiple-empty-lines": [ - 0, - { - "max": 1 - } - ], - "no-nested-ternary": 0, + "no-array-constructor": "error", "no-new-object": 1, - "no-spaced-func": 0, - "no-ternary": 0, - "no-trailing-spaces": 0, - "no-underscore-dangle": 0, - "no-unneeded-ternary": 1, - "object-curly-spacing": 0, // see Babel section - "one-var": [0, "never"], - "padded-blocks": [0, "never"], - "quote-props": [0, "as-needed"], - "quotes": [0, "single"], - "semi-spacing": [ - 1, - { - "before": false, - "after": true + "no-unneeded-ternary": 1 /* ECMAScript 6 */, + "prefer-const": "error" + }, + "overrides": [ + { + "files": ["**/*.ts", "**/*.tsx"], + "rules": { + // @TODO: revise these rules + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + "caughtErrorsIgnorePattern": "^_" + } + ], + "@typescript-eslint/ban-ts-comment": "warn", + "@typescript-eslint/no-loss-of-precision": "warn", + "@typescript-eslint/no-unsafe-declaration-merging": "warn", + "react-hooks/exhaustive-deps": "warn", + "react/prop-types": "warn" } - ], - "semi": [1, "always"], - "sort-vars": 0, - "space-after-keywords": 0, - "space-before-blocks": [0, "always"], - "space-before-function-paren": [0, "never"], - "space-in-parens": [0, "never"], - "space-infix-ops": 0, - "space-unary-ops": 0, - "spaced-comment": [0, "always"], - "wrap-regex": 0, - - /* ECMAScript 6 */ - "constructor-super": 1, - "generator-star-spacing": 0, // see Babel section - "no-this-before-super": 1, - "no-var": 0, - "object-shorthand": 0, // see Babel section - "prefer-const": 1, - "no-useless-escape": 0 - } + } + ] } diff --git a/CHANGES.md b/CHANGES.md index 34eebf54151..587f9dfb86d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ - `WebMapServiceCatalogItem` will drop problematic query parameters from `url` when calling `GetCapabilities` (eg `"styles","srs","crs","format"`) - Fixed regression causing explorer window not to display instructions when first opened. - [The next improvement] +- Enable eslint for typescript: plugin:@typescript-eslint/eslint-recommended #### 8.4.1 - 2023-12-08 diff --git a/doc/js/rewrite-links.js b/doc/js/rewrite-links.js index 09007119df2..1a6ec514617 100644 --- a/doc/js/rewrite-links.js +++ b/doc/js/rewrite-links.js @@ -11,5 +11,7 @@ document.querySelectorAll("a").forEach(function (a) { a.target = "_blank"; a.rel = "noreferrer noopener"; } - } catch {} + } catch { + /* eslint-disable-line no-empty */ + } }); diff --git a/gulpfile.js b/gulpfile.js index 1389dac0c91..3bc960a85dd 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -49,13 +49,11 @@ gulp.task("lint", function (done) { "lib", "test", "--ext", - ".jsx", - "--ext", - ".js", + ".jsx,.js,.ts,.tsx", "--ignore-pattern", "lib/ThirdParty", "--max-warnings", - "0" + "481" // TODO: Bring this back to 0 ]); done(); diff --git a/lib/Core/CorsProxy.ts b/lib/Core/CorsProxy.ts index 365e915eeb2..6231c3925fc 100644 --- a/lib/Core/CorsProxy.ts +++ b/lib/Core/CorsProxy.ts @@ -101,7 +101,7 @@ export default class CorsProxy { } host = host.toLowerCase(); - for (var i = 0; i < domains.length; i++) { + for (let i = 0; i < domains.length; i++) { if (host.match("(^|\\.)" + domains[i] + "$")) { return true; } @@ -123,7 +123,7 @@ export default class CorsProxy { } getProxyBaseURL(proxyFlag: string | undefined) { - var flag = proxyFlag === undefined ? "" : "_" + proxyFlag + "/"; + const flag = proxyFlag === undefined ? "" : "_" + proxyFlag + "/"; return this.baseProxyUrl + flag; } @@ -161,8 +161,8 @@ export default class CorsProxy { return false; } - var uri = new URI(url); - var host = uri.host(); + const uri = new URI(url); + const host = uri.host(); if (host === "") { // do not proxy local files diff --git a/lib/Core/TerriaError.ts b/lib/Core/TerriaError.ts index 8a68f916cf7..0e4b23afd2e 100644 --- a/lib/Core/TerriaError.ts +++ b/lib/Core/TerriaError.ts @@ -304,7 +304,7 @@ export default class TerriaError { /** Has any error in the error tree been raised to the user? */ get raisedToUser() { - return this.flatten().find((error) => error._raisedToUser) ? true : false; + return !!this.flatten().find((error) => error._raisedToUser); } /** Resolve error seveirty */ diff --git a/lib/Core/animation.ts b/lib/Core/animation.ts index 262d04d674e..4a18f7e8322 100644 --- a/lib/Core/animation.ts +++ b/lib/Core/animation.ts @@ -48,7 +48,7 @@ const animationTimeout = ( */ export const animateEnd = (element: Element | null) => { - let timeoutID: ReturnType | undefined = undefined; + const timeoutID: ReturnType | undefined = undefined; return Promise.race([ transitionEnd(element), animationTimeout(timeoutID) diff --git a/lib/Core/arraysAreEqual.ts b/lib/Core/arraysAreEqual.ts index 01a3873774d..1d3297073f9 100644 --- a/lib/Core/arraysAreEqual.ts +++ b/lib/Core/arraysAreEqual.ts @@ -9,7 +9,7 @@ export default function arraysAreEqual(left: T[], right: T[]) { return false; } - for (var i = 0; i < left.length; ++i) { + for (let i = 0; i < left.length; ++i) { if (left[i] !== right[i]) { return false; } diff --git a/lib/Core/createDiscreteTimes.ts b/lib/Core/createDiscreteTimes.ts index d6bfb7ea703..38785f6ca12 100644 --- a/lib/Core/createDiscreteTimes.ts +++ b/lib/Core/createDiscreteTimes.ts @@ -67,7 +67,7 @@ export default function createDiscreteTimesFromIsoSegments( } } - let current = start.clone(); + const current = start.clone(); let count = 0; // Add intervals starting at start until: diff --git a/lib/Core/createTransformerAllowUndefined.ts b/lib/Core/createTransformerAllowUndefined.ts index e0cab1aeb8c..b6542aee463 100644 --- a/lib/Core/createTransformerAllowUndefined.ts +++ b/lib/Core/createTransformerAllowUndefined.ts @@ -3,7 +3,7 @@ import { createTransformer, ITransformer } from "mobx-utils"; const undefinedObjectSymbol = Symbol("isUndefinedObject"); class UndefinedObject { - readonly [undefinedObjectSymbol]: true = true; + readonly [undefinedObjectSymbol]: true = true as const; } function isUndefinedObject(x: any): x is UndefinedObject { @@ -28,7 +28,7 @@ export default function createTransformerAllowUndefined( value: (transformer.name || "anonymous") + "-allowUndefined" }); const unwrapOnCleanup = - onCleanup == undefined + onCleanup === undefined ? undefined : function ( resultObject: B | undefined, diff --git a/lib/Core/flattenNested.ts b/lib/Core/flattenNested.ts index bdb27386cf9..091dad03975 100644 --- a/lib/Core/flattenNested.ts +++ b/lib/Core/flattenNested.ts @@ -14,8 +14,8 @@ export default function flattenNested(array: NestedArray): T[] { } function flattenNestedLoop(array: NestedArray, result: T[]) { - for (var i = 0; i < array.length; i++) { - var value = array[i]; + for (let i = 0; i < array.length; i++) { + const value = array[i]; if (Array.isArray(value)) { flattenNestedLoop(value, result); } else { diff --git a/lib/Core/hashFromString.ts b/lib/Core/hashFromString.ts index 32cc1d14f65..6f1d2533394 100644 --- a/lib/Core/hashFromString.ts +++ b/lib/Core/hashFromString.ts @@ -3,7 +3,7 @@ export default function hashFromString(s: string) { return Math.abs( s.split("").reduce(function (prev, c) { - var hash = (prev << 5) - prev + c.charCodeAt(0); + const hash = (prev << 5) - prev + c.charCodeAt(0); return hash; }, 0) ); diff --git a/lib/Core/injectTerms.ts b/lib/Core/injectTerms.ts index 59d0123e926..3cb747f2906 100644 --- a/lib/Core/injectTerms.ts +++ b/lib/Core/injectTerms.ts @@ -72,8 +72,8 @@ const findFirstTerm = ( const injectTerms = (string: string, termDictionary: Term[]): string => { let injectIndex = 0; const injectedBoldSet = new Set(); - while (1) { - let tooltipTerms = new Map(); + for (;;) { + const tooltipTerms = new Map(); termDictionary.forEach((item: any) => tooltipTerms.set( diff --git a/lib/Core/loadJson.ts b/lib/Core/loadJson.ts index 61be0e52a59..c0cd6d20705 100644 --- a/lib/Core/loadJson.ts +++ b/lib/Core/loadJson.ts @@ -6,10 +6,10 @@ export default function loadJson( body?: any, asForm: boolean = false ): Promise { - let responseType: XMLHttpRequestResponseType = "json"; + const responseType: XMLHttpRequestResponseType = "json"; let jsonPromise: Promise; - let params: any = { + const params: any = { url: urlOrResource, headers: headers }; diff --git a/lib/Core/markdownToHtml.ts b/lib/Core/markdownToHtml.ts index 76d80e84a74..4d2c9ef823d 100644 --- a/lib/Core/markdownToHtml.ts +++ b/lib/Core/markdownToHtml.ts @@ -1,17 +1,17 @@ "use strict"; -var defined = require("terriajs-cesium/Source/Core/defined").default; -var MarkdownIt = require("markdown-it"); -var DOMPurify = require("dompurify/dist/purify"); +const defined = require("terriajs-cesium/Source/Core/defined").default; +const MarkdownIt = require("markdown-it"); +const DOMPurify = require("dompurify/dist/purify"); import injectTerms from "./injectTerms"; import { Term } from "../ReactViewModels/defaultTerms"; -var md = new MarkdownIt({ +const md = new MarkdownIt({ html: true, linkify: true }); -var htmlRegex = /^\s*<[^>]+>/; +const htmlRegex = /^\s*<[^>]+>/; export interface MarkdownOptions { // requires tooltipTerms as well @@ -35,7 +35,7 @@ export interface MarkdownOptions { function markdownToHtml( markdownString: string, allowUnsafeHtml: boolean = false, - domPurifyOptions: Object = {}, + domPurifyOptions: object = {}, markdownOptions: MarkdownOptions = {} ) { if (!defined(markdownString) || markdownString.length === 0) { @@ -44,7 +44,7 @@ function markdownToHtml( // If the text looks like html, don't try to interpret it as Markdown because // we'll probably break it in the process. // It would wrap non-standard tags such as hi in a

, which is bad. - var unsafeHtml: string; + let unsafeHtml: string; if (htmlRegex.test(markdownString)) { unsafeHtml = markdownString; } else { diff --git a/lib/Core/scaleToDenominator.ts b/lib/Core/scaleToDenominator.ts index 402330c3494..77ee091c6e7 100644 --- a/lib/Core/scaleToDenominator.ts +++ b/lib/Core/scaleToDenominator.ts @@ -5,7 +5,7 @@ export function scaleDenominatorToLevel( min: boolean = true, ows: boolean = true ): number | undefined { - if (scaleDenominator == undefined || scaleDenominator <= 0.0) { + if (scaleDenominator === undefined || scaleDenominator <= 0.0) { return undefined; } diff --git a/lib/Map/Cesium/CesiumRenderLoopPauser.ts b/lib/Map/Cesium/CesiumRenderLoopPauser.ts index f0b0b2350df..4ad8dcf74d4 100644 --- a/lib/Map/Cesium/CesiumRenderLoopPauser.ts +++ b/lib/Map/Cesium/CesiumRenderLoopPauser.ts @@ -45,7 +45,7 @@ export default class CesiumRenderLoopPauser { ); this._boundNotifyRepaintRequired = this.notifyRepaintRequired.bind(this); - var canvas = this.cesiumWidget.canvas; + const canvas = this.cesiumWidget.canvas; canvas.addEventListener( "mousemove", this._boundNotifyRepaintRequired, @@ -156,7 +156,7 @@ export default class CesiumRenderLoopPauser { parameters, transferableObjects ) { - var result = that._originalScheduleTask.call( + const result = that._originalScheduleTask.call( this, parameters, transferableObjects @@ -165,7 +165,7 @@ export default class CesiumRenderLoopPauser { if (!defined(this._originalWorkerMessageSinkRepaint)) { this._originalWorkerMessageSinkRepaint = this._worker.onmessage; - var taskProcessor = this; + const taskProcessor = this; this._worker.onmessage = function (event: any) { taskProcessor._originalWorkerMessageSinkRepaint(event); diff --git a/lib/Map/Cesium/CesiumSelectionIndicator.ts b/lib/Map/Cesium/CesiumSelectionIndicator.ts index 0e35272641e..f7747e00834 100644 --- a/lib/Map/Cesium/CesiumSelectionIndicator.ts +++ b/lib/Map/Cesium/CesiumSelectionIndicator.ts @@ -25,8 +25,8 @@ declare module "terriajs-cesium/Source/Scene/Scene" { } } -var screenSpacePos = new Cartesian2(); -var offScreen = "-1000px"; +const screenSpacePos = new Cartesian2(); +const offScreen = "-1000px"; export default class CesiumSelectionIndicator { /** diff --git a/lib/Map/ColorMap/DiscreteColorMap.ts b/lib/Map/ColorMap/DiscreteColorMap.ts index 30db8779eff..4d0279d0460 100644 --- a/lib/Map/ColorMap/DiscreteColorMap.ts +++ b/lib/Map/ColorMap/DiscreteColorMap.ts @@ -48,7 +48,9 @@ export default class DiscreteColorMap extends ColorMap { i = 0, len = maximums.length - 1; i < len && value > maximums[i]; ++i - ) {} + ) { + /* TODO: refactor */ + } // Value may equal maximum, in which case we look at // `includeMinimumInThisBin` for the _next_ bin. diff --git a/lib/Map/ImageryProvider/ProtomapsImageryProvider.ts b/lib/Map/ImageryProvider/ProtomapsImageryProvider.ts index 20fd81084c6..424ea366f57 100644 --- a/lib/Map/ImageryProvider/ProtomapsImageryProvider.ts +++ b/lib/Map/ImageryProvider/ProtomapsImageryProvider.ts @@ -163,7 +163,7 @@ export class GeojsonSource implements TileSource { // request a particular tile const tile = (await this.tileIndex).getTile(c.z, c.x, c.y) as GeojsonVtTile; - let result = new Map(); + const result = new Map(); const scale = tileSize / geojsonvtExtent; if (tile && tile.features && tile.features.length > 0) { @@ -176,7 +176,7 @@ export class GeojsonSource implements TileSource { let numVertices = 0; // Calculate bbox - let bbox: Bbox = { + const bbox: Bbox = { minX: Infinity, minY: Infinity, maxX: -Infinity, @@ -359,7 +359,7 @@ export default class ProtomapsImageryProvider this.ready = true; this.credit = - typeof options.credit == "string" + typeof options.credit === "string" ? new Credit(options.credit) : (options.credit as Credit); @@ -373,7 +373,7 @@ export default class ProtomapsImageryProvider if (typeof this.data === "string") { if (this.data.endsWith(".pmtiles")) { this.source = new PmtilesSource(this.data, false); - let cache = new TileCache(this.source, 1024); + const cache = new TileCache(this.source, 1024); this.view = new View(cache, this.maximumNativeZoom, 2); } else if ( this.data.endsWith(".json") || @@ -382,7 +382,7 @@ export default class ProtomapsImageryProvider this.source = new GeojsonSource(this.data); } else { this.source = new ZxySource(this.data, false); - let cache = new TileCache(this.source, 1024); + const cache = new TileCache(this.source, 1024); this.view = new View(cache, this.maximumNativeZoom, 2); } } @@ -469,7 +469,7 @@ export default class ProtomapsImageryProvider this.labelers.add(coords.z, tileMap); - let labelData = this.labelers.getIndex(tile.z); + const labelData = this.labelers.getIndex(tile.z); const bbox = { minX: 256 * coords.x - BUF, @@ -573,7 +573,7 @@ export default class ProtomapsImageryProvider const bufferBbox = bbox(buffer); // Get array of all features - let geojsonFeatures: Feature[] = this.source.geojsonObject.features; + const geojsonFeatures: Feature[] = this.source.geojsonObject.features; const pickedFeatures: Feature[] = []; diff --git a/lib/Map/Leaflet/ImageryProviderLeafletTileLayer.ts b/lib/Map/Leaflet/ImageryProviderLeafletTileLayer.ts index 900030fef62..b51f068d0d9 100644 --- a/lib/Map/Leaflet/ImageryProviderLeafletTileLayer.ts +++ b/lib/Map/Leaflet/ImageryProviderLeafletTileLayer.ts @@ -225,7 +225,7 @@ export default class ImageryProviderLeafletTileLayer extends L.TileLayer { return tilePoint.z - this._zSubtract; } - _update() { + _update(...args: unknown[]) { if (!this.imageryProvider.ready) { if (!this._delayedUpdate) { this._delayedUpdate = setTimeout(() => { @@ -299,7 +299,7 @@ export default class ImageryProviderLeafletTileLayer extends L.TileLayer { } if (this._usable) { - (L.TileLayer).prototype._update.apply(this, arguments); + (L.TileLayer).prototype._update.apply(this, args); this._updateAttribution(); } diff --git a/lib/Map/Leaflet/LeafletSelectionIndicator.ts b/lib/Map/Leaflet/LeafletSelectionIndicator.ts index 9b0159e8bfb..79ed9474b5e 100644 --- a/lib/Map/Leaflet/LeafletSelectionIndicator.ts +++ b/lib/Map/Leaflet/LeafletSelectionIndicator.ts @@ -67,7 +67,7 @@ export default class LeafletSelectionIndicator { this._selectionIndicatorTween = undefined; } - var style = this._selectionIndicatorDomElement.style; + const style = this._selectionIndicatorDomElement.style; this._selectionIndicatorIsAppearing = true; @@ -111,7 +111,7 @@ export default class LeafletSelectionIndicator { this._selectionIndicatorTween = undefined; } - var style = this._selectionIndicatorDomElement.style; + const style = this._selectionIndicatorDomElement.style; this._selectionIndicatorIsAppearing = false; @@ -147,9 +147,9 @@ export default class LeafletSelectionIndicator { return; } - var feature = this._leaflet.terria.selectedFeature; + const feature = this._leaflet.terria.selectedFeature; if (isDefined(feature) && isDefined(feature.position)) { - var cartographic = Ellipsoid.WGS84.cartesianToCartographic( + const cartographic = Ellipsoid.WGS84.cartesianToCartographic( feature.position.getValue( this._leaflet.terria.timelineClock.currentTime ), diff --git a/lib/Map/Leaflet/LeafletVisualizer.ts b/lib/Map/Leaflet/LeafletVisualizer.ts index f83edf57c24..4068597663e 100644 --- a/lib/Map/Leaflet/LeafletVisualizer.ts +++ b/lib/Map/Leaflet/LeafletVisualizer.ts @@ -1022,7 +1022,7 @@ class LeafletGeomVisualizer { polyline.setLatLngs(latlngs); } - for (let prop in polylineOptions) { + for (const prop in polylineOptions) { if ((polylineOptions)[prop] !== (polyline.options)[prop]) { polyline.setStyle(polylineOptions); break; @@ -1215,7 +1215,7 @@ function positionToLatLng( position: Cartesian3, bounds: LatLngBounds | undefined ) { - var cartographic = Ellipsoid.WGS84.cartesianToCartographic(position); + const cartographic = Ellipsoid.WGS84.cartesianToCartographic(position); let lon = CesiumMath.toDegrees(cartographic.longitude); if (bounds !== undefined) { if (_isCloseToEasternAntiMeridian(bounds)) { @@ -1232,7 +1232,7 @@ function positionToLatLng( } function hierarchyToLatLngs(hierarchy: PolygonHierarchy) { - let holes: L.LatLng[][] = []; + const holes: L.LatLng[][] = []; const positions = Array.isArray(hierarchy) ? hierarchy : hierarchy.positions; if (hierarchy.holes.length > 0) { hierarchy.holes.forEach((hole) => { @@ -1320,10 +1320,10 @@ function getValueOrUndefined(property: Property | undefined, time: JulianDate) { } function convertEntityPositionsToLatLons(positions: Cartesian3[]): L.LatLng[] { - var carts = Ellipsoid.WGS84.cartesianArrayToCartographicArray(positions); - var latlngs: L.LatLng[] = []; + const carts = Ellipsoid.WGS84.cartesianArrayToCartographicArray(positions); + const latlngs: L.LatLng[] = []; let lastLongitude; - for (var p = 0; p < carts.length; p++) { + for (let p = 0; p < carts.length; p++) { let lon = CesiumMath.toDegrees(carts[p].longitude); if (lastLongitude !== undefined) { diff --git a/lib/Map/PickedFeatures/featureDataToGeoJson.ts b/lib/Map/PickedFeatures/featureDataToGeoJson.ts index 9e1c801442a..9f0711c1815 100644 --- a/lib/Map/PickedFeatures/featureDataToGeoJson.ts +++ b/lib/Map/PickedFeatures/featureDataToGeoJson.ts @@ -185,7 +185,7 @@ function getEsriFeature( if (geojsonGeom) { return { - type: "Feature" as "Feature", + type: "Feature" as const, properties: isJsonObject(featureData.attributes) ? featureData.attributes : {}, diff --git a/lib/Map/Region/RegionProvider.ts b/lib/Map/Region/RegionProvider.ts index faffff8d19b..19a4b05fc2d 100644 --- a/lib/Map/Region/RegionProvider.ts +++ b/lib/Map/Region/RegionProvider.ts @@ -393,7 +393,7 @@ export default class RegionProvider { } else { r = s.toLowerCase().trim(); } - let replacements = this[replacementsProp]; + const replacements = this[replacementsProp]; if (replacements === undefined || replacements.length === 0) { return r; } @@ -429,8 +429,8 @@ export default class RegionProvider { "dataReplacements" ); - let id = this._idIndex[code]; - let idAfterReplacement = this._idIndex[codeAfterReplacement]; + const id = this._idIndex[code]; + const idAfterReplacement = this._idIndex[codeAfterReplacement]; if (!isDefined(id) && !isDefined(idAfterReplacement)) { return -1; diff --git a/lib/Map/Vector/Reproject.ts b/lib/Map/Vector/Reproject.ts index 1312fc285ec..b883042f591 100644 --- a/lib/Map/Vector/Reproject.ts +++ b/lib/Map/Vector/Reproject.ts @@ -62,7 +62,7 @@ export default { sourceCode in Proj4Definitions ? new proj4.Proj(Proj4Definitions[sourceCode]) : undefined; - var dest = + const dest = destCode in Proj4Definitions ? new proj4.Proj(Proj4Definitions[destCode]) : undefined; @@ -86,7 +86,7 @@ export default { return true; } - var url = new urijs(proj4ServiceBaseUrl).segment(code).toString(); + const url = new urijs(proj4ServiceBaseUrl).segment(code).toString(); return loadText(url) .then(function (proj4Text: string) { Proj4Definitions[code] = proj4Text; diff --git a/lib/Map/Vector/rectangleToLatLngBounds.ts b/lib/Map/Vector/rectangleToLatLngBounds.ts index 8ff2a4b182f..a3ea79f8e96 100644 --- a/lib/Map/Vector/rectangleToLatLngBounds.ts +++ b/lib/Map/Vector/rectangleToLatLngBounds.ts @@ -8,9 +8,9 @@ import Rectangle from "terriajs-cesium/Source/Core/Rectangle"; * @return {L.latLngBounds} The equivalent Leaflet latLngBounds. */ export default function rectangleToLatLngBounds(rectangle: Rectangle) { - var west = CesiumMath.toDegrees(rectangle.west); - var south = CesiumMath.toDegrees(rectangle.south); - var east = CesiumMath.toDegrees(rectangle.east); - var north = CesiumMath.toDegrees(rectangle.north); + const west = CesiumMath.toDegrees(rectangle.west); + const south = CesiumMath.toDegrees(rectangle.south); + const east = CesiumMath.toDegrees(rectangle.east); + const north = CesiumMath.toDegrees(rectangle.north); return L.latLngBounds([south, west], [north, east]); } diff --git a/lib/ModelMixins/CatalogMemberMixin.ts b/lib/ModelMixins/CatalogMemberMixin.ts index 6c0f31ba47c..c0d32b929c9 100644 --- a/lib/ModelMixins/CatalogMemberMixin.ts +++ b/lib/ModelMixins/CatalogMemberMixin.ts @@ -123,9 +123,9 @@ function CatalogMemberMixin>(Base: T) { @computed get nameSortKey() { - var parts = (this.nameInCatalog || "").split(/(\d+)/); + const parts = (this.nameInCatalog || "").split(/(\d+)/); return parts.map(function (part) { - var parsed = parseInt(part, 10); + const parsed = parseInt(part, 10); if (parsed === parsed) { return parsed; } else { diff --git a/lib/ModelMixins/Cesium3dTilesMixin.ts b/lib/ModelMixins/Cesium3dTilesMixin.ts index ff17939e254..7b3f2eb2289 100644 --- a/lib/ModelMixins/Cesium3dTilesMixin.ts +++ b/lib/ModelMixins/Cesium3dTilesMixin.ts @@ -214,7 +214,7 @@ function Cesium3dTilesMixin>(Base: T) { */ private computeModelMatrixFromTransformationTraits(modelMatrix: Matrix4) { let scale = Matrix4.getScale(modelMatrix, new Cartesian3()); - let position = Matrix4.getTranslation(modelMatrix, new Cartesian3()); + const position = Matrix4.getTranslation(modelMatrix, new Cartesian3()); let orientation = Quaternion.fromRotationMatrix( Matrix4.getMatrix3(modelMatrix, new Matrix3()) ); @@ -348,7 +348,7 @@ function Cesium3dTilesMixin>(Base: T) { return; } - let resource: IonResource | undefined = await IonResource.fromAssetId( + const resource: IonResource | undefined = await IonResource.fromAssetId( ionAssetId, { accessToken: @@ -436,7 +436,7 @@ function Cesium3dTilesMixin>(Base: T) { "(${COLOR}.b === undefined ? 1 : ${COLOR}.b) * 255," + "${opacity}" + "))"; - } else if (typeof style.color == "string") { + } else if (typeof style.color === "string") { // Check if the color specified is just a css color const cssColor = Color.fromCssColorString(style.color); if (isDefined(cssColor)) { diff --git a/lib/ModelMixins/ClippingMixin.ts b/lib/ModelMixins/ClippingMixin.ts index 960804fb51a..cb4a2b64bcf 100644 --- a/lib/ModelMixins/ClippingMixin.ts +++ b/lib/ModelMixins/ClippingMixin.ts @@ -79,7 +79,7 @@ function ClippingMixin>(Base: T) { return; } - if (this.clippingPlanes.planes.length == 0) { + if (this.clippingPlanes.planes.length === 0) { return; } @@ -551,14 +551,13 @@ function zoomToDataSourceWithTimeout( // Create a promise that waits for the dataSource to be added to map or // timeout to complete whichever happens first return new Promise((resolve, reject) => { - let removeListener = renderedDataSources.dataSourceAdded.addEventListener( - (_, added) => { + const removeListener = + renderedDataSources.dataSourceAdded.addEventListener((_, added) => { if (added === dataSource) { removeListener(); resolve(cesium.doZoomTo(dataSource)); } - } - ); + }); runLater(removeListener, timeoutMilliseconds).then(reject); }); } diff --git a/lib/ModelMixins/DiscretelyTimeVaryingMixin.ts b/lib/ModelMixins/DiscretelyTimeVaryingMixin.ts index 10a0fd98cd5..922044b4636 100644 --- a/lib/ModelMixins/DiscretelyTimeVaryingMixin.ts +++ b/lib/ModelMixins/DiscretelyTimeVaryingMixin.ts @@ -115,7 +115,9 @@ function DiscretelyTimeVaryingMixin< tag: dt.tag !== undefined ? dt.tag : dt.time }); } - } catch {} + } catch { + /* eslint-disable-line no-empty */ + } } asJulian.sort((a, b) => JulianDate.compare(a.time, b.time)); return asJulian; @@ -436,15 +438,15 @@ export type ObjectifiedHours = DatesObject; * whose values are objects whose keys are days, whose values are arrays of all the datetimes on that day. */ function objectifyDates(dates: Date[]): ObjectifiedDates { - let result: ObjectifiedDates = { index: [], dates }; + const result: ObjectifiedDates = { index: [], dates }; for (let i = 0; i < dates.length; i++) { - let date = dates[i]; - let year = date.getFullYear(); - let century = Math.floor(year / 100); - let month = date.getMonth(); - let day = date.getDate(); - let hour = date.getHours(); + const date = dates[i]; + const year = date.getFullYear(); + const century = Math.floor(year / 100); + const month = date.getMonth(); + const day = date.getDate(); + const hour = date.getHours(); // ObjectifiedDates if (!result[century]) { diff --git a/lib/ModelMixins/ExportWebCoverageServiceMixin.ts b/lib/ModelMixins/ExportWebCoverageServiceMixin.ts index c8e0a3d07b7..622d01fb9ab 100644 --- a/lib/ModelMixins/ExportWebCoverageServiceMixin.ts +++ b/lib/ModelMixins/ExportWebCoverageServiceMixin.ts @@ -488,6 +488,7 @@ function ExportWebCoverageServiceMixin< xml.getElementsByTagName("ServiceException")?.[0]?.innerHTML ?? xml.getElementsByTagName("ows:ExceptionText")?.[0]?.innerHTML; if (isDefined(message)) { + /* eslint-disable-next-line no-ex-assign */ error = message; } } diff --git a/lib/ModelMixins/GeojsonMixin.ts b/lib/ModelMixins/GeojsonMixin.ts index 5eacc8fee0c..5b229b77a6d 100644 --- a/lib/ModelMixins/GeojsonMixin.ts +++ b/lib/ModelMixins/GeojsonMixin.ts @@ -649,8 +649,8 @@ function GeoJsonMixin>(Base: T) { }); if (matchedStyles !== undefined) { - for (let matched of matchedStyles) { - for (let trait of Object.keys(matched.style.traits)) { + for (const matched of matchedStyles) { + for (const trait of Object.keys(matched.style.traits)) { featureProperties[trait] = // @ts-ignore - TS can't tell that `trait` is of the correct index type for style matched.style[trait] ?? featureProperties[trait]; @@ -684,7 +684,7 @@ function GeoJsonMixin>(Base: T) { const dataSource = new CustomDataSource(this.name || "Table"); dataSource.entities.suspendEvents(); - let features: Entity[] = createLongitudeLatitudeFeaturePerRow( + const features: Entity[] = createLongitudeLatitudeFeaturePerRow( style, longitudes, latitudes @@ -1616,8 +1616,8 @@ function filterValue( prop: string, func: (obj: any, prop: string) => void ) { - for (let p in obj) { - if (obj.hasOwnProperty(p) === false) { + for (const p in obj) { + if (Object.hasOwnProperty.call(obj, p) === false) { continue; } else if (p === prop) { if (func && typeof func === "function") { @@ -1679,7 +1679,7 @@ function describeWithoutUnderscores( ): string { let html = ""; for (let key in properties) { - if (properties.hasOwnProperty(key)) { + if (Object.hasOwnProperty.call(properties, key)) { if (key === nameProperty || simpleStyleIdentifiers.indexOf(key) !== -1) { continue; } @@ -1834,7 +1834,7 @@ function isPolygonOnTerrain(polygon: PolygonGraphics, now: JulianDate) { return isClamped || (!hasPerPositionHeight && !hasPolygonHeight); } -export function getColor(color: String | string | Color): Color { +export function getColor(color: string | Color): Color { if (typeof color === "string" || color instanceof String) { return Color.fromCssColorString(color.toString()) ?? Color.GRAY; } else { diff --git a/lib/ModelMixins/SearchProviders/WebFeatureServiceSearchProviderMixin.ts b/lib/ModelMixins/SearchProviders/WebFeatureServiceSearchProviderMixin.ts index 622a5bddb57..482740f1bfb 100644 --- a/lib/ModelMixins/SearchProviders/WebFeatureServiceSearchProviderMixin.ts +++ b/lib/ModelMixins/SearchProviders/WebFeatureServiceSearchProviderMixin.ts @@ -91,7 +91,7 @@ function WebFeatureServiceSearchProviderMixin< return this.getXml(_wfsServiceUrl.toString()) .then((xml: any) => { - let json: any = xml2json(xml); + const json: any = xml2json(xml); let features: any[]; if (json === undefined) { results.message = { @@ -215,8 +215,8 @@ function createZoomToFunction( ) { // Server does not return information of a bounding box, just a location. // bboxSize is used to expand a point - var bboxSize = 0.2; - var rectangle = zoomRectangleFromPoint( + const bboxSize = 0.2; + const rectangle = zoomRectangleFromPoint( location.latitude, location.longitude, bboxSize diff --git a/lib/ModelMixins/TableMixin.ts b/lib/ModelMixins/TableMixin.ts index 2f44c562e12..9a2619dd6ca 100644 --- a/lib/ModelMixins/TableMixin.ts +++ b/lib/ModelMixins/TableMixin.ts @@ -185,7 +185,9 @@ function TableMixin>(Base: T) { if (activeStyle === undefined) { return this.defaultTableStyle; } - let ret = this.tableStyles.find((style) => style.id === this.activeStyle); + const ret = this.tableStyles.find( + (style) => style.id === this.activeStyle + ); if (ret === undefined) { return this.defaultTableStyle; } @@ -214,7 +216,7 @@ function TableMixin>(Base: T) { protected async _exportData(): Promise { if (isDefined(this.dataColumnMajor)) { // I am assuming all columns have the same length -> so use first column - let csvString = this.dataColumnMajor[0] + const csvString = this.dataColumnMajor[0] .map((row, rowIndex) => this.dataColumnMajor!.map((col) => col[rowIndex]).join(",") ) diff --git a/lib/Models/BoxDrawing.ts b/lib/Models/BoxDrawing.ts index f86fca053f1..13eab4a6453 100644 --- a/lib/Models/BoxDrawing.ts +++ b/lib/Models/BoxDrawing.ts @@ -1620,8 +1620,8 @@ export default class BoxDrawing { scalePoint1: ScalePoint, scalePoint2: ScalePoint ): Entity { - const position1 = scalePoint1.position?.getValue(JulianDate.now())!; - const position2 = scalePoint2.position?.getValue(JulianDate.now())!; + const position1 = scalePoint1.position?.getValue(JulianDate.now()); + const position2 = scalePoint2.position?.getValue(JulianDate.now()); const scaleAxis = new Entity({ show: false, polyline: { diff --git a/lib/Models/CameraView.ts b/lib/Models/CameraView.ts index c8c87706777..7529b0e246c 100644 --- a/lib/Models/CameraView.ts +++ b/lib/Models/CameraView.ts @@ -78,15 +78,15 @@ export default class CameraView { north: CesiumMath.toDegrees(this.rectangle.north) }; - if (this.position && this.direction && this.up) { - function vectorToJson(vector: Readonly) { - return { - x: vector.x, - y: vector.y, - z: vector.z - }; - } + function vectorToJson(vector: Readonly) { + return { + x: vector.x, + y: vector.y, + z: vector.z + }; + } + if (this.position && this.direction && this.up) { result.position = vectorToJson(this.position); result.direction = vectorToJson(this.direction); result.up = vectorToJson(this.up); @@ -240,7 +240,7 @@ export default class CameraView { } Cartesian3.normalize(rightENU, rightENU); - var upENU = Cartesian3.cross(rightENU, directionENU, scratchUp); + const upENU = Cartesian3.cross(rightENU, directionENU, scratchUp); Cartesian3.normalize(upENU, upENU); const targetCartesian = Ellipsoid.WGS84.cartographicToCartesian( diff --git a/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunction.ts b/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunction.ts index 48eb4fc73a3..822eac7380e 100644 --- a/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunction.ts +++ b/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunction.ts @@ -339,8 +339,7 @@ ${DATASETS.map((d) => `\n- ${d.title}`)}` .map((col) => { return { id: col.name }; }) || []; - if (possibleValues.length === 0) { - } + return new EnumerationParameter(this, { id: "Data Column", description: diff --git a/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunctionJob.ts b/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunctionJob.ts index 07fadd9dcc6..e6c15f203f1 100644 --- a/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunctionJob.ts +++ b/lib/Models/Catalog/CatalogFunctions/YDYRCatalogFunctionJob.ts @@ -245,7 +245,7 @@ export default class YDYRCatalogFunctionJob extends CatalogFunctionJobMixin( undefined ); - let regionColumnSplit = DATASETS.find( + const regionColumnSplit = DATASETS.find( (d) => d.title === this.parameters?.["Output Geography"] )?.geographyName.split("_"); let regionColumn = ""; diff --git a/lib/Models/Catalog/CatalogGroups/OpenDataSoftCatalogGroup.ts b/lib/Models/Catalog/CatalogGroups/OpenDataSoftCatalogGroup.ts index 651a3dd0761..7a6ee43084e 100644 --- a/lib/Models/Catalog/CatalogGroups/OpenDataSoftCatalogGroup.ts +++ b/lib/Models/Catalog/CatalogGroups/OpenDataSoftCatalogGroup.ts @@ -39,7 +39,7 @@ export class OpenDataSoftCatalogStratum extends LoadableStratum( domain: catalogGroup.url }); - let datasets: ValidDataset[] = []; + const datasets: ValidDataset[] = []; let facets: ValidFacet[] | undefined; // If no facetFilters, try to get some facets diff --git a/lib/Models/Catalog/CatalogGroups/ThreddsCatalogGroup.ts b/lib/Models/Catalog/CatalogGroups/ThreddsCatalogGroup.ts index 9461235dfb7..3fca5712cc9 100644 --- a/lib/Models/Catalog/CatalogGroups/ThreddsCatalogGroup.ts +++ b/lib/Models/Catalog/CatalogGroups/ThreddsCatalogGroup.ts @@ -28,9 +28,9 @@ interface ThreddsCatalog { hasNestedCatalogs: boolean; datasets: ThreddsDataset[]; catalogs: ThreddsCatalog[]; - getAllChildDatasets: Function; - loadAllNestedCatalogs: Function; - loadNestedCatalogById: Function; + getAllChildDatasets: () => void; + loadAllNestedCatalogs: () => void; + loadNestedCatalogById: () => void; parentCatalog: ThreddsCatalog; } @@ -43,7 +43,7 @@ export interface ThreddsDataset { isParentDataset: boolean; datasets: ThreddsDataset[]; catalogs: ThreddsCatalog[]; - loadAllNestedCatalogs: Function; + loadAllNestedCatalogs: () => void; } export class ThreddsStratum extends LoadableStratum(ThreddsCatalogGroupTraits) { @@ -101,7 +101,7 @@ export class ThreddsStratum extends LoadableStratum(ThreddsCatalogGroupTraits) { @action async createMembers() { if (!isDefined(this._catalogGroup.url)) return; - let proxy = proxyCatalogItemBaseUrl( + const proxy = proxyCatalogItemBaseUrl( this._catalogGroup, this._catalogGroup.url ); diff --git a/lib/Models/Catalog/CatalogItems/ApiTableCatalogItem.ts b/lib/Models/Catalog/CatalogItems/ApiTableCatalogItem.ts index 0de57c9b073..1ff89b2e465 100644 --- a/lib/Models/Catalog/CatalogItems/ApiTableCatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/ApiTableCatalogItem.ts @@ -131,7 +131,7 @@ export class ApiTableCatalogItem extends AutoRefreshingMixin( row["value"] = value; // add the id to the row's data row[this.idKey!] = id; if (columnMajorData.has(id)) { - let currentRow = columnMajorData.get(id); + const currentRow = columnMajorData.get(id); columnMajorData.set(id, { currentRow, ...value }); } else { columnMajorData.set(id, row); diff --git a/lib/Models/Catalog/CatalogItems/CartoMapV1CatalogItem.ts b/lib/Models/Catalog/CatalogItems/CartoMapV1CatalogItem.ts index 061f2635b29..e17649023bf 100644 --- a/lib/Models/Catalog/CatalogItems/CartoMapV1CatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/CartoMapV1CatalogItem.ts @@ -38,8 +38,7 @@ export class CartoLoadableStratum extends LoadableStratum( static load( catalogItem: CartoMapV1CatalogItem ): Promise { - let queryParameters: { auth_token?: string }; - queryParameters = {}; + const queryParameters: { auth_token?: string } = {}; if (catalogItem.auth_token) { queryParameters.auth_token = catalogItem.auth_token; } diff --git a/lib/Models/Catalog/CatalogItems/CartoMapV3CatalogItem.ts b/lib/Models/Catalog/CatalogItems/CartoMapV3CatalogItem.ts index e71af758eb6..01f45883c5b 100644 --- a/lib/Models/Catalog/CatalogItems/CartoMapV3CatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/CartoMapV3CatalogItem.ts @@ -109,7 +109,7 @@ export default class CartoMapV3CatalogItem extends GeoJsonMixin( q: this.cartoQuery, geo_column: this.cartoGeoColumn }) - ).throwIfError(); + )?.throwIfError(); } // If cartoTableName is defined - use Table API (https://api-docs.carto.com/#6a05d4d7-c6a1-4635-a8de-c91fa5e77fda) else if (this.cartoTableName) { @@ -124,7 +124,7 @@ export default class CartoMapV3CatalogItem extends GeoJsonMixin( response = ( await callCartoApi(url.toString(), this.accessToken) - ).throwIfError(); + )?.throwIfError(); } else { throw new TerriaError({ title: "Invalid Carto V3 config", @@ -176,7 +176,7 @@ export default class CartoMapV3CatalogItem extends GeoJsonMixin( // Download all geoJson files const geojsonResponses = await Promise.all( this.geoJsonUrls.map(async (url) => { - jsonData = (await callCartoApi(url, this.accessToken)).throwIfError(); + jsonData = (await callCartoApi(url, this.accessToken))?.throwIfError(); if (jsonData === undefined) { throw new TerriaError({ @@ -289,7 +289,9 @@ async function callCartoApi(url: string, auth?: string, body?: JsonObject) { ) ); } - } catch {} + } catch { + /* eslint-disable-line no-empty */ + } } return Result.error(e); } diff --git a/lib/Models/Catalog/CatalogItems/Cesium3DTilesCatalogItem.ts b/lib/Models/Catalog/CatalogItems/Cesium3DTilesCatalogItem.ts index 1344bf42262..087a7836342 100644 --- a/lib/Models/Catalog/CatalogItems/Cesium3DTilesCatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/Cesium3DTilesCatalogItem.ts @@ -120,7 +120,7 @@ export default class Cesium3DTilesCatalogItem extends SearchableItemMixin( results: ItemSearchResult[] ): ItemSelectionDisposer { const tileset = this.tileset; - if (tileset === undefined || results.length == 0) { + if (tileset === undefined || results.length === 0) { return () => {}; // empty disposer } diff --git a/lib/Models/Catalog/CatalogItems/GpxCatalogItem.ts b/lib/Models/Catalog/CatalogItems/GpxCatalogItem.ts index a4c0e3b95c1..77e4b039781 100644 --- a/lib/Models/Catalog/CatalogItems/GpxCatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/GpxCatalogItem.ts @@ -43,7 +43,7 @@ class GpxCatalogItem extends GeoJsonMixin(CreateModel(GpxCatalogItemTraits)) { } private loadGpxText(text: string) { - var dom = new DOMParser().parseFromString(text, "text/xml"); + const dom = new DOMParser().parseFromString(text, "text/xml"); return toGeoJSON.gpx(dom); } diff --git a/lib/Models/Catalog/CatalogItems/MapboxVectorTileCatalogItem.ts b/lib/Models/Catalog/CatalogItems/MapboxVectorTileCatalogItem.ts index 6d21833590f..d9245fe91d3 100644 --- a/lib/Models/Catalog/CatalogItems/MapboxVectorTileCatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/MapboxVectorTileCatalogItem.ts @@ -158,7 +158,7 @@ class MapboxVectorTileCatalogItem extends MappableMixin( * - `parsedJsonStyle` */ get paintRules(): PaintRule[] { - let rules: PaintRule[] = []; + const rules: PaintRule[] = []; if (this.layer) { if (this.fillColor) { diff --git a/lib/Models/Catalog/CatalogItems/SenapsLocationsCatalogItem.ts b/lib/Models/Catalog/CatalogItems/SenapsLocationsCatalogItem.ts index f2673a11e84..62acdb0b33c 100644 --- a/lib/Models/Catalog/CatalogItems/SenapsLocationsCatalogItem.ts +++ b/lib/Models/Catalog/CatalogItems/SenapsLocationsCatalogItem.ts @@ -88,6 +88,19 @@ export class SenapsLocationsStratum extends LoadableStratum( static async load(senapsLocationsCatalogItem: SenapsLocationsCatalogItem) { const locationsUrl = senapsLocationsCatalogItem._constructLocationsUrl(); + + function addStreamIds(f: SenapsFeature, index: number, streamData: any) { + const sd: SenapsStreamResponse = streamData[index]; + if (sd.count === 0) { + f.properties.hasStreams = false; + } else if (sd._embedded !== undefined) { + f.properties.streamIds = sd._embedded.streams.map( + (s: SenapsStream) => s.id + ); + f.properties.hasStreams = true; + } + } + try { const locationsResponse: LocationsData = await loadJson( proxyCatalogItemUrl(senapsLocationsCatalogItem, locationsUrl, "0d") @@ -95,7 +108,7 @@ export class SenapsLocationsStratum extends LoadableStratum( const locations = locationsResponse._embedded.locations; const streamPromises = []; - for (var i = 0; i < locations.length; i++) { + for (let i = 0; i < locations.length; i++) { const location = locations[i]; const locationId = location.id; const streamUrl = proxyCatalogItemUrl( @@ -107,18 +120,6 @@ export class SenapsLocationsStratum extends LoadableStratum( } const streamData = await Promise.all(streamPromises); - function addStreamIds(f: SenapsFeature, index: number) { - const sd: SenapsStreamResponse = streamData[index]; - if (sd.count === 0) { - f.properties.hasStreams = false; - } else if (sd._embedded !== undefined) { - f.properties.streamIds = sd._embedded.streams.map( - (s: SenapsStream) => s.id - ); - f.properties.hasStreams = true; - } - } - const fc: SenapsFeatureCollection = { type: "FeatureCollection", features: locations.map((site: SenapsLocation, i: number) => { @@ -133,7 +134,7 @@ export class SenapsLocationsStratum extends LoadableStratum( }, geometry: site.geojson }; - addStreamIds(f, i); + addStreamIds(f, i, streamData); return f; }) }; @@ -286,7 +287,7 @@ class SenapsLocationsCatalogItem extends MappableMixin( message: i18next.t("models.senaps.missingSenapsBaseUrl") }); } - var uri = new URI(`${this.url}/locations`); + const uri = new URI(`${this.url}/locations`); if (this.locationIdFilter !== undefined) { uri.setSearch("id", this.locationIdFilter); } @@ -302,7 +303,7 @@ class SenapsLocationsCatalogItem extends MappableMixin( message: i18next.t("models.senaps.missingSenapsBaseUrl") }); } - var uri = new URI(`${this.url}/streams`); + const uri = new URI(`${this.url}/streams`); if (this.streamIdFilter !== undefined) { uri.setSearch("id", this.streamIdFilter); } diff --git a/lib/Models/Catalog/CatalogReferences/MagdaReference.ts b/lib/Models/Catalog/CatalogReferences/MagdaReference.ts index 4330c04276a..6c8c797917a 100644 --- a/lib/Models/Catalog/CatalogReferences/MagdaReference.ts +++ b/lib/Models/Catalog/CatalogReferences/MagdaReference.ts @@ -237,7 +237,7 @@ export default class MagdaReference extends AccessControlMixin( ) { if (record && override && isJsonObject(override.aspects)) { if (isJsonObject(record.aspects)) { - for (let key in override.aspects) + for (const key in override.aspects) record.aspects[key] = override.aspects[key]; } else { record.aspects = override.aspects; diff --git a/lib/Models/Catalog/Ckan/CkanCatalogGroup.ts b/lib/Models/Catalog/Ckan/CkanCatalogGroup.ts index eade52374a4..ba04862c518 100644 --- a/lib/Models/Catalog/Ckan/CkanCatalogGroup.ts +++ b/lib/Models/Catalog/Ckan/CkanCatalogGroup.ts @@ -117,14 +117,14 @@ export class CkanServerStratum extends LoadableStratum(CkanCatalogGroupTraits) { static async load( catalogGroup: CkanCatalogGroup ): Promise { - var terria = catalogGroup.terria; + const terria = catalogGroup.terria; let ckanServerResponse: CkanServerResponse | undefined = undefined; // Each item in the array causes an independent request to the CKAN, and the results are concatenated - for (var i = 0; i < catalogGroup.filterQuery.length; ++i) { + for (let i = 0; i < catalogGroup.filterQuery.length; ++i) { const filterQuery = catalogGroup.filterQuery[i]; - var uri = new URI(catalogGroup.url) + const uri = new URI(catalogGroup.url) .segment("api/3/action/package_search") .addQuery({ start: 0, rows: 1000, sort: "metadata_created asc" }); @@ -242,7 +242,7 @@ export class CkanServerStratum extends LoadableStratum(CkanCatalogGroupTraits) { dataset: CkanDataset, groupId: string ) { - let group: CatalogGroup | undefined = + const group: CatalogGroup | undefined = this._catalogGroup.terria.getModelById(CatalogGroup, groupId); if (group !== undefined) { group.add(CommonStrata.definition, catalogItem); @@ -293,7 +293,7 @@ export class CkanServerStratum extends LoadableStratum(CkanCatalogGroupTraits) { let filteredResources: CkanResourceWithFormat[] = []; // Track format IDS which multiple resources // As if they do, we will need to make sure that CkanItemReference uses resource name (instead of dataset name) - let formatsWithMultipleResources = new Set(); + const formatsWithMultipleResources = new Set(); if (this._catalogGroup.useSingleResource) { filteredResources = supportedResources[0] ? [supportedResources[0]] : []; @@ -352,7 +352,7 @@ export class CkanServerStratum extends LoadableStratum(CkanCatalogGroupTraits) { this._catalogGroup ); - for (var i = 0; i < filteredResources.length; ++i) { + for (let i = 0; i < filteredResources.length; ++i) { const { resource, format } = filteredResources[i]; const itemId = this.getItemId(ckanDataset, resource); diff --git a/lib/Models/Catalog/Ckan/CkanItemReference.ts b/lib/Models/Catalog/Ckan/CkanItemReference.ts index 388de0beff3..c52e581a420 100644 --- a/lib/Models/Catalog/Ckan/CkanItemReference.ts +++ b/lib/Models/Catalog/Ckan/CkanItemReference.ts @@ -143,14 +143,14 @@ export class CkanDatasetStratum extends LoadableStratum( } } if (this.ckanDataset.geo_coverage !== undefined) { - var bboxString = this.ckanDataset.geo_coverage; - var parts = bboxString.split(","); + const bboxString = this.ckanDataset.geo_coverage; + const parts = bboxString.split(","); if (parts.length === 4) { return createStratumInstance(RectangleTraits, { - west: parseInt(parts[0]), - south: parseInt(parts[1]), - east: parseInt(parts[2]), - north: parseInt(parts[3]) + west: parseInt(parts[0], 10), + south: parseInt(parts[1], 10), + east: parseInt(parts[2], 10), + north: parseInt(parts[3], 10) }); } } @@ -158,7 +158,7 @@ export class CkanDatasetStratum extends LoadableStratum( isDefined(this.ckanDataset.spatial) && this.ckanDataset.spatial !== "" ) { - var gj = JSON.parse(this.ckanDataset.spatial); + const gj = JSON.parse(this.ckanDataset.spatial); if (gj.type === "Polygon" && gj.coordinates[0].length === 5) { return createStratumInstance(RectangleTraits, { west: gj.coordinates[0][0][0], @@ -439,7 +439,7 @@ export interface PreparedSupportedFormat } async function loadCkanDataset(ckanItem: CkanItemReference) { - var uri = new URI(ckanItem.url) + const uri = new URI(ckanItem.url) .segment("api/3/action/package_show") .addQuery({ id: ckanItem.datasetId }); @@ -451,7 +451,7 @@ async function loadCkanDataset(ckanItem: CkanItemReference) { } async function loadCkanResource(ckanItem: CkanItemReference) { - var uri = new URI(ckanItem.url) + const uri = new URI(ckanItem.url) .segment("api/3/action/resource_show") .addQuery({ id: ckanItem.resourceId }); @@ -520,7 +520,7 @@ export function isResourceInSupportedFormats( formats: PreparedSupportedFormat[] ): PreparedSupportedFormat | undefined { if (resource === undefined) return undefined; - let matches: PreparedSupportedFormat[] = []; + const matches: PreparedSupportedFormat[] = []; for (let i = 0; i < formats.length; ++i) { const format = formats[i]; if (resourceIsSupported(resource, format)) return format; diff --git a/lib/Models/Catalog/Esri/ArcGisCatalogGroup.ts b/lib/Models/Catalog/Esri/ArcGisCatalogGroup.ts index b987db9fbf3..3b1aa01588b 100644 --- a/lib/Models/Catalog/Esri/ArcGisCatalogGroup.ts +++ b/lib/Models/Catalog/Esri/ArcGisCatalogGroup.ts @@ -68,8 +68,8 @@ class ArcGisServerStratum extends LoadableStratum(ArcGisCatalogGroupTraits) { static async load( catalogGroup: ArcGisCatalogGroup ): Promise { - var terria = catalogGroup.terria; - var uri = new URI(catalogGroup.url).addQuery("f", "json"); + const terria = catalogGroup.terria; + const uri = new URI(catalogGroup.url).addQuery("f", "json"); return loadJson(proxyCatalogItemUrl(catalogGroup, uri.toString())) .then((arcgisServer: ArcGisServer) => { // Is this really a ArcGisServer REST response? @@ -169,7 +169,7 @@ class ArcGisServerStratum extends LoadableStratum(ArcGisCatalogGroupTraits) { model.setTrait(CommonStrata.definition, "name", replaceUnderscores(folder)); - var uri = new URI(this._catalogGroup.url).segment(folder); + const uri = new URI(this._catalogGroup.url).segment(folder); model.setTrait(CommonStrata.definition, "url", uri.toString()); } @@ -230,7 +230,7 @@ class ArcGisServerStratum extends LoadableStratum(ArcGisCatalogGroupTraits) { replaceUnderscores(localName) ); - var uri = new URI(this._catalogGroup.url) + const uri = new URI(this._catalogGroup.url) .segment(localName) .segment(service.type); model.setTrait(CommonStrata.definition, "url", uri.toString()); @@ -314,7 +314,7 @@ function removePathFromName(basePath: string, name: string) { return name; } - var index = name.indexOf(basePath); + const index = name.indexOf(basePath); if (index === 0) { return name.substring(basePath.length + 1); } else { @@ -323,7 +323,7 @@ function removePathFromName(basePath: string, name: string) { } function getBasePath(catalogGroup: ArcGisCatalogGroup) { - var match = /rest\/services\/(.*)/i.exec(catalogGroup.url || ""); + const match = /rest\/services\/(.*)/i.exec(catalogGroup.url || ""); if (match && match.length > 1) { return match[1]; } else { diff --git a/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogGroup.ts b/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogGroup.ts index d9b7a59bbd2..5fff7242dea 100644 --- a/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogGroup.ts +++ b/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogGroup.ts @@ -120,8 +120,8 @@ export class FeatureServerStratum extends LoadableStratum( static async load( catalogGroup: ArcGisFeatureServerCatalogGroup | ArcGisCatalogGroup ): Promise { - var terria = catalogGroup.terria; - var uri = new URI(catalogGroup.url).addQuery("f", "json"); + const terria = catalogGroup.terria; + const uri = new URI(catalogGroup.url).addQuery("f", "json"); return loadJson(proxyCatalogItemUrl(catalogGroup, uri.toString())) .then((featureServer: FeatureServer) => { @@ -208,7 +208,7 @@ export class FeatureServerStratum extends LoadableStratum( replaceUnderscores(layer.name) ); - var uri = new URI(this._catalogGroup.url).segment(layer.id + ""); // Convert layer id to string as segment(0) means sthg different. + const uri = new URI(this._catalogGroup.url).segment(layer.id + ""); // Convert layer id to string as segment(0) means sthg different. model.setTrait(CommonStrata.definition, "url", uri.toString()); } } diff --git a/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogItem.ts b/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogItem.ts index f0d90021fdb..b7b199cc1ed 100644 --- a/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogItem.ts +++ b/lib/Models/Catalog/Esri/ArcGisFeatureServerCatalogItem.ts @@ -84,7 +84,7 @@ export type SupportedLineStyle = | "esriSLSNull"; // See actual Symbol at https://developers.arcgis.com/web-map-specification/objects/symbol/ -interface Symbol { +interface ISymbol { contentType: string; color?: number[]; outline?: Outline; @@ -119,7 +119,7 @@ interface ClassBreakInfo extends SimpleRenderer { interface ClassBreaksRenderer extends Renderer { field: string; classBreakInfos: ClassBreakInfo[]; - defaultSymbol: Symbol | null; + defaultSymbol: ISymbol | null; } interface UniqueValueInfo extends SimpleRenderer { @@ -135,12 +135,12 @@ interface UniqueValueRenderer extends Renderer { field3?: string; fieldDelimiter?: string; uniqueValueInfos: UniqueValueInfo[]; - defaultSymbol: Symbol | null; + defaultSymbol: ISymbol | null; } interface SimpleRenderer extends Renderer { label?: string; - symbol: Symbol | null; + symbol: ISymbol | null; } interface DrawingInfo { @@ -203,6 +203,8 @@ class FeatureServerStratum extends LoadableStratum( item: ArcGisFeatureServerCatalogItem ): Promise { if (item.url === undefined) { + /* TODO: Should this be returned? */ + /* eslint-disable-next-line no-new */ new FeatureServerStratum(item, undefined, undefined); } const metaUrl = buildMetadataUrl(item); @@ -514,7 +516,7 @@ export default class ArcGisFeatureServerCatalogItem extends GeoJsonMixin( // until we run out of features or hit the limit const featuresPerRequest = this.featuresPerRequest; const maxFeatures = this.maxFeatures; - let combinedEsriLayerJson = await getEsriLayerJson(0); + const combinedEsriLayerJson = await getEsriLayerJson(0); const mapObjectIds = (features: any) => features.map( @@ -663,7 +665,7 @@ function cleanUrl(url: string): string { } function esriSymbolToTableStyle( - symbol?: Symbol | null, + symbol?: ISymbol | null, label?: string | undefined ) { if (!symbol) return {}; diff --git a/lib/Models/Catalog/Esri/ArcGisMapServerCatalogItem.ts b/lib/Models/Catalog/Esri/ArcGisMapServerCatalogItem.ts index 7b5d03fbc92..86b87b82f86 100644 --- a/lib/Models/Catalog/Esri/ArcGisMapServerCatalogItem.ts +++ b/lib/Models/Catalog/Esri/ArcGisMapServerCatalogItem.ts @@ -621,10 +621,10 @@ async function getJson(item: ArcGisMapServerCatalogItem, uri: any) { /* Given a comma-separated string of layer names, returns the layer objects corresponding to them. */ function findLayers(layers: Layer[], names: string | undefined) { function findLayer(layers: Layer[], id: string) { - var idLowerCase = id.toLowerCase(); - var foundByName; - for (var i = 0; i < layers.length; ++i) { - var layer = layers[i]; + const idLowerCase = id.toLowerCase(); + let foundByName; + for (let i = 0; i < layers.length; ++i) { + const layer = layers[i]; if (layer.id.toString() === id) { return layer; } else if ( @@ -703,7 +703,7 @@ function cleanAndProxyUrl( function cleanUrl(url: string) { // Strip off the search portion of the URL - var uri = new URI(url); + const uri = new URI(url); uri.search(""); return uri.toString(); } diff --git a/lib/Models/Catalog/Esri/ArcGisPortalCatalogGroup.ts b/lib/Models/Catalog/Esri/ArcGisPortalCatalogGroup.ts index d856be689c3..f8b3eaf669a 100644 --- a/lib/Models/Catalog/Esri/ArcGisPortalCatalogGroup.ts +++ b/lib/Models/Catalog/Esri/ArcGisPortalCatalogGroup.ts @@ -60,7 +60,7 @@ export class ArcGisPortalStratum extends LoadableStratum( static async load( catalogGroup: ArcGisPortalCatalogGroup ): Promise { - var terria = catalogGroup.terria; + const terria = catalogGroup.terria; let portalGroupsServerResponse: | ArcGisPortalGroupSearchResponse @@ -244,7 +244,7 @@ export class ArcGisPortalStratum extends LoadableStratum( private getGroups(): CatalogGroup[] { if (this._catalogGroup.groupBy === "none") return []; - let groups: CatalogGroup[] = [ + const groups: CatalogGroup[] = [ ...createUngroupedGroup(this), ...createGroupsByPortalGroups(this) ]; @@ -287,7 +287,7 @@ export class ArcGisPortalStratum extends LoadableStratum( dataset: ArcGisItem, groupId: string ) { - let group: CatalogGroup | undefined = + const group: CatalogGroup | undefined = this._catalogGroup.terria.getModelById(CatalogGroup, groupId); if (group !== undefined) { group.add(CommonStrata.definition, catalogItem); diff --git a/lib/Models/Catalog/Esri/ArcGisPortalItemReference.ts b/lib/Models/Catalog/Esri/ArcGisPortalItemReference.ts index 136659b9dd0..0232f355aa9 100644 --- a/lib/Models/Catalog/Esri/ArcGisPortalItemReference.ts +++ b/lib/Models/Catalog/Esri/ArcGisPortalItemReference.ts @@ -384,7 +384,7 @@ interface PreparedSupportedFormat { } async function loadPortalItem(portalItem: ArcGisPortalItemReference) { - var uri = new URI(portalItem._portalRootUrl) + const uri = new URI(portalItem._portalRootUrl) .segment(`/sharing/rest/content/items/${portalItem.itemId}`) .addQuery({ f: "json" }); @@ -400,7 +400,7 @@ async function loadPortalItem(portalItem: ArcGisPortalItemReference) { async function loadAdditionalPortalInfo(portalItem: ArcGisPortalItemReference) { if (portalItem._arcgisItem === undefined) return undefined; const baseUrl = portalItem._portalRootUrl; - var uri = new URI(baseUrl) + const uri = new URI(baseUrl) .segment(`/sharing/rest/content/items/${portalItem._arcgisItem.id}/data`) .addQuery({ f: "json" }); diff --git a/lib/Models/Catalog/Gltf/AssImpCatalogItem.ts b/lib/Models/Catalog/Gltf/AssImpCatalogItem.ts index 674aa99a986..b593bed3a85 100644 --- a/lib/Models/Catalog/Gltf/AssImpCatalogItem.ts +++ b/lib/Models/Catalog/Gltf/AssImpCatalogItem.ts @@ -159,7 +159,7 @@ export default class AssImpCatalogItem const ajs = await assimpjs(); // Create assimpjs FileList object, and add the files - let fileList = new ajs.FileList(); + const fileList = new ajs.FileList(); for (let i = 0; i < fileArrayBuffers.length; i++) { fileList.AddFile( fileArrayBuffers[i].name, @@ -168,10 +168,10 @@ export default class AssImpCatalogItem } // Convert files to GlTf 2 - let result = ajs.ConvertFileList(fileList, "gltf2"); + const result = ajs.ConvertFileList(fileList, "gltf2"); const fileCount = result.FileCount(); - if (!result.IsSuccess() || fileCount == 0) { + if (!result.IsSuccess() || fileCount === 0) { throw TerriaError.from(result.GetErrorCode(), { title: "Failed to convert files to GlTf" }); diff --git a/lib/Models/Catalog/Gtfs/GtfsCatalogItem.ts b/lib/Models/Catalog/Gtfs/GtfsCatalogItem.ts index 27883c4e04c..348670009e2 100644 --- a/lib/Models/Catalog/Gtfs/GtfsCatalogItem.ts +++ b/lib/Models/Catalog/Gtfs/GtfsCatalogItem.ts @@ -137,14 +137,14 @@ export default class GtfsCatalogItem extends UrlMixin( // Although technically the timestamp property is optional, if none is // present we'll show the record. const vehicleMap = new Map(); - for (var i = 0; i < feedEntities.length; ++i) { + for (let i = 0; i < feedEntities.length; ++i) { const entity: FeedEntity = feedEntities[i]; const item: VehicleData = this.convertFeedEntityToBillboardData(entity); if (item && item.position && item.featureInfo) { const vehicleInfo = item.featureInfo.get("entity").vehicle.vehicle; if (vehicleMap.has(vehicleInfo.id) && vehicleInfo.timestamp) { - let existingRecord = vehicleMap.get(vehicleInfo.id); + const existingRecord = vehicleMap.get(vehicleInfo.id); if (existingRecord.timestamp < vehicleInfo.timestamp) { vehicleMap.set(vehicleInfo.id, item); } @@ -163,7 +163,7 @@ export default class GtfsCatalogItem extends UrlMixin( // Convert the GTFS protobuf into a more useful shape const vehicleData: VehicleData[] = this.convertManyFeedEntitiesToBillboardData(this.gtfsFeedEntities); - for (let data of vehicleData) { + for (const data of vehicleData) { if (data.sourceId === undefined) { continue; } @@ -254,7 +254,7 @@ export default class GtfsCatalogItem extends UrlMixin( if (data.featureInfo !== undefined && data.featureInfo !== null) { entity.properties = new PropertyBag(); - for (let key of data.featureInfo.keys()) { + for (const key of data.featureInfo.keys()) { entity.properties.addProperty(key, data.featureInfo.get(key)); } } @@ -414,12 +414,12 @@ export default class GtfsCatalogItem extends UrlMixin( } protected convertFeedEntityToBillboardData(entity: FeedEntity): VehicleData { - if (entity.id == undefined) { + if (entity.id === undefined) { return {}; } let position = undefined; let orientation = undefined; - let featureInfo: Map = new Map(); + const featureInfo: Map = new Map(); if ( entity.vehicle !== null && entity.vehicle !== undefined && @@ -452,7 +452,7 @@ export default class GtfsCatalogItem extends UrlMixin( } // Add the values that the feature info template gets populated with - for (let field of GtfsCatalogItem.FEATURE_INFO_TEMPLATE_FIELDS) { + for (const field of GtfsCatalogItem.FEATURE_INFO_TEMPLATE_FIELDS) { featureInfo.set(field, prettyPrintGtfsEntityField(field, entity)); } featureInfo.set("entity", entity); diff --git a/lib/Models/Catalog/Gtfs/prettyPrintGtfsEntityField.ts b/lib/Models/Catalog/Gtfs/prettyPrintGtfsEntityField.ts index 36e374e495f..90cd11ff1d9 100644 --- a/lib/Models/Catalog/Gtfs/prettyPrintGtfsEntityField.ts +++ b/lib/Models/Catalog/Gtfs/prettyPrintGtfsEntityField.ts @@ -39,6 +39,7 @@ export default function prettyPrintGtfsEntityField( return "Not accepting passengers"; } } + break; } case "speed#km": { return (_get(entity, "vehicle.position.speed", 0) * 3.6).toFixed(2); diff --git a/lib/Models/Catalog/Ows/CswCatalogGroup.ts b/lib/Models/Catalog/Ows/CswCatalogGroup.ts index 7365e171267..eff455a8cbb 100644 --- a/lib/Models/Catalog/Ows/CswCatalogGroup.ts +++ b/lib/Models/Catalog/Ows/CswCatalogGroup.ts @@ -60,7 +60,7 @@ export interface BriefRecord { type?: string; } -export type CswURI = String & { +export type CswURI = string & { scheme?: string; protocol?: string; description?: string; @@ -304,12 +304,12 @@ class CswStratum extends LoadableStratum(CswCatalogGroupTraits) { // Get next start position - or stop pageing const nextRecord = typeof json?.SearchResults?.nextRecord === "string" - ? parseInt(json?.SearchResults?.nextRecord ?? "0") + ? parseInt(json?.SearchResults?.nextRecord ?? "0", 10) : json?.SearchResults?.nextRecord; const numberOfRecordsMatched = typeof json?.SearchResults?.numberOfRecordsMatched === "string" - ? parseInt(json?.SearchResults?.numberOfRecordsMatched ?? "0") + ? parseInt(json?.SearchResults?.numberOfRecordsMatched ?? "0", 10) : json?.SearchResults?.numberOfRecordsMatched; if ( !isDefined(nextRecord) || @@ -656,7 +656,7 @@ function findGroup( metadataGroups: MetadataGroup[], record: Record ): MetadataGroup | undefined { - for (var i = 0; i < metadataGroups.length; i++) { + for (let i = 0; i < metadataGroups.length; i++) { const group = metadataGroups[i]; if (group.field) { const fields = filterOutUndefined(toArray(record[group.field]) ?? []); @@ -678,7 +678,7 @@ function findGroup( function matchValue(value: string, recordValue: string, regex?: boolean) { if (isDefined(regex) && regex) { // regular expression so parse it and check string against it - var regExp = new RegExp(value); + const regExp = new RegExp(value); return regExp.test(recordValue); } else { return value === recordValue; diff --git a/lib/Models/Catalog/Ows/SensorObservationServiceCatalogItem.ts b/lib/Models/Catalog/Ows/SensorObservationServiceCatalogItem.ts index 02a3620d00e..a9fe09e5c86 100644 --- a/lib/Models/Catalog/Ows/SensorObservationServiceCatalogItem.ts +++ b/lib/Models/Catalog/Ows/SensorObservationServiceCatalogItem.ts @@ -72,8 +72,8 @@ interface ObservationPoint { } interface MeasurementTimeValuePair { - time: Object | string; - value: Object | string; + time: object | string; + value: object | string; } StratumOrder.addLoadStratum(TableAutomaticStylesStratum.stratumName); @@ -469,8 +469,8 @@ export default class SensorObservationServiceCatalogItem extends TableMixin( if (!points) return; if (!Array.isArray(points)) points = [points]; - var measurements = points.map((point) => point.MeasurementTVP); // TVP = Time value pairs, I think. - var featureIdentifier = + const measurements = points.map((point) => point.MeasurementTVP); // TVP = Time value pairs, I think. + const featureIdentifier = observation.featureOfInterest["xlink:href"] || ""; datesCol.push( ...measurements.map((measurement) => @@ -633,7 +633,7 @@ function createChartColumn( identifier: string, name: string | undefined ): string { - const nameAttr = name == undefined ? "" : `name="${name}"`; + const nameAttr = name === undefined ? "" : `name="${name}"`; // The API that provides the chart data is a SOAP API, and the download button is essentially just a link, so when you click it you get an error page. // can-download="false" will disable this broken download button. return ``; @@ -660,9 +660,9 @@ async function loadSoapBody( return; } - var json = xml2json(responseXml); + const json = xml2json(responseXml); if (json.Exception) { - var errorMessage = i18next.t( + let errorMessage = i18next.t( "models.sensorObservationService.unknownError" ); if (json.Exception.ExceptionText) { @@ -728,10 +728,11 @@ function addDurationToIso8601( scratchJulianDate ); break; - case "y": + case "y": { const days = Math.round(duration * 365); julianDate = JulianDate.addDays(julianDate, days, scratchJulianDate); break; + } default: throw new DeveloperError( 'Unknown duration type "' + durationString + '" (use s, h, d or y)' @@ -750,7 +751,7 @@ function addDurationToIso8601( */ function convertObjectToNameValueArray(parameters: any): NameValue[] { return Object.keys(parameters).reduce((result, key) => { - var values = parameters[key]; + let values = parameters[key]; if (!Array.isArray(values)) { values = [values]; } diff --git a/lib/Models/Catalog/Ows/WebFeatureServiceCapabilities.ts b/lib/Models/Catalog/Ows/WebFeatureServiceCapabilities.ts index 785f13a9f63..c5e8e2ef968 100644 --- a/lib/Models/Catalog/Ows/WebFeatureServiceCapabilities.ts +++ b/lib/Models/Catalog/Ows/WebFeatureServiceCapabilities.ts @@ -24,7 +24,7 @@ export interface FeatureType { export function getRectangleFromLayer( layer: FeatureType ): StratumFromTraits | undefined { - var bbox = layer.WGS84BoundingBox; + const bbox = layer.WGS84BoundingBox; if (bbox) { return { west: bbox.westBoundLongitude, @@ -124,7 +124,7 @@ function getFeatureTypes(json: any): FeatureType[] { } function getOutputTypes(json: any): string[] | undefined { - let outputTypes = json.OperationsMetadata?.Operation?.find( + const outputTypes = json.OperationsMetadata?.Operation?.find( (op: any) => op.name === "GetFeature" )?.Parameter?.find((p: any) => p.name === "outputFormat")?.Value; @@ -147,7 +147,7 @@ interface SrsNamesForLayer { * TODO: For catalog items that specify which layer we are interested in, why build the array describing the srsNames for all the other layers too? */ function getSrsNames(json: any): SrsNamesForLayer[] | undefined { - let layers = json.FeatureTypeList?.FeatureType; + const layers = json.FeatureTypeList?.FeatureType; let srsNamesByLayer: SrsNamesForLayer[] = []; if (Array.isArray(layers)) { srsNamesByLayer = layers.map(buildSrsNameObject); @@ -162,7 +162,7 @@ function getSrsNames(json: any): SrsNamesForLayer[] | undefined { * @param layer */ function buildSrsNameObject(layer: any): SrsNamesForLayer { - let srsNames: string[] = []; + const srsNames: string[] = []; if (isJsonString(layer.DefaultSRS)) srsNames.push(layer.DefaultSRS); if (Array.isArray(layer.OtherSRS)) diff --git a/lib/Models/Catalog/Ows/WebFeatureServiceCatalogItem.ts b/lib/Models/Catalog/Ows/WebFeatureServiceCatalogItem.ts index f9e3f8b0308..261dfa1fb9a 100644 --- a/lib/Models/Catalog/Ows/WebFeatureServiceCatalogItem.ts +++ b/lib/Models/Catalog/Ows/WebFeatureServiceCatalogItem.ts @@ -431,7 +431,9 @@ class WebFeatureServiceCatalogItem extends GetCapabilitiesMixin( let errorMessage: string | undefined; try { errorMessage = xml2json(getFeatureResponse).Exception?.ExceptionText; - } catch {} + } catch { + /* eslint-disable-line no-empty */ + } const originalError = isDefined(errorMessage) ? new TerriaError({ @@ -454,7 +456,7 @@ class WebFeatureServiceCatalogItem extends GetCapabilitiesMixin( }); } - let geojsonData = + const geojsonData = this.outputFormat === "JSON" ? JSON.parse(getFeatureResponse) : gmlToGeoJson(getFeatureResponse); diff --git a/lib/Models/Catalog/Ows/WebMapServiceCapabilities.ts b/lib/Models/Catalog/Ows/WebMapServiceCapabilities.ts index bffbafb677a..12bb1ea326f 100644 --- a/lib/Models/Catalog/Ows/WebMapServiceCapabilities.ts +++ b/lib/Models/Catalog/Ows/WebMapServiceCapabilities.ts @@ -132,7 +132,7 @@ type Mutable = { -readonly [P in keyof T]: T[P] }; export function getRectangleFromLayer( layer: CapabilitiesLayer ): StratumFromTraits | undefined { - var egbb = layer.EX_GeographicBoundingBox; // required in WMS 1.3.0 + const egbb = layer.EX_GeographicBoundingBox; // required in WMS 1.3.0 if (egbb) { return { west: egbb.westBoundLongitude, @@ -141,7 +141,7 @@ export function getRectangleFromLayer( north: egbb.northBoundLatitude }; } else { - var llbb = layer.LatLonBoundingBox; // required in WMS 1.0.0 through 1.1.1 + const llbb = layer.LatLonBoundingBox; // required in WMS 1.0.0 through 1.1.1 if (llbb) { return { west: llbb.minx, diff --git a/lib/Models/Catalog/Ows/WebMapServiceCapabilitiesStratum.ts b/lib/Models/Catalog/Ows/WebMapServiceCapabilitiesStratum.ts index 4426c8d540b..ed847705c89 100644 --- a/lib/Models/Catalog/Ows/WebMapServiceCapabilitiesStratum.ts +++ b/lib/Models/Catalog/Ows/WebMapServiceCapabilitiesStratum.ts @@ -376,11 +376,11 @@ export default class WebMapServiceCapabilitiesStratum extends LoadableStratum( result.push({ layerName: layerName, styles: styles.map((style) => { - var wmsLegendUrl = isReadOnlyArray(style.LegendURL) + const wmsLegendUrl = isReadOnlyArray(style.LegendURL) ? style.LegendURL[0] : style.LegendURL; - var legendUri, legendMimeType; + let legendUri, legendMimeType; if ( wmsLegendUrl && wmsLegendUrl.OnlineResource && @@ -760,7 +760,7 @@ export default class WebMapServiceCapabilitiesStratum extends LoadableStratum( get discreteTimes(): { time: string; tag: string | undefined }[] | undefined { const result = []; - for (let layer of this.capabilitiesLayers.values()) { + for (const layer of this.capabilitiesLayers.values()) { if (!layer) { continue; } @@ -943,7 +943,7 @@ export default class WebMapServiceCapabilitiesStratum extends LoadableStratum( // This is used to flag subsets (dimensions) which have multiple values // Each element in this array represents the **actual** value used for a subset which has multiple values - let duplicateSubsetValues: StratumFromTraits[] = []; + const duplicateSubsetValues: StratumFromTraits[] = []; // Get dimensionSubsets const dimensionSubsets: { key: string; value: string }[] = []; diff --git a/lib/Models/Catalog/Ows/WebMapServiceCatalogGroup.ts b/lib/Models/Catalog/Ows/WebMapServiceCatalogGroup.ts index 58517a153ae..5355642dc71 100644 --- a/lib/Models/Catalog/Ows/WebMapServiceCatalogGroup.ts +++ b/lib/Models/Catalog/Ows/WebMapServiceCatalogGroup.ts @@ -388,7 +388,7 @@ export default class WebMapServiceCatalogGroup extends GetCapabilitiesMixin( } protected async forceLoadMembers(): Promise { - let getCapabilitiesStratum = ( + const getCapabilitiesStratum = ( this.strata.get(GetCapabilitiesMixin.getCapabilitiesStratumName) ); if (getCapabilitiesStratum !== undefined) { diff --git a/lib/Models/Catalog/Ows/WebMapServiceCatalogItem.ts b/lib/Models/Catalog/Ows/WebMapServiceCatalogItem.ts index 44ae738148d..54f2b0ad886 100644 --- a/lib/Models/Catalog/Ows/WebMapServiceCatalogItem.ts +++ b/lib/Models/Catalog/Ows/WebMapServiceCatalogItem.ts @@ -653,7 +653,7 @@ class WebMapServiceCatalogItem // Try to set selectedId to value stored in `styles` trait for this `layerIndex` // The `styles` parameter is CSV, a style for each layer - let selectedId = this.styles?.split(",")?.[layerIndex]; + const selectedId = this.styles?.split(",")?.[layerIndex]; return { name, diff --git a/lib/Models/Catalog/Ows/WebMapTileServiceCatalogItem.ts b/lib/Models/Catalog/Ows/WebMapTileServiceCatalogItem.ts index 57cb6735239..ac9933b981d 100644 --- a/lib/Models/Catalog/Ows/WebMapTileServiceCatalogItem.ts +++ b/lib/Models/Catalog/Ows/WebMapTileServiceCatalogItem.ts @@ -262,7 +262,7 @@ class GetCapabilitiesStratum extends LoadableStratum( @computed get capabilitiesLayer(): Readonly { - let result = this.catalogItem.layer + const result = this.catalogItem.layer ? this.capabilities.findLayer(this.catalogItem.layer) : undefined; return result; @@ -287,11 +287,10 @@ class GetCapabilitiesStratum extends LoadableStratum( result.push({ layerName: layer?.Identifier, styles: styles.map((style: CapabilitiesStyle) => { - let wmtsLegendUrl: WmtsCapabilitiesLegend | undefined = isReadOnlyArray( - style.LegendURL - ) - ? style.LegendURL[0] - : style.LegendURL; + const wmtsLegendUrl: WmtsCapabilitiesLegend | undefined = + isReadOnlyArray(style.LegendURL) + ? style.LegendURL[0] + : style.LegendURL; let legendUri, legendMimeType; if (wmtsLegendUrl && wmtsLegendUrl["xlink:href"]) { legendUri = new URI(decodeURIComponent(wmtsLegendUrl["xlink:href"])); @@ -352,9 +351,9 @@ class GetCapabilitiesStratum extends LoadableStratum( continue; } - var levelZeroTopLeftCorner = levelZeroMatrix.TopLeftCorner.split(" "); - var startX = parseFloat(levelZeroTopLeftCorner[0]); - var startY = parseFloat(levelZeroTopLeftCorner[1]); + const levelZeroTopLeftCorner = levelZeroMatrix.TopLeftCorner.split(" "); + const startX = parseFloat(levelZeroTopLeftCorner[0]); + const startY = parseFloat(levelZeroTopLeftCorner[1]); const rectangleInMeters = standardTilingScheme.rectangleToNativeRectangle( standardTilingScheme.rectangle ); diff --git a/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunction.ts b/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunction.ts index d11037c162b..69ea0ca6a0a 100644 --- a/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunction.ts +++ b/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunction.ts @@ -272,7 +272,7 @@ export default class WebProcessingServiceCatalogFunction extends XmlRequestMixin protected async createJob(id: string) { const job = new WebProcessingServiceCatalogFunctionJob(id, this.terria); - let dataInputs = filterOutUndefined( + const dataInputs = filterOutUndefined( await Promise.all( this.functionParameters .filter((p) => isDefined(p.value) && p.value !== null) @@ -332,7 +332,7 @@ export default class WebProcessingServiceCatalogFunction extends XmlRequestMixin } async convertParameterToInput(parameter: FunctionParameter) { - let converter = parameterTypeToConverter(parameter); + const converter = parameterTypeToConverter(parameter); const result = converter?.parameterToInput(parameter); if (!isDefined(result)) { @@ -514,8 +514,8 @@ const RectangleConverter = { ) { return undefined; } - var code = Reproject.crsStringToCode(input.BoundingBoxData.Default.CRS); - var usedCrs = input.BoundingBoxData.Default.CRS; + let code = Reproject.crsStringToCode(input.BoundingBoxData.Default.CRS); + let usedCrs = input.BoundingBoxData.Default.CRS; // Find out if Terria's CRS is supported. if ( code !== Reproject.TERRIA_CRS && @@ -656,7 +656,7 @@ function simpleGeoJsonDataConverter(schemaType: string, klass: any) { return undefined; } - var schema = input.ComplexData.Default.Format.Schema; + const schema = input.ComplexData.Default.Format.Schema; if (schema.indexOf("http://geojson.org/geojson-spec.html#") !== 0) { return undefined; } diff --git a/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunctionJob.ts b/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunctionJob.ts index 9a6c8cd92a9..b903c7763ee 100644 --- a/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunctionJob.ts +++ b/lib/Models/Catalog/Ows/WebProcessingServiceCatalogFunctionJob.ts @@ -430,19 +430,19 @@ export default class WebProcessingServiceCatalogFunctionJob extends XmlRequestMi private async createCatalogItemFromJson(json: any) { let itemJson = json; - try { - if ( - this.forceConvertResultsToV8 || - // If startData.version has version 0.x.x - user catalog-converter to convert result - ("version" in itemJson && - typeof itemJson.version === "string" && - itemJson.version.startsWith("0")) - ) { - itemJson = await convertResultV7toV8(json); - } - } catch (e) { - throw e; + + if ( + this.forceConvertResultsToV8 || + // If startData.version has version 0.x.x - user catalog-converter to convert result + ("version" in itemJson && + typeof itemJson.version === "string" && + itemJson.version.startsWith("0")) + ) { + itemJson = await convertResultV7toV8(json).catch((e) => { + throw e; + }); } + const catalogItem = upsertModelFromJson( CatalogMemberFactory, this.terria, @@ -473,7 +473,7 @@ function formatOutputValue(title: string, value: string | undefined) { const values = value.split(","); return values.reduce(function (previousValue, currentValue) { - if (value.match(/[.\/](png|jpg|jpeg|gif|svg)/i)) { + if (value.match(/[./](png|jpg|jpeg|gif|svg)/i)) { return ( previousValue + ' { - let text = annotation.texts?.[i18next.language] ?? annotation.text!; + const text = annotation.texts?.[i18next.language] ?? annotation.text!; const title = text.includes("|") ? text.split("|")[0] : undefined; const url = text.includes("|") ? text.split("|")[1] : text; return createStratumInstance(MetadataUrlTraits, { title, url }); @@ -292,7 +292,7 @@ export class SdmxJsonDataflowStratum extends LoadableStratum( let options: StratumFromTraits[] = []; // Get codes by merging allowedOptionIds with codelist - let filteredCodesList = + const filteredCodesList = (allowedOptionIds.size > 0 ? codelist?.codes?.filter((code) => allowedOptionIds.has(code.id!) @@ -399,7 +399,7 @@ export class SdmxJsonDataflowStratum extends LoadableStratum( ?.filter((override) => override.type === "unit-measure" && override.id) .map((override) => { // Find dimension/attribute id with concept or codelist override - let dimOrAttr = + const dimOrAttr = this.getAttributionWithConceptOrCodelist(override.id!) ?? this.getDimensionWithConceptOrCodelist(override.id!); @@ -424,7 +424,7 @@ export class SdmxJsonDataflowStratum extends LoadableStratum( ); // Try to get option label if it exists - let frequency = + const frequency = frequencyDim?.options.find((o) => o.id === frequencyDim.selectedId) ?.name ?? frequencyDim?.id; @@ -459,7 +459,7 @@ export class SdmxJsonDataflowStratum extends LoadableStratum( ) .map((override) => { // Find dimension/attribute id with concept or codelist - let dimOrAttr = + const dimOrAttr = this.getAttributionWithConceptOrCodelist(override.id!) ?? this.getDimensionWithConceptOrCodelist(override.id!); @@ -823,7 +823,7 @@ export class SdmxJsonDataflowStratum extends LoadableStratum( const conceptId = conceptUrn?.descendantIds?.[0]; if (!isDefined(conceptId)) return; - let resolvedConceptScheme = + const resolvedConceptScheme = typeof conceptSchemeId === "string" ? this.getConceptScheme(conceptSchemeId) : conceptSchemeId; diff --git a/lib/Models/Catalog/SdmxJson/SdmxJsonServerStratum.ts b/lib/Models/Catalog/SdmxJson/SdmxJsonServerStratum.ts index 4c66d76e1c2..60c71080ad4 100644 --- a/lib/Models/Catalog/SdmxJson/SdmxJsonServerStratum.ts +++ b/lib/Models/Catalog/SdmxJson/SdmxJsonServerStratum.ts @@ -47,7 +47,7 @@ export class SdmxServerStratum extends LoadableStratum(SdmxCatalogGroupTraits) { catalogGroup: SdmxCatalogGroup ): Promise { // Load agency schemes (may be undefined) - let agencySchemes = ( + const agencySchemes = ( await loadSdmxJsonStructure( proxyCatalogItemUrl(catalogGroup, `${catalogGroup.url}/agencyscheme/`), true @@ -55,7 +55,7 @@ export class SdmxServerStratum extends LoadableStratum(SdmxCatalogGroupTraits) { )?.data?.agencySchemes; // Load category schemes (may be undefined) - let categorySchemeResponse = await loadSdmxJsonStructure( + const categorySchemeResponse = await loadSdmxJsonStructure( proxyCatalogItemUrl( catalogGroup, `${catalogGroup.url}/categoryscheme?references=parentsandsiblings` @@ -376,7 +376,7 @@ export class SdmxServerStratum extends LoadableStratum(SdmxCatalogGroupTraits) { id?: string ) { if (!isDefined(id)) return; - let resolvedCategoryScheme = + const resolvedCategoryScheme = typeof categoryScheme === "string" ? this.getCategoryScheme(categoryScheme) : categoryScheme; diff --git a/lib/Models/Catalog/registerCatalogMembers.ts b/lib/Models/Catalog/registerCatalogMembers.ts index f6ffa854679..bf0040e7cfa 100644 --- a/lib/Models/Catalog/registerCatalogMembers.ts +++ b/lib/Models/Catalog/registerCatalogMembers.ts @@ -284,17 +284,17 @@ export default function registerCatalogMembers() { // These items work by trying to match a URL, then loading the data. If it fails, they move on. UrlToCatalogMemberMapping.register( - matchesUrl(/\/wms|\=wms/i), + matchesUrl(/\/wms|=wms/i), WebMapServiceCatalogGroup.type, true ); UrlToCatalogMemberMapping.register( - matchesUrl(/\/wfs|\=wfs/i), + matchesUrl(/\/wfs|=wfs/i), WebFeatureServiceCatalogGroup.type, true ); UrlToCatalogMemberMapping.register( - matchesUrl(/\/wmts|\=wmts/i), + matchesUrl(/\/wmts|=wmts/i), WebMapTileServiceCatalogGroup.type, true ); @@ -397,7 +397,7 @@ function matchesUrl(regex: RegExp) { } export function matchesExtension(extension: string) { - var regex = new RegExp("\\." + extension + "$", "i"); + const regex = new RegExp("\\." + extension + "$", "i"); return function (url: string) { return Boolean(url.match(regex)); }; diff --git a/lib/Models/Cesium.ts b/lib/Models/Cesium.ts index f54115c838b..65b6bda4908 100644 --- a/lib/Models/Cesium.ts +++ b/lib/Models/Cesium.ts @@ -100,16 +100,16 @@ type CreditDisplayElement = { }; // Intermediary -var cartesian3Scratch = new Cartesian3(); -var enuToFixedScratch = new Matrix4(); -var southwestScratch = new Cartesian3(); -var southeastScratch = new Cartesian3(); -var northeastScratch = new Cartesian3(); -var northwestScratch = new Cartesian3(); -var southwestCartographicScratch = new Cartographic(); -var southeastCartographicScratch = new Cartographic(); -var northeastCartographicScratch = new Cartographic(); -var northwestCartographicScratch = new Cartographic(); +const cartesian3Scratch = new Cartesian3(); +const enuToFixedScratch = new Matrix4(); +const southwestScratch = new Cartesian3(); +const southeastScratch = new Cartesian3(); +const northeastScratch = new Cartesian3(); +const northwestScratch = new Cartesian3(); +const southwestCartographicScratch = new Cartographic(); +const southeastCartographicScratch = new Cartographic(); +const northeastCartographicScratch = new Cartographic(); +const northwestCartographicScratch = new Cartographic(); export default class Cesium extends GlobeOrMap { readonly type = "Cesium"; @@ -505,7 +505,9 @@ export default class Cesium extends GlobeOrMap { creditDisplay.destroy = () => { try { creditDisplayOldDestroy(); - } catch (err) {} + } catch (err) { + /* TODO: handle Error */ + } }; const creditDisplayOldEndFrame = creditDisplay.endFrame; @@ -668,7 +670,7 @@ export default class Cesium extends GlobeOrMap { } // 2. Add new data sources - for (let ds of availableDataSources) { + for (const ds of availableDataSources) { if (!dataSources.contains(ds)) { await dataSources.add(ds); } @@ -768,7 +770,9 @@ export default class Cesium extends GlobeOrMap { const fnArray = this._3dTilesetEventListeners.get(primitive); try { fnArray?.forEach((fn) => fn()); // Run the remover functions - } catch (error) {} + } catch (error) { + /* TODO: handle error */ + } this._3dTilesetEventListeners.delete(primitive); // Remove the item for this tileset from our eventListener reference storage array this._updateTilesLoadingIndeterminate(false); // reset progress bar loading state to false. Any new tile loading event will restart it to account for multiple currently loading 3DTilesets. @@ -986,7 +990,7 @@ export default class Cesium extends GlobeOrMap { * @returns Camera */ private cloneCamera(camera: Camera): Camera { - let result = new Camera(this.scene); + const result = new Camera(this.scene); Cartesian3.clone(camera.position, result.position); Cartesian3.clone(camera.direction, result.direction); Cartesian3.clone(camera.up, result.up); @@ -1340,17 +1344,16 @@ export default class Cesium extends GlobeOrMap { providerCoords: ProviderCoordsMap ) { const promises: (Promise | undefined)[] = []; + function hasUrl(o: any): o is { url: string } { + return typeof o?.url === "string"; + } for (let i = this.scene.imageryLayers.length - 1; i >= 0; i--) { const imageryLayer = this.scene.imageryLayers.get(i); const imageryProvider = imageryLayer.imageryProvider; - function hasUrl(o: any): o is { url: string } { - return typeof o?.url === "string"; - } - if (hasUrl(imageryProvider) && providerCoords[imageryProvider.url]) { - var coords = providerCoords[imageryProvider.url]; + const coords = providerCoords[imageryProvider.url]; promises.push( imageryProvider .pickFeatures( @@ -1729,7 +1732,7 @@ export default class Cesium extends GlobeOrMap { } } -var boundingSphereScratch = new BoundingSphere(); +const boundingSphereScratch = new BoundingSphere(); function zoomToDataSource( cesium: Cesium, @@ -1744,11 +1747,11 @@ function zoomToDataSource( return false; } - var entities = target.entities.values; + const entities = target.entities.values; - var boundingSpheres = []; - for (var i = 0, len = entities.length; i < len; i++) { - var state = BoundingSphereState.PENDING; + const boundingSpheres = []; + for (let i = 0, len = entities.length; i < len; i++) { + let state = BoundingSphereState.PENDING; try { // TODO: missing Cesium type info state = (dataSourceDisplay).getBoundingSphere( @@ -1756,7 +1759,9 @@ function zoomToDataSource( false, boundingSphereScratch ); - } catch (e) {} + } catch (e) { + /* TODO: handle error */ + } if (state === BoundingSphereState.PENDING) { return false; @@ -1769,7 +1774,7 @@ function zoomToDataSource( // Test if boundingSpheres is empty to avoid zooming to nowhere if (boundingSpheres.length > 0 && _lastZoomTarget === target) { - var boundingSphere = + const boundingSphere = BoundingSphere.fromBoundingSpheres(boundingSpheres); flyToPromise = flyToBoundingSpherePromise( cesium.scene.camera, diff --git a/lib/Models/Definition/addModelStrataView.ts b/lib/Models/Definition/addModelStrataView.ts index 42b80538182..61cf9b6aab4 100644 --- a/lib/Models/Definition/addModelStrataView.ts +++ b/lib/Models/Definition/addModelStrataView.ts @@ -19,6 +19,8 @@ export default function addModelStrataView< ): ModelPropertiesFromTraits>; export default function addModelStrataView< T extends TraitsConstructor + /* TODO: Fix this overload type */ + /* eslint-disable-next-line @typescript-eslint/ban-types */ >(model: Function, Traits: T): ModelPropertiesFromTraits>; export default function addModelStrataView< T extends TraitsConstructor diff --git a/lib/Models/Definition/createCombinedModel.ts b/lib/Models/Definition/createCombinedModel.ts index cb94f03c75b..a7082fa817b 100644 --- a/lib/Models/Definition/createCombinedModel.ts +++ b/lib/Models/Definition/createCombinedModel.ts @@ -132,7 +132,7 @@ class CombinedStrata implements Map> { const result = new Map>(); // Add the strata fro the top - for (let key of this.top.strata.keys()) { + for (const key of this.top.strata.keys()) { const topStratum = this.top.strata.get(key); const bottomStratum = this.bottom.strata.get(key); @@ -159,7 +159,7 @@ class CombinedStrata implements Map> { } // Add any strata that are only in the bottom - for (let key of this.bottom.strata.keys()) { + for (const key of this.bottom.strata.keys()) { if (this.top.strata.has(key)) { continue; } diff --git a/lib/Models/Definition/upsertModelFromJson.ts b/lib/Models/Definition/upsertModelFromJson.ts index c8c051b5083..9ef4198f575 100644 --- a/lib/Models/Definition/upsertModelFromJson.ts +++ b/lib/Models/Definition/upsertModelFromJson.ts @@ -62,7 +62,7 @@ export default function upsertModelFromJson( ); } - let id = (parentId || "") + "/" + localId; + const id = (parentId || "") + "/" + localId; let idIncrement = 1; uniqueId = id; model = terria.getModelById(BaseModel, uniqueId); diff --git a/lib/Models/FunctionParameters/PointParameter.ts b/lib/Models/FunctionParameters/PointParameter.ts index 4fba82e677f..6f7f3eba1fb 100644 --- a/lib/Models/FunctionParameters/PointParameter.ts +++ b/lib/Models/FunctionParameters/PointParameter.ts @@ -30,7 +30,7 @@ export default class PointParameter * Get feature as geojson for display on map. */ static getGeoJsonFeature(value: CartographicPoint): Feature { - var coordinates = [ + const coordinates = [ CesiumMath.toDegrees(value.longitude), CesiumMath.toDegrees(value.latitude), value.height diff --git a/lib/Models/Internationalization.ts b/lib/Models/Internationalization.ts index 9eef538c265..116f6ade138 100644 --- a/lib/Models/Internationalization.ts +++ b/lib/Models/Internationalization.ts @@ -35,7 +35,7 @@ export interface LanguageConfiguration { enabled: boolean; debug: boolean; react: ReactOptions; - languages: Object; + languages: object; fallbackLanguage: string; changeLanguageOnStartWhen: string[]; diff --git a/lib/Models/ItemSearchProviders/IndexedItemSearchProvider.ts b/lib/Models/ItemSearchProviders/IndexedItemSearchProvider.ts index e79c6a63ad5..f2840cfa569 100644 --- a/lib/Models/ItemSearchProviders/IndexedItemSearchProvider.ts +++ b/lib/Models/ItemSearchProviders/IndexedItemSearchProvider.ts @@ -238,7 +238,7 @@ export default class IndexedItemSearchProvider extends ItemSearchProvider { // The record can have a bunch of arbitrary properties and a few known // properties. We use the latitude, longitude, height & radius for // constructing a zoom target for the search result. - let { latitude, longitude, height, ...properties } = record; + const { latitude, longitude, height, ...properties } = record; const _latitude = parseFloat(latitude); const _longitude = parseFloat(longitude); const _featureHeight = parseFloat(height); diff --git a/lib/Models/Leaflet.ts b/lib/Models/Leaflet.ts index 84af5588269..674783e007e 100644 --- a/lib/Models/Leaflet.ts +++ b/lib/Models/Leaflet.ts @@ -256,7 +256,7 @@ export default class Leaflet extends GlobeOrMap { */ private _initProgressEvent() { const onTileLoadChange = () => { - var tilesLoadingCount = 0; + let tilesLoadingCount = 0; this.map.eachLayer(function (layerOrGridlayer) { // _tiles is protected but our knockout-loading-logic accesses it here anyway @@ -477,7 +477,7 @@ export default class Leaflet extends GlobeOrMap { } // 2. Add new data sources - for (let ds of availableDataSources) { + for (const ds of availableDataSources) { if (!dataSources.contains(ds) && ds.show) { await dataSources.add(ds); } @@ -608,7 +608,7 @@ export default class Leaflet extends GlobeOrMap { const owner = entity.entityCollection.owner; if ( owner instanceof DataSource && - owner.name == GlobeOrMap._featureHighlightName + owner.name === GlobeOrMap._featureHighlightName ) { return; } diff --git a/lib/Models/SearchProviders/AustralianGazetteerSearchProvider.ts b/lib/Models/SearchProviders/AustralianGazetteerSearchProvider.ts index 2072841b206..ededdb55867 100644 --- a/lib/Models/SearchProviders/AustralianGazetteerSearchProvider.ts +++ b/lib/Models/SearchProviders/AustralianGazetteerSearchProvider.ts @@ -160,7 +160,7 @@ const searchResultScoreFunction = function ( feature = feature.Gazetteer_of_Australia; // Taken from original GazetteerSearchProviderViewModel in v7 - var featureTypes = [ + const featureTypes = [ "CONT", "STAT", "URBN", diff --git a/lib/Models/SearchProviders/BingMapsSearchProvider.ts b/lib/Models/SearchProviders/BingMapsSearchProvider.ts index b9ebb6b0ab7..a634e935a47 100644 --- a/lib/Models/SearchProviders/BingMapsSearchProvider.ts +++ b/lib/Models/SearchProviders/BingMapsSearchProvider.ts @@ -34,7 +34,7 @@ export default class BingMapsSearchProvider extends LocationSearchProviderMixin( makeObservable(this); runInAction(() => { - if (!!this.terria.configParameters.bingMapsKey) { + if (this.terria.configParameters.bingMapsKey) { this.setTrait( CommonStrata.defaults, "key", diff --git a/lib/Models/SearchProviders/CesiumIonSearchProvider.ts b/lib/Models/SearchProviders/CesiumIonSearchProvider.ts index b1e39b33605..65b18687fea 100644 --- a/lib/Models/SearchProviders/CesiumIonSearchProvider.ts +++ b/lib/Models/SearchProviders/CesiumIonSearchProvider.ts @@ -40,7 +40,7 @@ export default class CesiumIonSearchProvider extends LocationSearchProviderMixin makeObservable(this); runInAction(() => { - if (!!this.terria.configParameters.cesiumIonAccessToken) { + if (this.terria.configParameters.cesiumIonAccessToken) { this.setTrait( CommonStrata.defaults, "key", diff --git a/lib/Models/Terria.ts b/lib/Models/Terria.ts index 24773609c63..f67b40a4c5f 100644 --- a/lib/Models/Terria.ts +++ b/lib/Models/Terria.ts @@ -846,7 +846,7 @@ export default class Terria { type: Class, id: string ): T | undefined { - let model = this.getModelById(type, id); + const model = this.getModelById(type, id); if (model) { return model; } else { @@ -1225,6 +1225,16 @@ export default class Terria { const hash = uri.fragment(); const hashProperties = queryToObject(hash); + function checkSegments(urlSegments: string[], customRoute: string) { + // Accept /${customRoute}/:some-id/ or /${customRoute}/:some-id + return ( + ((urlSegments.length === 3 && urlSegments[2] === "") || + urlSegments.length === 2) && + urlSegments[0] === customRoute && + urlSegments[1].length > 0 + ); + } + try { await interpretHash( this, @@ -1241,15 +1251,6 @@ export default class Terria { // /catalog/ and /story/ routes if (newUrl.startsWith(this.appBaseHref)) { - function checkSegments(urlSegments: string[], customRoute: string) { - // Accept /${customRoute}/:some-id/ or /${customRoute}/:some-id - return ( - ((urlSegments.length === 3 && urlSegments[2] === "") || - urlSegments.length === 2) && - urlSegments[0] === customRoute && - urlSegments[1].length > 0 - ); - } const pageUrl = new URL(newUrl); // Find relative path from baseURI to documentURI excluding query and hash // then split into url segments @@ -1300,7 +1301,7 @@ export default class Terria { @action updateParameters(parameters: ConfigParameters | JsonObject): void { Object.entries(parameters).forEach(([key, value]) => { - if (this.configParameters.hasOwnProperty(key)) { + if (Object.hasOwnProperty.call(this.configParameters, key)) { (this.configParameters as any)[key] = value; } }); @@ -1823,7 +1824,7 @@ export default class Terria { const newItems: BaseModel[] = []; // Maintain the model order in the workbench. - while (true) { + for (;;) { const model = newItemsRaw.shift(); if (model) { await this.pushAndLoadMapItems(model, newItems, errors); @@ -2008,7 +2009,7 @@ export default class Terria { @action async loadPickedFeatures(pickedFeatures: JsonObject): Promise { let vectorFeatures: TerriaFeature[] = []; - let featureIndex: Record = {}; + const featureIndex: Record = {}; if (Array.isArray(pickedFeatures.entities)) { // Build index of terria features by a hash of their properties. @@ -2109,7 +2110,7 @@ export default class Terria { // SecurityError can arise if 3rd party cookies are blocked in Chrome and we're served in an iFrame return null; } - var v = window.localStorage.getItem(this.appName + "." + key); + const v = window.localStorage.getItem(this.appName + "." + key); if (v === "true") { return true; } else if (v === "false") { diff --git a/lib/Models/TimelineStack.ts b/lib/Models/TimelineStack.ts index 8c8ac14897e..03b9f39742c 100644 --- a/lib/Models/TimelineStack.ts +++ b/lib/Models/TimelineStack.ts @@ -142,7 +142,7 @@ export default class TimelineStack { */ @action addToTop(item: TimeVarying) { - var currentIndex = this.items.indexOf(item); + const currentIndex = this.items.indexOf(item); this.items.unshift(item); if (currentIndex > -1) { this.items.splice(currentIndex, 1); @@ -157,7 +157,7 @@ export default class TimelineStack { */ @action remove(item: TimeVarying) { - var index = this.items.indexOf(item); + const index = this.items.indexOf(item); this.items.splice(index, 1); } @@ -177,7 +177,7 @@ export default class TimelineStack { */ @action promoteToTop(item: TimeVarying) { - var currentIndex = this.items.indexOf(item); + const currentIndex = this.items.indexOf(item); if (currentIndex > -1) { this.addToTop(item); } diff --git a/lib/Models/UserDrawing.ts b/lib/Models/UserDrawing.ts index a4b59302941..12b992f2205 100644 --- a/lib/Models/UserDrawing.ts +++ b/lib/Models/UserDrawing.ts @@ -170,13 +170,13 @@ export default class UserDrawing extends MappableMixin( * SVG element for point drawn when user clicks. * http://stackoverflow.com/questions/24869733/how-to-draw-custom-dynamic-billboards-in-cesium-js */ - var svgDataDeclare = "data:image/svg+xml,"; - var svgPrefix = + const svgDataDeclare = "data:image/svg+xml,"; + const svgPrefix = ''; - var svgCircle = + const svgCircle = ' '; - var svgSuffix = ""; - var svgString = svgPrefix + svgCircle + svgSuffix; + const svgSuffix = ""; + const svgString = svgPrefix + svgCircle + svgSuffix; // create the cesium entity return svgDataDeclare + svgString; @@ -324,7 +324,7 @@ export default class UserDrawing extends MappableMixin( * Add new point to list of pointEntities */ private addPointToPointEntities(name: string, position: Cartesian3) { - var pointEntity = new Entity({ + const pointEntity = new Entity({ name: name, position: new ConstantPositionProperty(position), billboard: { @@ -562,7 +562,7 @@ export default class UserDrawing extends MappableMixin( ? this.messageHeader() : this.messageHeader) + "
"; - let innerMessage = isDefined(this.onMakeDialogMessage) + const innerMessage = isDefined(this.onMakeDialogMessage) ? this.onMakeDialogMessage() : ""; @@ -602,7 +602,7 @@ export default class UserDrawing extends MappableMixin( getPointsForShape() { if (isDefined(this.pointEntities.entities)) { const pos = []; - for (var i = 0; i < this.pointEntities.entities.values.length; i++) { + for (let i = 0; i < this.pointEntities.entities.values.length; i++) { const obj = this.pointEntities.entities.values[i]; if (isDefined(obj.position)) { const position = obj.position.getValue( diff --git a/lib/Models/Workflows/TableStylingWorkflow.ts b/lib/Models/Workflows/TableStylingWorkflow.ts index 68e627c28b5..c39f32b8f3d 100644 --- a/lib/Models/Workflows/TableStylingWorkflow.ts +++ b/lib/Models/Workflows/TableStylingWorkflow.ts @@ -242,30 +242,28 @@ export default class TableStylingWorkflow } } } else if (colorMap instanceof DiscreteColorMap) { - { - if ( - this.tableStyle.colorTraits.binColors && - this.tableStyle.colorTraits.binColors.length > 0 - ) { - this.colorSchemeType = "custom-discrete"; - } else if (SEQUENTIAL_SCALES.includes(colorPaletteWithDefault)) { - this.colorSchemeType = "sequential-discrete"; - if (!colorPalette) { - this.getTableStyleTraits(CommonStrata.user)?.color.setTrait( - CommonStrata.user, - "colorPalette", - DEFAULT_SEQUENTIAL - ); - } - } else if (DIVERGING_SCALES.includes(colorPaletteWithDefault)) { - this.colorSchemeType = "diverging-discrete"; - if (!colorPalette) { - this.getTableStyleTraits(CommonStrata.user)?.color.setTrait( - CommonStrata.user, - "colorPalette", - DEFAULT_DIVERGING - ); - } + if ( + this.tableStyle.colorTraits.binColors && + this.tableStyle.colorTraits.binColors.length > 0 + ) { + this.colorSchemeType = "custom-discrete"; + } else if (SEQUENTIAL_SCALES.includes(colorPaletteWithDefault)) { + this.colorSchemeType = "sequential-discrete"; + if (!colorPalette) { + this.getTableStyleTraits(CommonStrata.user)?.color.setTrait( + CommonStrata.user, + "colorPalette", + DEFAULT_SEQUENTIAL + ); + } + } else if (DIVERGING_SCALES.includes(colorPaletteWithDefault)) { + this.colorSchemeType = "diverging-discrete"; + if (!colorPalette) { + this.getTableStyleTraits(CommonStrata.user)?.color.setTrait( + CommonStrata.user, + "colorPalette", + DEFAULT_DIVERGING + ); } } } else if ( diff --git a/lib/ReactViews/.eslintrc b/lib/ReactViews/.eslintrc deleted file mode 100644 index ff88a651c6c..00000000000 --- a/lib/ReactViews/.eslintrc +++ /dev/null @@ -1,40 +0,0 @@ -{ - "parser": "@babel/eslint-parser", - "parserOptions": { - "requireConfigFile": false, - "ecmaVersion": 2018, - "ecmaFeatures": { - "jsx": true, - "modules": true, - "legacyDecorators": true - } - }, - "env": { - "browser": true, - "commonjs": true - }, - "rules": { - "react/no-danger": 0, - "no-return-assign": 0, - "valid-jsdoc": 0, - "require-jsdoc": 0, - "consistent-return": 0, - "no-else-return": 0, - "no-multi-spaces": 0, - "no-multi-str": 1, - "vars-on-top": 1, - "handle-callback-err": 1, - "brace-style": [1, "1tbs", { "allowSingleLine": true }], - "camelcase": [1, { "properties": "always" }], - "indent": [0, 4, { "SwitchCase": 1 }], - "key-spacing": [1, { "beforeColon": false, "afterColon": true }], - "no-mixed-spaces-and-tabs": 1, - "no-multiple-empty-lines": [1, { "max": 1 }], - "one-var": [1, "never"], - "space-before-blocks": [1, "always"], - "space-in-parens": [1, "never"], - "spaced-comment": [1, "always"], - "no-var": 1, - "react/no-string-refs": 0 - } -} diff --git a/lib/ReactViews/ActionBar/ActionBar.tsx b/lib/ReactViews/ActionBar/ActionBar.tsx index 5ddefabe205..c03cd6ec51a 100644 --- a/lib/ReactViews/ActionBar/ActionBar.tsx +++ b/lib/ReactViews/ActionBar/ActionBar.tsx @@ -11,7 +11,7 @@ import { ActionBarPortalId } from "./ActionBarPortal"; * {@link ActionButton} can be used as a themed button for the action bar * {@link ActionButtonGroup} can be used for grouping elements inside an action bar */ -export const ActionBar: React.FC<{}> = (props) => { +export const ActionBar: React.FC = (props) => { const viewState = useViewState(); useEffect(function setVisibility() { diff --git a/lib/ReactViews/Analytics/PointParameterEditor.jsx b/lib/ReactViews/Analytics/PointParameterEditor.jsx index 2fcec4baf8e..1e1737e10f3 100644 --- a/lib/ReactViews/Analytics/PointParameterEditor.jsx +++ b/lib/ReactViews/Analytics/PointParameterEditor.jsx @@ -119,7 +119,7 @@ PointParameterEditor.setValueFromText = function (e, parameter) { // common errors like trying to specify degrees/minutes/seconds or // specifying W or E rather than using positive or negative numbers // for longitude. - if (/[^\d\s\.,+-]/.test(text)) { + if (/[^\d\s.,+-]/.test(text)) { return false; } diff --git a/lib/ReactViews/BottomDock/Timeline/DateTimePicker.tsx b/lib/ReactViews/BottomDock/Timeline/DateTimePicker.tsx index c5a05011274..870151b3984 100644 --- a/lib/ReactViews/BottomDock/Timeline/DateTimePicker.tsx +++ b/lib/ReactViews/BottomDock/Timeline/DateTimePicker.tsx @@ -178,7 +178,7 @@ class DateTimePicker extends React.Component { makeObservable(this); } - componentWillMount() { + UNSAFE_componentWillMount() { const datesObject = this.props.dates; let defaultCentury: number | undefined; let defaultYear: number | undefined; diff --git a/lib/ReactViews/Context/ViewStateContext.tsx b/lib/ReactViews/Context/ViewStateContext.tsx index b3bbad594a9..951d9fd05cb 100644 --- a/lib/ReactViews/Context/ViewStateContext.tsx +++ b/lib/ReactViews/Context/ViewStateContext.tsx @@ -20,12 +20,11 @@ export const useViewState = () => { return viewState; }; -export const withViewState = -

( - Component: React.ComponentType

- ): React.FC> => - (props) => - ( +export const withViewState =

( + Component: React.ComponentType

+): React.FC> => + function withViewState(props) { + return ( {(viewState) => { if (!viewState) @@ -34,6 +33,7 @@ export const withViewState = }} ); + }; export interface WithViewState { viewState: ViewState; diff --git a/lib/ReactViews/Custom/Chart/ChartExpandAndDownloadButtons.tsx b/lib/ReactViews/Custom/Chart/ChartExpandAndDownloadButtons.tsx index fb25511c762..89e231d985a 100644 --- a/lib/ReactViews/Custom/Chart/ChartExpandAndDownloadButtons.tsx +++ b/lib/ReactViews/Custom/Chart/ChartExpandAndDownloadButtons.tsx @@ -73,7 +73,9 @@ class ChartExpandAndDownloadButtons extends React.Component { try { terria.addModel(itemToExpand); - } catch {} + } catch { + /* eslint-disable-line no-empty */ + } (await workbench.add(itemToExpand)).raiseError(terria, undefined, true); }); } @@ -104,7 +106,7 @@ class ChartExpandAndDownloadButtons extends React.Component { } // The downloads and download names default to the sources and source names if not defined. - let downloads: string[] = filterOutUndefined( + const downloads: string[] = filterOutUndefined( this.props.downloads || this.sourceItems.map((item) => hasTraits(item, UrlTraits, "url") ? item.url : undefined diff --git a/lib/ReactViews/Custom/Chart/ChartPanelDownloadButton.tsx b/lib/ReactViews/Custom/Chart/ChartPanelDownloadButton.tsx index 5791035507f..20bb45d247c 100644 --- a/lib/ReactViews/Custom/Chart/ChartPanelDownloadButton.tsx +++ b/lib/ReactViews/Custom/Chart/ChartPanelDownloadButton.tsx @@ -87,34 +87,32 @@ async function download(items: TableMixin.Instance[]) { export const ChartPanelDownloadButton = observer( (props: { chartableItems: ChartableMixin.Instance[] }) => { - { - // For the moment we only support TableMixin items - const tableItems = props.chartableItems.filter(TableMixin.isMixedInto); + // For the moment we only support TableMixin items + const tableItems = props.chartableItems.filter(TableMixin.isMixedInto); - const isDownloadSupported = - FeatureDetection.supportsTypedArrays() && - FeatureDetection.supportsWebWorkers(); + const isDownloadSupported = + FeatureDetection.supportsTypedArrays() && + FeatureDetection.supportsWebWorkers(); - const isExportDisabled = props.chartableItems.some( - (item) => - hasTraits(item, ExportableTraits, "disableExport") && - item.disableExport === true - ); + const isExportDisabled = props.chartableItems.some( + (item) => + hasTraits(item, ExportableTraits, "disableExport") && + item.disableExport === true + ); - if (!isDownloadSupported || isExportDisabled || tableItems.length === 0) - return null; + if (!isDownloadSupported || isExportDisabled || tableItems.length === 0) + return null; - return ( - - ); - } + return ( + + ); } ); diff --git a/lib/ReactViews/Custom/ChartCustomComponent.ts b/lib/ReactViews/Custom/ChartCustomComponent.ts index 50ea2a7f767..87701ac020a 100644 --- a/lib/ReactViews/Custom/ChartCustomComponent.ts +++ b/lib/ReactViews/Custom/ChartCustomComponent.ts @@ -549,7 +549,7 @@ export default abstract class ChartCustomComponent< function checkAllPropertyKeys(object: any, allowedKeys: string[]) { for (const key in object) { - if (object.hasOwnProperty(key)) { + if (Object.hasOwnProperty.call(object, key)) { if (allowedKeys.indexOf(key) === -1) { console.log("Unknown attribute " + key); } diff --git a/lib/ReactViews/Custom/Collapsible/Collapsible.tsx b/lib/ReactViews/Custom/Collapsible/Collapsible.tsx index a17541724de..62a566d19ac 100644 --- a/lib/ReactViews/Custom/Collapsible/Collapsible.tsx +++ b/lib/ReactViews/Custom/Collapsible/Collapsible.tsx @@ -76,7 +76,7 @@ const Collapsible: React.FC = observer((props) => { }; return ( - + <> = observer((props) => { ) : null} - + ); }); diff --git a/lib/ReactViews/Custom/CsvChartCustomComponent.ts b/lib/ReactViews/Custom/CsvChartCustomComponent.ts index 79faefcc6ef..9f62cfb7e92 100644 --- a/lib/ReactViews/Custom/CsvChartCustomComponent.ts +++ b/lib/ReactViews/Custom/CsvChartCustomComponent.ts @@ -92,7 +92,7 @@ export default class CsvChartCustomComponent extends ChartCustomComponent; + ) { + if (!context.viewState) return undefined; return ( + /> ); } } diff --git a/lib/ReactViews/Custom/SOSChartCustomComponent.ts b/lib/ReactViews/Custom/SOSChartCustomComponent.ts index a488419e3ea..22d5de61051 100644 --- a/lib/ReactViews/Custom/SOSChartCustomComponent.ts +++ b/lib/ReactViews/Custom/SOSChartCustomComponent.ts @@ -16,7 +16,7 @@ export default class SOSChartCustomComponent extends ChartCustomComponent node.attribs?.title, diff --git a/lib/ReactViews/Custom/parseCustomHtmlToReact.ts b/lib/ReactViews/Custom/parseCustomHtmlToReact.ts index 1c38f5ca116..3d89d755817 100644 --- a/lib/ReactViews/Custom/parseCustomHtmlToReact.ts +++ b/lib/ReactViews/Custom/parseCustomHtmlToReact.ts @@ -113,6 +113,8 @@ function getProcessingInstructions(context: ParseCustomHtmlToReactContext) { // If external link and showExternalLinkWarning is true - replace with ExternalLinkWithWarning if (appendExternalLink && context.showExternalLinkWarning) { + /* TODO: Fix types */ + /* eslint-disable-next-line react/no-children-prop */ return createElement(ExternalLinkWithWarning, { attributes: aElement.props, children: aElement.props.children @@ -147,7 +149,7 @@ function parseCustomHtmlToReact( html: string, context?: ParseCustomHtmlToReactContext, allowUnsafeHtml: boolean = false, - domPurifyOptions: Object = {} + domPurifyOptions: object = {} ) { if (!defined(html) || html.length === 0) { return html; diff --git a/lib/ReactViews/DataCatalog/DataCatalog.jsx b/lib/ReactViews/DataCatalog/DataCatalog.jsx index 75ae5184a38..c30eca6510a 100644 --- a/lib/ReactViews/DataCatalog/DataCatalog.jsx +++ b/lib/ReactViews/DataCatalog/DataCatalog.jsx @@ -61,7 +61,7 @@ class DataCatalog extends React.Component { onActionButtonClicked={this.props.onActionButtonClicked} removable={this.props.removable} terria={this.props.terria} - isTopLevel={true} + isTopLevel /> ) )} diff --git a/lib/ReactViews/DataCatalog/DataCatalogReference.tsx b/lib/ReactViews/DataCatalog/DataCatalogReference.tsx index 6e16f4ec990..70b9060c6ce 100644 --- a/lib/ReactViews/DataCatalog/DataCatalogReference.tsx +++ b/lib/ReactViews/DataCatalog/DataCatalogReference.tsx @@ -79,29 +79,25 @@ export default observer(function DataCatalogReference({ btnState = ButtonState.Add; } - return ( - <> - {reference.isGroup ? ( - - ) : ( - - )} - + return reference.isGroup ? ( + + ) : ( + ); }); diff --git a/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/AddData.jsx b/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/AddData.jsx index 10d48f53479..ff1a7d59d88 100644 --- a/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/AddData.jsx +++ b/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/AddData.jsx @@ -229,7 +229,7 @@ const AddData = createReactClass({ options={this.state.localDataTypes} selected={this.state.localDataType} selectOption={this.selectLocalOption} - matchWidth={true} + matchWidth theme={dropdownTheme} /> {this.state.localDataType?.description @@ -263,7 +263,7 @@ const AddData = createReactClass({ options={this.state.remoteDataTypes} selected={this.state.remoteDataType} selectOption={this.selectRemoteOption} - matchWidth={true} + matchWidth theme={dropdownTheme} /> {this.state.remoteDataType?.description diff --git a/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/MyDataTab.jsx b/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/MyDataTab.jsx index cec82e8d5b6..98a5fdfcb18 100644 --- a/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/MyDataTab.jsx +++ b/lib/ReactViews/ExplorerWindow/Tabs/MyDataTab/MyDataTab.jsx @@ -184,7 +184,7 @@ class MyDataTab extends React.Component { items={ this.props.terria.catalog.userAddedDataGroup.memberModels } - removable={true} + removable viewState={this.props.viewState} terria={this.props.terria} /> diff --git a/lib/ReactViews/FeatureInfo/FeatureInfoPanel.tsx b/lib/ReactViews/FeatureInfo/FeatureInfoPanel.tsx index 5d45367fb28..c2bc418f3fb 100644 --- a/lib/ReactViews/FeatureInfo/FeatureInfoPanel.tsx +++ b/lib/ReactViews/FeatureInfo/FeatureInfoPanel.tsx @@ -229,7 +229,7 @@ class FeatureInfoPanel extends React.Component { const cartographic = Ellipsoid.WGS84.cartesianToCartographic(cartesianPosition); if (cartographic === undefined) { - return <>; + return null; } const latitude = CesiumMath.toDegrees(cartographic.latitude); const longitude = CesiumMath.toDegrees(cartographic.longitude); diff --git a/lib/ReactViews/FeatureInfo/FeatureInfoSection.tsx b/lib/ReactViews/FeatureInfo/FeatureInfoSection.tsx index 29f4b8847e9..8275e8fec9c 100644 --- a/lib/ReactViews/FeatureInfo/FeatureInfoSection.tsx +++ b/lib/ReactViews/FeatureInfo/FeatureInfoSection.tsx @@ -12,7 +12,7 @@ import { import { observer } from "mobx-react"; import { IDisposer } from "mobx-utils"; import Mustache from "mustache"; -import React from "react"; +import React, { Ref } from "react"; import { withTranslation } from "react-i18next"; import styled from "styled-components"; import Cartesian3 from "terriajs-cesium/Source/Core/Cartesian3"; @@ -77,6 +77,8 @@ export class FeatureInfoSection extends React.Component { | React.ReactNode | undefined = undefined; + noInfoRef: HTMLDivElement | null = null; + @observable private showRawData: boolean = false; @@ -293,7 +295,7 @@ export class FeatureInfoSection extends React.Component { const feature = this.props.feature; const currentTime = this.currentTimeIfAvailable ?? JulianDate.now(); - let description: string | undefined = + const description: string | undefined = feature.description?.getValue(currentTime); if (isDefined(description)) return description; @@ -453,7 +455,12 @@ export class FeatureInfoSection extends React.Component { {titleElement} {this.props.isOpen ? (

-
+
{ + this.noInfoRef = r; + }} + key="no-info" + > {t("featureInfo.noInfoAvailable")}
@@ -472,15 +479,18 @@ export class FeatureInfoSection extends React.Component { {this.props.feature.loadingFeatureInfoUrl ? ( "Loading" ) : this.showRawData || !this.templatedFeatureInfoReactNode ? ( - <> - {this.rawFeatureInfoReactNode ? ( - this.rawFeatureInfoReactNode - ) : ( -
- {t("featureInfo.noInfoAvailable")} -
- )} - + this.rawFeatureInfoReactNode ? ( + this.rawFeatureInfoReactNode + ) : ( +
{ + this.noInfoRef = r; + }} + key="no-info" + > + {t("featureInfo.noInfoAvailable")} +
+ ) ) : ( // Show templated feature info this.templatedFeatureInfoReactNode diff --git a/lib/ReactViews/FeatureInfo/getFeatureProperties.ts b/lib/ReactViews/FeatureInfo/getFeatureProperties.ts index b693d17ba28..7a2e6b7a318 100644 --- a/lib/ReactViews/FeatureInfo/getFeatureProperties.ts +++ b/lib/ReactViews/FeatureInfo/getFeatureProperties.ts @@ -29,6 +29,9 @@ export default function getFeatureProperties( // Try JSON.parse on values that look like JSON arrays or objects let result = parseValues(properties); + if (result === undefined) { + return undefined; + } result = replaceBadKeyCharacters(result); if (formats) { @@ -80,7 +83,9 @@ function parseValues(properties: JsonObject) { ) { try { val = JSON.parse(val as string); - } catch (e) {} + } catch (e) { + return; + } } result[key] = val; } diff --git a/lib/ReactViews/FeatureInfo/mustacheExpressions.ts b/lib/ReactViews/FeatureInfo/mustacheExpressions.ts index 028776255ed..cd48fb66418 100644 --- a/lib/ReactViews/FeatureInfo/mustacheExpressions.ts +++ b/lib/ReactViews/FeatureInfo/mustacheExpressions.ts @@ -31,7 +31,7 @@ function mustacheJsonSubOptions( return customProcessing(render(text)); } // Allow {foo: 1} by converting it to {"foo": 1} for JSON.parse. - const quoteReg = /([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/g; + const quoteReg = /([{,])(\s*)([A-Za-z0-9_-]+?)\s*:/g; const jsonOptions = components[1].replace(quoteReg, '$1"$3":'); const options = JSON.parse(jsonOptions); return customProcessing(render(components[2]), options); @@ -84,7 +84,7 @@ export function mustacheFormatNumberFunction(): ( */ export function mustacheRenderPartialByName( partials: Record, - templateData: Object + templateData: object ): MustacheFunction { return () => { return mustacheJsonSubOptions((value, options) => { diff --git a/lib/ReactViews/Feedback/FeedbackForm.tsx b/lib/ReactViews/Feedback/FeedbackForm.tsx index 675f47de837..92df385d21f 100644 --- a/lib/ReactViews/Feedback/FeedbackForm.tsx +++ b/lib/ReactViews/Feedback/FeedbackForm.tsx @@ -137,7 +137,9 @@ class FeedbackForm extends React.Component { this.state.comment.length >= this.props.viewState.terria.configParameters.feedbackMinLength! ) { - this.state.isSending = true; + this.setState({ + isSending: true + }); sendFeedback({ terria: this.props.viewState.terria, name: this.state.name, @@ -219,7 +221,7 @@ class FeedbackForm extends React.Component { value={this.state.name} onChange={this.updateName} autoComplete="off" - > + /> { value={this.state.email} onChange={this.updateEmail} autoComplete="off" - > + /> = (props: TextAreaProps) => { } }} invalidValue={!valueIsValid} - > + /> ); }; diff --git a/lib/ReactViews/Generic/TooltipWrapper.tsx b/lib/ReactViews/Generic/TooltipWrapper.tsx index fde7b90f406..69daa6a918e 100644 --- a/lib/ReactViews/Generic/TooltipWrapper.tsx +++ b/lib/ReactViews/Generic/TooltipWrapper.tsx @@ -32,7 +32,7 @@ type Props = { forceSetState: (bool?: boolean) => void; }) => React.ReactNode; /** Styles to apply to the actual tooltip */ - innerElementStyles?: Object; + innerElementStyles?: object; /** The tooltip content itself, as higher-order function that provides a function to dismiss the tooltip */ children: (applyAriaId: boolean, dismiss: () => void) => React.ReactNode; }; @@ -86,7 +86,7 @@ class TooltipWrapperRaw extends React.Component { const rootElement = this.rootRef.current; // Why .firstChild? Because we can't attach a ref to a render prop unless whatever's passed in passes the ref through to its first dom element - const launcherElement = rootElement!?.firstChild!; + const launcherElement = rootElement?.firstChild; if (!launcherElement || !tooltipTextElement) { return; } diff --git a/lib/ReactViews/Map/BottomBar/Credits/DataAttribution/DataAttributionModal.tsx b/lib/ReactViews/Map/BottomBar/Credits/DataAttribution/DataAttributionModal.tsx index b5b1856e5ca..d7b597dc0c7 100644 --- a/lib/ReactViews/Map/BottomBar/Credits/DataAttribution/DataAttributionModal.tsx +++ b/lib/ReactViews/Map/BottomBar/Credits/DataAttribution/DataAttributionModal.tsx @@ -71,7 +71,7 @@ export const DataAttributionModal: FC = observer( aria-hidden="true" pseudoBg css={{ top: 0, left: 0, zIndex: 99989 }} - > + /> diff --git a/lib/ReactViews/Map/BottomBar/Credits/MapCredits.tsx b/lib/ReactViews/Map/BottomBar/Credits/MapCredits.tsx index 05a8a30a118..5800d416b4b 100644 --- a/lib/ReactViews/Map/BottomBar/Credits/MapCredits.tsx +++ b/lib/ReactViews/Map/BottomBar/Credits/MapCredits.tsx @@ -52,7 +52,7 @@ export const MapCredits: FC = observer( {!hideTerriaLogo ? : null} - + {currentViewer.attributions && currentViewer.attributions.length > 0 ? ( diff --git a/lib/ReactViews/Map/BottomLeftBar/BottomLeftBar.tsx b/lib/ReactViews/Map/BottomLeftBar/BottomLeftBar.tsx index 2fbc49aacdf..ce939e8a7c6 100644 --- a/lib/ReactViews/Map/BottomLeftBar/BottomLeftBar.tsx +++ b/lib/ReactViews/Map/BottomLeftBar/BottomLeftBar.tsx @@ -73,7 +73,7 @@ const BottomLeftBar: FC = observer(() => { } onClick={() => viewState.runStories()} primary={!isNotificationActive} @@ -89,7 +89,7 @@ const BottomLeftBar: FC = observer(() => { height="18px" style={{ paddingLeft: "8px" }} src="build/TerriaJS/images/google_on_non_white_hdpi.png" - > + /> )} {/* On screen data attributions. At the moment, this supports only Cesium viewer. Needed for Google Photorealistic 3D Tiles diff --git a/lib/ReactViews/Map/MapNavigation/CollapsedNavigation.tsx b/lib/ReactViews/Map/MapNavigation/CollapsedNavigation.tsx index 57b1ef8c648..81fb527bf89 100644 --- a/lib/ReactViews/Map/MapNavigation/CollapsedNavigation.tsx +++ b/lib/ReactViews/Map/MapNavigation/CollapsedNavigation.tsx @@ -85,7 +85,7 @@ const CollapsedNavigationPanel: React.FC = observer( const viewState = useViewState(); const theme = useTheme(); const { t, i18n } = useTranslation(); - let items = props.items; + const items = props.items; return ( { role="presentation" aria-hidden="true" pseudoBg - > - + /> + ); }); diff --git a/lib/ReactViews/Map/MapNavigation/Items/Compass/GyroscopeGuidance.jsx b/lib/ReactViews/Map/MapNavigation/Items/Compass/GyroscopeGuidance.jsx index b1ff9cf0ff5..ecc8a55b637 100644 --- a/lib/ReactViews/Map/MapNavigation/Items/Compass/GyroscopeGuidance.jsx +++ b/lib/ReactViews/Map/MapNavigation/Items/Compass/GyroscopeGuidance.jsx @@ -134,72 +134,70 @@ export function GyroscopeGuidance(props) { const controlsMapIcon = useRef(); const { t } = useTranslation(); return ( - <> +
+ } + onClick={() => setControlPanelOpen(!controlPanelOpen)} + inverted + css={` + svg { + margin: 0px; + width: 25px; + height: 25px; + } + `} + />
e.preventDefault()} css={` position: relative; `} > - } - onClick={() => setControlPanelOpen(!controlPanelOpen)} - inverted - css={` - svg { - margin: 0px; - width: 25px; - height: 25px; + p.theme.textBlack}; } `} - /> -
e.preventDefault()} - css={` - position: relative; - `} + refForCaret={controlsMapIcon} + isOpen={controlPanelOpen} + onOpenChanged={() => controlPanelOpen} + // onDismissed={() => setControlPanelOpen(false)} + btnTitle={t("compass.guidanceBtnTitle")} + btnText={t("compass.guidanceBtnText")} + viewState={props.viewState} + smallScreen={props.viewState.useSmallScreenInterface} > - p.theme.textBlack}; - } - `} - refForCaret={controlsMapIcon} - isOpen={controlPanelOpen} - onOpenChanged={() => controlPanelOpen} - // onDismissed={() => setControlPanelOpen(false)} - btnTitle={t("compass.guidanceBtnTitle")} - btnText={t("compass.guidanceBtnText")} - viewState={props.viewState} - smallScreen={props.viewState.useSmallScreenInterface} - > - { - setControlPanelOpen(false); - props.onClose(); - props.viewState.terria.setLocalProperty( - COMPASS_LOCAL_PROPERTY_KEY, - true - ); - }} - /> - -
+ { + setControlPanelOpen(false); + props.onClose(); + props.viewState.terria.setLocalProperty( + COMPASS_LOCAL_PROPERTY_KEY, + true + ); + }} + /> +
- +
); } diff --git a/lib/ReactViews/Map/MapNavigation/MapNavigation.tsx b/lib/ReactViews/Map/MapNavigation/MapNavigation.tsx index 5f6ef8cf951..23131e3b538 100644 --- a/lib/ReactViews/Map/MapNavigation/MapNavigation.tsx +++ b/lib/ReactViews/Map/MapNavigation/MapNavigation.tsx @@ -167,15 +167,15 @@ class MapNavigationBase extends React.Component { if (this.computeSizes.length !== this.model.visibleItems.length) { this.computeSizes(); } - let itemsToShow = this.model.visibleItems.filter((item) => + const itemsToShow = this.model.visibleItems.filter((item) => filterViewerAndScreenSize(item, this.viewState) ); // items we have to show in the navigation bar - let pinnedItems = this.model.pinnedItems.filter((item) => + const pinnedItems = this.model.pinnedItems.filter((item) => filterViewerAndScreenSize(item, this.viewState) ); // items that are possible to be collapsed - let possibleToCollapse = itemsToShow + const possibleToCollapse = itemsToShow .filter( (item) => !pinnedItems.some((pinnedItem) => pinnedItem.id === item.id) ) diff --git a/lib/ReactViews/Map/MenuBar/StoryButton/StoryButton.tsx b/lib/ReactViews/Map/MenuBar/StoryButton/StoryButton.tsx index afc1afb5972..f2906d7135c 100644 --- a/lib/ReactViews/Map/MenuBar/StoryButton/StoryButton.tsx +++ b/lib/ReactViews/Map/MenuBar/StoryButton/StoryButton.tsx @@ -59,7 +59,7 @@ const promptHtml = (hasStories: boolean) => (
); -export default (props: Props) => { +const StoryButton = (props: Props) => { const storyButtonRef: Ref = useRefForTerria( STORY_BUTTON_NAME, props.viewState @@ -110,3 +110,4 @@ export default (props: Props) => { ); }; +export default StoryButton; diff --git a/lib/ReactViews/Map/Panels/LangPanel/LangPanel.tsx b/lib/ReactViews/Map/Panels/LangPanel/LangPanel.tsx index 2ad49bc15b8..5b69f3a15bf 100644 --- a/lib/ReactViews/Map/Panels/LangPanel/LangPanel.tsx +++ b/lib/ReactViews/Map/Panels/LangPanel/LangPanel.tsx @@ -15,7 +15,7 @@ type Props = { smallScreen: boolean; }; -export default (props: Props) => { +const LangPanel = (props: Props) => { const { t, i18n } = useTranslation(); if (!props.terria.configParameters.languageConfiguration?.languages) { @@ -61,3 +61,4 @@ export default (props: Props) => { ); }; +export default LangPanel; diff --git a/lib/ReactViews/Map/Panels/SharePanel/Print/PrintDatasets.tsx b/lib/ReactViews/Map/Panels/SharePanel/Print/PrintDatasets.tsx index 6ff0f4952c7..4121f66d51e 100644 --- a/lib/ReactViews/Map/Panels/SharePanel/Print/PrintDatasets.tsx +++ b/lib/ReactViews/Map/Panels/SharePanel/Print/PrintDatasets.tsx @@ -13,7 +13,7 @@ const PrintDatasets = (props: Props) => { {props.items.map((item, index) => (
{getName(item)} - +
))} diff --git a/lib/ReactViews/Map/Panels/SharePanel/Print/PrintView.tsx b/lib/ReactViews/Map/Panels/SharePanel/Print/PrintView.tsx index 8f283732101..03323501baf 100644 --- a/lib/ReactViews/Map/Panels/SharePanel/Print/PrintView.tsx +++ b/lib/ReactViews/Map/Panels/SharePanel/Print/PrintView.tsx @@ -186,7 +186,7 @@ const PrintView = (props: Props) => { scale={getScale( viewState.terria.currentViewer.getContainer() )} - isPrintMode={true} + isPrintMode /> ) : ( diff --git a/lib/ReactViews/Map/Panels/SharePanel/Print/PrintWorkbench.tsx b/lib/ReactViews/Map/Panels/SharePanel/Print/PrintWorkbench.tsx index dab2e9cc5c6..df693035052 100644 --- a/lib/ReactViews/Map/Panels/SharePanel/Print/PrintWorkbench.tsx +++ b/lib/ReactViews/Map/Panels/SharePanel/Print/PrintWorkbench.tsx @@ -45,7 +45,7 @@ const renderLegend = (catalogItem: BaseModel) => {
Time: {catalogItem.currentTime}
)} {CatalogMemberMixin.isMixedInto(catalogItem) && ( - + )} ); diff --git a/lib/ReactViews/Map/Panels/SharePanel/SharePanel.tsx b/lib/ReactViews/Map/Panels/SharePanel/SharePanel.tsx index 3328cf2e3a4..a70f16cf43f 100644 --- a/lib/ReactViews/Map/Panels/SharePanel/SharePanel.tsx +++ b/lib/ReactViews/Map/Panels/SharePanel/SharePanel.tsx @@ -78,7 +78,7 @@ class SharePanel extends React.Component { { = ({ shouldShortenDefault(terria) ); - const [_, update] = useState<{}>(); + const [_, update] = useState(); const shareUrlRef = useCallbackRef(null, () => update({})); const includeStoryInShareOnChange = useCallback(() => { diff --git a/lib/ReactViews/Map/Panels/SharePanel/ShareUrl/ShareUrl.tsx b/lib/ReactViews/Map/Panels/SharePanel/ShareUrl/ShareUrl.tsx index 766047564b4..3979f1cdb65 100644 --- a/lib/ReactViews/Map/Panels/SharePanel/ShareUrl/ShareUrl.tsx +++ b/lib/ReactViews/Map/Panels/SharePanel/ShareUrl/ShareUrl.tsx @@ -42,107 +42,105 @@ export interface IShareUrlRef { export const ShareUrl = forwardRef< IShareUrlRef, PropsWithChildren ->( - ( - { - terria, - viewState, - includeStories, - shouldShorten, - children, - theme, - inputTheme, - rounded, - callback - }, - forwardRef - ) => { - const { t } = useTranslation(); +>(function ShareUrl( + { + terria, + viewState, + includeStories, + shouldShorten, + children, + theme, + inputTheme, + rounded, + callback + }, + forwardRef +) { + const { t } = useTranslation(); - const [shareUrl, setShareUrl] = useState(""); - const [shorteningInProgress, setShorteningInProgress] = useState(false); - const [placeholder, setPlaceholder] = useState(); + const [shareUrl, setShareUrl] = useState(""); + const [shorteningInProgress, setShorteningInProgress] = useState(false); + const [placeholder, setPlaceholder] = useState(); - useImperativeHandle( - forwardRef, - () => ({ - url: shareUrl, - shorteningInProgress: shorteningInProgress - }), - [forwardRef, shareUrl, shorteningInProgress] - ); + useImperativeHandle( + forwardRef, + () => ({ + url: shareUrl, + shorteningInProgress: shorteningInProgress + }), + [forwardRef, shareUrl, shorteningInProgress] + ); - useEffect(() => { - if (shouldShorten) { - setPlaceholder(t("share.shortLinkShortening")); - setShorteningInProgress(true); - buildShortShareLink(terria, viewState, { + useEffect(() => { + if (shouldShorten) { + setPlaceholder(t("share.shortLinkShortening")); + setShorteningInProgress(true); + buildShortShareLink(terria, viewState, { + includeStories + }) + .then((shareUrl) => setShareUrl(shareUrl)) + .catch(() => { + setShareUrl( + buildShareLink(terria, viewState, { + includeStories + }) + ); + }) + .finally(() => setShorteningInProgress(false)); + } else { + setShareUrl( + buildShareLink(terria, viewState, { includeStories }) - .then((shareUrl) => setShareUrl(shareUrl)) - .catch(() => { - setShareUrl( - buildShareLink(terria, viewState, { - includeStories - }) - ); - }) - .finally(() => setShorteningInProgress(false)); - } else { - setShareUrl( - buildShareLink(terria, viewState, { - includeStories - }) - ); - } - }, [terria, viewState, shouldShorten, includeStories]); + ); + } + }, [terria, viewState, shouldShorten, includeStories]); - return ( - <> - - {t("clipboard.shareExplanation")} - - - e.currentTarget.select()} - css={` - ${rounded ? `border-radius: 32px 0 0 32px;` : ""} - `} - id="share-url" - /> - } - id="share-url" - rounded={rounded} - onCopy={(text) => - terria.analytics?.logEvent( - Category.share, - ShareAction.storyCopy, - text - ) - } - /> - {children} - - {})} - /> - - ); - } -); + return ( + <> + + {t("clipboard.shareExplanation")} + + + e.currentTarget.select()} + css={` + ${rounded ? `border-radius: 32px 0 0 32px;` : ""} + `} + id="share-url" + /> + } + id="share-url" + rounded={rounded} + onCopy={(text) => + terria.analytics?.logEvent( + Category.share, + ShareAction.storyCopy, + text + ) + } + /> + {children} + + {})} + /> + + ); +}); const Explanation = styled(TextSpan)` opacity: 0.8; diff --git a/lib/ReactViews/Map/Panels/ToolsPanel/CountDatasets.tsx b/lib/ReactViews/Map/Panels/ToolsPanel/CountDatasets.tsx index b446d8530d2..0bd4fccf3d8 100644 --- a/lib/ReactViews/Map/Panels/ToolsPanel/CountDatasets.tsx +++ b/lib/ReactViews/Map/Panels/ToolsPanel/CountDatasets.tsx @@ -82,7 +82,7 @@ const CountDatasets: React.FC = observer((props) => { path.push(member.name!); const loadPromise = member.loadMembers(); - let countPromise = member.isLoading + const countPromise = member.isLoading ? loadPromise .then((result) => result.throwIfError()) .then( @@ -116,7 +116,7 @@ const CountDatasets: React.FC = observer((props) => { const promise = counter(member, childStats, path).then(function () { stats.groups += childStats.groups + 1; stats.members += childStats.members; - stats.messages.push.apply(stats.messages, childStats.messages); + stats.messages.push(...childStats.messages); stats.subTotals.push(childStats); }); return promise; diff --git a/lib/ReactViews/Map/Panels/ToolsPanel/ToolsPanel.jsx b/lib/ReactViews/Map/Panels/ToolsPanel/ToolsPanel.jsx index 634f6ac8165..af3f33d340a 100644 --- a/lib/ReactViews/Map/Panels/ToolsPanel/ToolsPanel.jsx +++ b/lib/ReactViews/Map/Panels/ToolsPanel/ToolsPanel.jsx @@ -38,6 +38,7 @@ const ToolsPanel = observer(() => { )}
+ {/* eslint-disable-next-line react/no-danger */}
diff --git a/lib/ReactViews/Map/TerriaViewerWrapper/Splitter/dragHook.ts b/lib/ReactViews/Map/TerriaViewerWrapper/Splitter/dragHook.ts index 2014e467f34..06bd9530428 100644 --- a/lib/ReactViews/Map/TerriaViewerWrapper/Splitter/dragHook.ts +++ b/lib/ReactViews/Map/TerriaViewerWrapper/Splitter/dragHook.ts @@ -23,7 +23,9 @@ try { window.addEventListener("test", callback, options); window.removeEventListener("test", callback, options); -} catch (err) {} +} catch (err) { + /* eslint-disable-line no-empty */ +} const notPassive = passiveSupported ? { passive: false } : false; diff --git a/lib/ReactViews/MapIconButton/MapIconButton.tsx b/lib/ReactViews/MapIconButton/MapIconButton.tsx index a0bb2b82e8d..63da09f4a22 100644 --- a/lib/ReactViews/MapIconButton/MapIconButton.tsx +++ b/lib/ReactViews/MapIconButton/MapIconButton.tsx @@ -118,7 +118,7 @@ function MapIconButton(props: IMapIconButtonProps) { noExpand = false } = props; const expanded = !noExpand && (isExpanded || neverCollapse) && children; - const buttonRef = props.buttonRef || useRef(); + const buttonRef = useRef(); const theme = useTheme(); // const handleAway = () => setTimeout(() => setExpanded(false), 1000); @@ -131,7 +131,7 @@ function MapIconButton(props: IMapIconButtonProps) { const MapIconButtonRaw = ( )} {searchState.showMobileCatalogSearch && ( @@ -153,7 +153,7 @@ class MobileHeader extends React.Component { onDoSearch={this.searchCatalog.bind(this)} placeholder={t("search.searchCatalogue")} onClear={this.closeCatalogSearch.bind(this)} - autoFocus={true} + autoFocus /> )}
; diff --git a/lib/ReactViews/Mobile/MobileMenuItem.tsx b/lib/ReactViews/Mobile/MobileMenuItem.tsx index 3b62acaf56d..5435466c207 100644 --- a/lib/ReactViews/Mobile/MobileMenuItem.tsx +++ b/lib/ReactViews/Mobile/MobileMenuItem.tsx @@ -10,7 +10,7 @@ type Props = { icon: { id: keyof typeof GLYPHS }; }; -export default (props: Props) => ( +const MobileMenuItem = (props: Props) => (
{props.href ? ( ( )}
); +export default MobileMenuItem; diff --git a/lib/ReactViews/Notification/Notification.tsx b/lib/ReactViews/Notification/Notification.tsx index 4b7e597d1bc..5ef6b16f9eb 100644 --- a/lib/ReactViews/Notification/Notification.tsx +++ b/lib/ReactViews/Notification/Notification.tsx @@ -16,7 +16,7 @@ const Notification = observer(() => { notificationState === undefined || notification === undefined ) { - return <>; + return null; } const close = () => { diff --git a/lib/ReactViews/Notification/shareConvertNotification.tsx b/lib/ReactViews/Notification/shareConvertNotification.tsx index 84907702966..a79b8b87fbe 100644 --- a/lib/ReactViews/Notification/shareConvertNotification.tsx +++ b/lib/ReactViews/Notification/shareConvertNotification.tsx @@ -9,9 +9,10 @@ import Text, { TextSpan } from "../../Styled/Text"; import { RawButton } from "../../Styled/Button"; import Spacing from "../../Styled/Spacing"; -export const shareConvertNotification = - (messages: import("catalog-converter").ShareResult["messages"]) => - (viewState: ViewState) => { +export const shareConvertNotification = ( + messages: import("catalog-converter").ShareResult["messages"] +) => + function shareConvertNotification(viewState: ViewState) { const messagesForPath: { [path: string]: string[] } = {}; messages?.forEach((message: any) => { let pathString = message.path?.join(": "); @@ -39,7 +40,7 @@ export const shareConvertNotification = }; return ( - + <> {parseCustomMarkdownToReact( i18next.t("share.convertNotificationMessage") @@ -77,27 +78,27 @@ export const shareConvertNotification = {rootMessages && ( - + <>
    - {rootMessages.map((message) => ( -
  • {message}
  • + {rootMessages.map((message, i) => ( +
  • {message}
  • ))}
-
+ )} {Object.entries(messagesForPath).map(([path, messages]) => ( - + <>
    - {messages.map((message) => ( -
  • {message}
  • + {messages.map((message, i) => ( +
  • {message}
  • ))}
-
+ ))}
-
+ ); }; diff --git a/lib/ReactViews/Notification/terriaErrorNotification.tsx b/lib/ReactViews/Notification/terriaErrorNotification.tsx index c529ac5c7e7..58cfe94249d 100644 --- a/lib/ReactViews/Notification/terriaErrorNotification.tsx +++ b/lib/ReactViews/Notification/terriaErrorNotification.tsx @@ -28,10 +28,7 @@ const ErrorsBox = (props: { key={idx} > {error instanceof TerriaError ? ( - + ) : ( // Show error.message (as well as error.stack) if error.stack is defined
@@ -72,14 +69,14 @@ const TerriaErrorBox = (props: { + /> ) : null} ); }; -export const terriaErrorNotification = - (error: TerriaError) => (viewState: ViewState) => { +export const terriaErrorNotification = (error: TerriaError) => + function TerriaErrorNotification(viewState: ViewState) { // Get "detailed" errors - these can be expanded if the user wants to see more "detail" let detailedErrors: (Error | TerriaError)[] | undefined; @@ -122,7 +119,7 @@ export const terriaErrorNotification = <> (error.showDetails = show)); }} > - + ) : null} - {!includesFeedbackLink ? ( - - ) : null} + {!includesFeedbackLink ? : null} ); }; diff --git a/lib/ReactViews/Preview/DataPreviewUrl.jsx b/lib/ReactViews/Preview/DataPreviewUrl.jsx index 420d29b98ec..fa536f9f213 100644 --- a/lib/ReactViews/Preview/DataPreviewUrl.jsx +++ b/lib/ReactViews/Preview/DataPreviewUrl.jsx @@ -5,6 +5,8 @@ import createReactClass from "create-react-class"; import PropTypes from "prop-types"; import Styles from "./data-preview.scss"; +import { Trans } from "react-i18next"; + /** * URL section of the preview. */ diff --git a/lib/ReactViews/Preview/Description.jsx b/lib/ReactViews/Preview/Description.jsx index eea167e3511..6e39b9401b6 100644 --- a/lib/ReactViews/Preview/Description.jsx +++ b/lib/ReactViews/Preview/Description.jsx @@ -117,7 +117,7 @@ class Description extends React.Component { `} > {metadataUrl.title && ( - + )} {!metadataUrl.title ? metadataUrl.url : null} @@ -230,7 +230,7 @@ class Description extends React.Component { `} > {dataUrl.title && ( - + )} {!dataUrl.title ? dataUrl.url : null} @@ -248,7 +248,7 @@ class Description extends React.Component {
)} - {!this.props.printView ? ( - - ) : null} + {!this.props.printView ? : null}
); } diff --git a/lib/ReactViews/Preview/WarningBox.tsx b/lib/ReactViews/Preview/WarningBox.tsx index 7134a906b52..0651547e719 100644 --- a/lib/ReactViews/Preview/WarningBox.tsx +++ b/lib/ReactViews/Preview/WarningBox.tsx @@ -48,7 +48,7 @@ const WarningBox: React.FC<{ )} {props.viewState && !includesFeedbackLink ? ( - + ) : null} {/* Add "show details" button if there are nested errors */} diff --git a/lib/ReactViews/RelatedMaps/RelatedMaps.tsx b/lib/ReactViews/RelatedMaps/RelatedMaps.tsx index 2194252874a..08e1c9f2382 100644 --- a/lib/ReactViews/RelatedMaps/RelatedMaps.tsx +++ b/lib/ReactViews/RelatedMaps/RelatedMaps.tsx @@ -51,7 +51,7 @@ class RelatedMaps extends React.Component { {this.props.relatedMaps.map((map, i) => ( - + { target="_blank" style={{ color: this.props.theme.colorPrimary }} href={map.url} + rel="noreferrer" > {map.title} diff --git a/lib/ReactViews/Search/LocationSearchResults.tsx b/lib/ReactViews/Search/LocationSearchResults.tsx index 191e7db1b33..f7be2d0f3f4 100644 --- a/lib/ReactViews/Search/LocationSearchResults.tsx +++ b/lib/ReactViews/Search/LocationSearchResults.tsx @@ -213,10 +213,11 @@ const NameWithLoader: React.FC = observer( return ( - {`${applyTranslationIfExists( - props.name, - i18n - )} (${props.length || 0})`} + + {`${applyTranslationIfExists(props.name, i18n)} (${ + props.length || 0 + })`} + {!props.isOpen && (props.search.isSearching || props.isWaitingForSearchToStart) && ( diff --git a/lib/ReactViews/SelectableDimensions/Color.tsx b/lib/ReactViews/SelectableDimensions/Color.tsx index 41f4b38a834..9330d6d237b 100644 --- a/lib/ReactViews/SelectableDimensions/Color.tsx +++ b/lib/ReactViews/SelectableDimensions/Color.tsx @@ -47,7 +47,7 @@ export const SelectableDimensionColor: React.FC<{ borderRadius: "2px", background: dim.value ?? "#aaa" }} - >
+ /> ) : null} {/* Show "Add" button if value is undefined */} diff --git a/lib/ReactViews/SelectableDimensions/ColorSchemeOptionRenderer.tsx b/lib/ReactViews/SelectableDimensions/ColorSchemeOptionRenderer.tsx index 3f3a250422d..f07d1b14688 100644 --- a/lib/ReactViews/SelectableDimensions/ColorSchemeOptionRenderer.tsx +++ b/lib/ReactViews/SelectableDimensions/ColorSchemeOptionRenderer.tsx @@ -5,7 +5,7 @@ import React from "react"; import StandardCssColors from "../../Core/StandardCssColors"; import { OptionRenderer } from "../../Models/SelectableDimensions/SelectableDimensions"; -const Invalid: React.VFC<{}> = () => { +const Invalid: React.VFC = () => { const { t } = useTranslation(); return {t("selectableDimensions.invalid")}; }; diff --git a/lib/ReactViews/SelectableDimensions/MarkerOptionRenderer.tsx b/lib/ReactViews/SelectableDimensions/MarkerOptionRenderer.tsx index 2246786731b..fb6dc40ea08 100644 --- a/lib/ReactViews/SelectableDimensions/MarkerOptionRenderer.tsx +++ b/lib/ReactViews/SelectableDimensions/MarkerOptionRenderer.tsx @@ -9,7 +9,7 @@ export const MarkerOptionRenderer: OptionRenderer = (option) => ( height="20px" style={{ marginBottom: -5 }} src={getMakiIcon(option.value, "#000", 1, "#fff", 24, 24) ?? option.value} - >{" "} + />{" "} {option.value} ); diff --git a/lib/ReactViews/SelectableDimensions/Select.tsx b/lib/ReactViews/SelectableDimensions/Select.tsx index d27aabe9897..f5f4e7eb490 100644 --- a/lib/ReactViews/SelectableDimensions/Select.tsx +++ b/lib/ReactViews/SelectableDimensions/Select.tsx @@ -99,7 +99,7 @@ export const SelectableDimensionEnumMulti: React.FC<{ }> = observer(({ id, dim }) => { const theme = useTheme(); - let options = dim.options?.map((option) => ({ + const options = dim.options?.map((option) => ({ value: option.id, label: option.name ?? option.id })); @@ -137,7 +137,7 @@ export const SelectableDimensionEnumMulti: React.FC<{ primary: theme.colorPrimary } })} - isMulti={true} + isMulti /> ); }); diff --git a/lib/ReactViews/SidePanel/SidePanel.tsx b/lib/ReactViews/SidePanel/SidePanel.tsx index d020e0bdb01..d590a8b5968 100644 --- a/lib/ReactViews/SidePanel/SidePanel.tsx +++ b/lib/ReactViews/SidePanel/SidePanel.tsx @@ -103,7 +103,7 @@ type SidePanelButtonProps = { const SidePanelButton = React.forwardRef< HTMLButtonElement, SidePanelButtonProps ->((props, ref) => { +>(function SidePanelButton(props, ref) { const { btnText, ...rest } = props; return (