diff --git a/packages/base/package.json b/packages/base/package.json index 80199890..5778e32d 100644 --- a/packages/base/package.json +++ b/packages/base/package.json @@ -78,6 +78,7 @@ "@apidevtools/json-schema-ref-parser": "^9.0.9", "@types/node": "^18.15.11", "@types/three": "^0.135.0", + "@types/uuid": "^10.0.0", "rimraf": "^3.0.2", "typescript": "^5" }, diff --git a/packages/base/src/dialogs/components/color-expression/StopRow.tsx b/packages/base/src/dialogs/components/color-expression/StopRow.tsx index 04c281c6..ed47479a 100644 --- a/packages/base/src/dialogs/components/color-expression/StopRow.tsx +++ b/packages/base/src/dialogs/components/color-expression/StopRow.tsx @@ -17,32 +17,32 @@ const StopRow = ({ stopRows: IStopRow[]; setStopRows: any; }) => { - const [inputZoom, setInputZoom] = useState(10); - const [inputColor, setInputColor] = useState(''); + const [, setInputZoom] = useState(10); + const [, setInputColor] = useState(''); - const rgbaStringToHex = rgbaStr => { - // Remove the "rgba(" part and close parenthesis - const rgbaParts = rgbaStr.replace('rgba(', '').replace(')', ''); + // const rgbaStringToHex = (rgbaStr: any) => { + // // Remove the "rgba(" part and close parenthesis + // const rgbaParts = rgbaStr.replace('rgba(', '').replace(')', ''); - // Split the string into individual components - const [r, g, b, a] = rgbaParts - .split(',') - .map(part => parseInt(part.trim())); + // // Split the string into individual components + // const [r, g, b, a] = rgbaParts + // .split(',') + // .map((part: any) => parseInt(part.trim())); - // Convert R, G, B to hexadecimal and ensure they are two digits long - const rHex = r.toString(16).padStart(2, '0'); - const gHex = g.toString(16).padStart(2, '0'); - const bHex = b.toString(16).padStart(2, '0'); + // // Convert R, G, B to hexadecimal and ensure they are two digits long + // const rHex = r.toString(16).padStart(2, '0'); + // const gHex = g.toString(16).padStart(2, '0'); + // const bHex = b.toString(16).padStart(2, '0'); - // Optionally handle alpha channel if needed - // For simplicity, this example ignores the alpha channel - // If you need to include alpha, you could append it after the RGB part, e.g., `return '#' + rHex + gHex + bHex + (a === 1 ? '' : a.toString(16));` - return '#' + rHex + gHex + bHex; - }; + // // Optionally handle alpha channel if needed + // // For simplicity, this example ignores the alpha channel + // // If you need to include alpha, you could append it after the RGB part, e.g., `return '#' + rHex + gHex + bHex + (a === 1 ? '' : a.toString(16));` + // return '#' + rHex + gHex + bHex; + // }; - const rgbArrToHex = rgbArr => { + const rgbArrToHex = (rgbArr: any) => { const hex = rgbArr - .map(val => { + .map((val: any) => { return val.toString(16).padStart(2, '0'); return hex.length === 1 ? '0' + hex : hex; }) @@ -51,7 +51,7 @@ const StopRow = ({ return '#' + hex; }; - const hexToRgb = hex => { + const hexToRgb = (hex: any) => { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); const l = result ? [ @@ -63,14 +63,15 @@ const StopRow = ({ return l; }; - const handleValueChange = event => { + const handleValueChange = (event: React.ChangeEvent) => { const newRows = [...stopRows]; - stopRows[index].value = event.target.value; + const value = parseFloat(event.target.value); + stopRows[index].value = value; setStopRows(newRows); - setInputZoom(event.target.value); + setInputZoom(value); }; - const handleColorChange = event => { + const handleColorChange = (event: React.ChangeEvent) => { const newRows = [...stopRows]; stopRows[index].color = hexToRgb(event.target.value); setStopRows(newRows); diff --git a/packages/base/src/dialogs/layerBrowserDialog.tsx b/packages/base/src/dialogs/layerBrowserDialog.tsx index 60bf64c0..d6954bac 100644 --- a/packages/base/src/dialogs/layerBrowserDialog.tsx +++ b/packages/base/src/dialogs/layerBrowserDialog.tsx @@ -59,7 +59,7 @@ export const LayerBrowserComponent = ({ /** * Track which layers are currently added to the map */ - const handleLayerChange = (_, change: IJGISLayerDocChange) => { + const handleLayerChange = (_: any, change: IJGISLayerDocChange) => { // The split is to get rid of the 'Layer' part of the name to match the names in the gallery setActiveLayers( Object.values(context.model.sharedModel.layers).map( diff --git a/packages/base/src/formbuilder/objectform/baseform.tsx b/packages/base/src/formbuilder/objectform/baseform.tsx index 8c03899b..3ad68124 100644 --- a/packages/base/src/formbuilder/objectform/baseform.tsx +++ b/packages/base/src/formbuilder/objectform/baseform.tsx @@ -1,7 +1,7 @@ import { SchemaForm } from '@deathbeds/jupyterlab-rjsf'; import { MessageLoop } from '@lumino/messaging'; import { Widget } from '@lumino/widgets'; -import { IChangeEvent, ISubmitEvent, WidgetProps } from '@rjsf/core'; +import { IChangeEvent, ISubmitEvent } from '@rjsf/core'; import * as React from 'react'; import { IJupyterGISModel } from '@jupytergis/schema'; diff --git a/packages/base/src/formbuilder/objectform/tilesourceform.ts b/packages/base/src/formbuilder/objectform/tilesourceform.ts index 2daaad81..99938043 100644 --- a/packages/base/src/formbuilder/objectform/tilesourceform.ts +++ b/packages/base/src/formbuilder/objectform/tilesourceform.ts @@ -35,7 +35,7 @@ export class TileSourcePropertiesForm extends BaseForm { } // Dynamically inject url parameters schema based of the url - const propertiesSchema = {}; + const propertiesSchema: { [name: string]: any } = {}; schema.properties.urlParameters = { type: 'object', required: this._urlParameters, diff --git a/packages/base/src/formbuilder/objectform/vectorlayerform.ts b/packages/base/src/formbuilder/objectform/vectorlayerform.ts index c968c1a8..abc8c318 100644 --- a/packages/base/src/formbuilder/objectform/vectorlayerform.ts +++ b/packages/base/src/formbuilder/objectform/vectorlayerform.ts @@ -8,9 +8,9 @@ import { ILayerProps, LayerPropertiesForm } from './layerform'; * The form to modify a vector layer. */ export class VectorLayerPropertiesForm extends LayerPropertiesForm { - private sourceLayers: string[] = []; - private currentSourceUrl = ''; protected currentFormData: IVectorLayer; + private sourceLayers: string[] = []; + private currentSourceId: string; constructor(props: ILayerProps) { super(props); @@ -111,9 +111,6 @@ export class VectorLayerPropertiesForm extends LayerPropertiesForm { sourceData = currentSource.parameters as IVectorTileSource; } - // if (this.currentSourceUrl !== sourceData.url) { - this.currentSourceUrl = sourceData.url; - try { this.sourceLayers = await getSourceLayerNames( sourceData.url, @@ -123,13 +120,10 @@ export class VectorLayerPropertiesForm extends LayerPropertiesForm { } catch (e) { console.error(e); } - // } } else { this.currentSourceId = ''; this.sourceLayers = []; this.forceUpdate(); } } - - private currentSourceId: string; } diff --git a/packages/base/src/mainview/mainView.tsx b/packages/base/src/mainview/mainView.tsx index a541acf8..06e4296b 100644 --- a/packages/base/src/mainview/mainView.tsx +++ b/packages/base/src/mainview/mainView.tsx @@ -26,6 +26,7 @@ import { IObservableMap, ObservableMap } from '@jupyterlab/observables'; import { User } from '@jupyterlab/services'; import { JSONValue, UUID } from '@lumino/coreutils'; import { Map as OlMap, View } from 'ol'; +import { FeatureLike } from 'ol/Feature'; import { GeoJSON, MVT } from 'ol/format'; import DragAndDrop from 'ol/interaction/DragAndDrop'; import { @@ -57,6 +58,7 @@ import { isLightTheme } from '../tools'; interface IProps { viewModel: MainViewModel; } + interface IStates { id: string; // ID of the component, it is used to identify which component //is the source of awareness updates. @@ -141,10 +143,6 @@ export class MainView extends React.Component { }); dragAndDropInteraction.on('addfeatures', event => { - // const source = new VectorSource({ - // features: event.features - // }); - const sourceId = UUID.uuid4(); const sourceModel: IJGISSource = { @@ -172,10 +170,6 @@ export class MainView extends React.Component { const layerId = UUID.uuid4(); this.addLayer(layerId, layerModel, this.getLayers().length); this._model.addLayer(layerId, layerModel); - - // this._Map - // .getView() - // .fit(this._sources[layerModel.parameters?.source].getExtent()); }); this._Map.addInteraction(dragAndDropInteraction); @@ -572,7 +566,7 @@ export class MainView extends React.Component { this._Map.getLayers().insertAt(index, newLayer); } - vectorLayerStyleFunc = (currentFeature, layer) => { + vectorLayerStyleFunc = (currentFeature: FeatureLike, layer: IJGISLayer) => { const layerParameters = layer.parameters as IVectorLayer; // const flatStyle = { @@ -587,12 +581,12 @@ export class MainView extends React.Component { // TODO: Need to make a version that works with strings as well const operators = { - '>': (a, b) => a > b, - '<': (a, b) => a < b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - '==': (a, b) => a === b, - '!=': (a, b) => a !== b + '>': (a: number | string, b: number | string) => a > b, + '<': (a: number | string, b: number | string) => a < b, + '>=': (a: number | string, b: number | string) => a >= b, + '<=': (a: number | string, b: number | string) => a <= b, + '==': (a: number | string, b: number | string) => a === b, + '!=': (a: number | string, b: number | string) => a !== b }; // TODO: I don't think this will work with fancy color expressions @@ -668,7 +662,7 @@ export class MainView extends React.Component { // Other frequently used methods include the Mapbox format // (red * 256 * 256 + green * 256 + blue) * 0.1 - 10000 // - function elevation(xOffset, yOffset) { + function elevation(xOffset: number, yOffset: number) { const red = ['band', 1, xOffset, yOffset]; const green = ['band', 2, xOffset, yOffset]; const blue = ['band', 3, xOffset, yOffset]; @@ -942,17 +936,6 @@ export class MainView extends React.Component { }); } - private getSource(id: string): T | undefined { - const source = this._model.sharedModel.getSource(id); - - if (!source || !source.parameters) { - console.log(`Source id ${id} does not exist`); - return; - } - - return source.parameters as T; - } - private _handleThemeChange = (): void => { const lightTheme = isLightTheme(); diff --git a/packages/base/src/panelview/components/filter-panel/Filter.tsx b/packages/base/src/panelview/components/filter-panel/Filter.tsx index a54a50b0..3a2f4d50 100644 --- a/packages/base/src/panelview/components/filter-panel/Filter.tsx +++ b/packages/base/src/panelview/components/filter-panel/Filter.tsx @@ -103,7 +103,7 @@ const FilterComponent = (props: IFilterComponentProps) => { setSelectedLayer(currentLayer); }; - const handleSharedOptionsChanged = (_, keys) => { + const handleSharedOptionsChanged = (_: any, keys: any) => { // model changes when current widget changes, don't want this to run in that case if (props.tracker.currentWidget?.id === widgetId && keys.has('zoom')) { if (!model?.localState?.selected?.value) { diff --git a/packages/base/src/panelview/components/filter-panel/FilterRow.tsx b/packages/base/src/panelview/components/filter-panel/FilterRow.tsx index fe108039..d9970e91 100644 --- a/packages/base/src/panelview/components/filter-panel/FilterRow.tsx +++ b/packages/base/src/panelview/components/filter-panel/FilterRow.tsx @@ -18,7 +18,9 @@ const FilterRow = ({ }) => { const operators = ['==', '!=', '>', '<', '>=', '<=']; - const [sortedFeatures, setSortedFeatures] = useState({}); + const [sortedFeatures, setSortedFeatures] = useState<{ [key: string]: any }>( + {} + ); const [selectedFeature, setSelectedFeature] = useState( filterRows[index].feature || Object.keys(features)[0] ); @@ -30,7 +32,7 @@ const FilterRow = ({ useEffect(() => { const sortedKeys = Object.keys(features).sort(); - const sortedResult = {}; + const sortedResult: { [key: string]: any } = {}; for (const key of sortedKeys) { // Convert each Set to a sorted array @@ -52,31 +54,34 @@ const FilterRow = ({ } const currentValue = valueSelect.options[valueSelect.selectedIndex]?.value; - currentValue && - handleValueChange({ - target: { value: currentValue } - }); + currentValue && onValueChange(currentValue); }, [selectedFeature]); - const handleKeyChange = event => { + const onValueChange = (value: string | number) => { + const newFilters = [...filterRows]; + const isNum = typeof sortedFeatures[selectedFeature][0] === 'number'; + + newFilters[index].value = isNum ? +value : value; + setFilterRows(newFilters); + }; + + const handleKeyChange = (event: React.ChangeEvent) => { const newFilters = [...filterRows]; newFilters[index].feature = event.target.value; setSelectedFeature(event.target.value); setFilterRows(newFilters); }; - const handleOperatorChange = event => { + const handleOperatorChange = ( + event: React.ChangeEvent + ) => { const newFilters = [...filterRows]; newFilters[index].operator = event.target.value; setFilterRows(newFilters); }; - const handleValueChange = event => { - const newFilters = [...filterRows]; - const isNum = typeof sortedFeatures[selectedFeature][0] === 'number'; - - newFilters[index].value = isNum ? +event.target.value : event.target.value; - setFilterRows(newFilters); + const handleValueChange = (event: React.ChangeEvent) => { + onValueChange(event.target.value); }; return ( diff --git a/packages/base/src/panelview/components/layers.tsx b/packages/base/src/panelview/components/layers.tsx index 38dcba47..1cac2cab 100644 --- a/packages/base/src/panelview/components/layers.tsx +++ b/packages/base/src/panelview/components/layers.tsx @@ -12,6 +12,7 @@ import { ReactWidget, caretDownIcon } from '@jupyterlab/ui-components'; +import { ReadonlyPartialJSONValue } from '@lumino/coreutils'; import { Panel } from '@lumino/widgets'; import React, { MouseEvent as ReactMouseEvent, @@ -242,10 +243,10 @@ function LayerGroupComponent(props: ILayerGroupProps): JSX.Element { useEffect(() => { setId(DOMUtils.createDomID()); - const getExpandedState = async () => { - const groupState = await state.fetch(group.name); - setOpen(groupState ? groupState['expanded'] : false); + const groupState: ReadonlyPartialJSONValue | undefined = + await state.fetch(group.name); + setOpen(groupState ? (groupState as any)['expanded'] ?? false : false); }; getExpandedState(); diff --git a/packages/base/src/tools.ts b/packages/base/src/tools.ts index 69eade31..c62d5faf 100644 --- a/packages/base/src/tools.ts +++ b/packages/base/src/tools.ts @@ -18,10 +18,10 @@ export const debounce = ( func: CallableFunction, timeout = 100 ): CallableFunction => { - let timeoutId; - return (...args) => { + let timeoutId: number; + return (...args: any[]) => { clearTimeout(timeoutId); - timeoutId = setTimeout(() => { + timeoutId = window.setTimeout(() => { func(...args); }, timeout); }; @@ -157,7 +157,7 @@ export function createDefaultLayerRegistry( importAll(context); for (const entry of Object.keys(RASTER_LAYER_GALLERY)) { - const xyzprovider = RASTER_LAYER_GALLERY[entry]; + const xyzprovider: any = (RASTER_LAYER_GALLERY as any)[entry]; if ('url' in xyzprovider) { const tile = convertToRegistryEntry(entry, xyzprovider); diff --git a/packages/schema/src/model.ts b/packages/schema/src/model.ts index e01ca64d..1bc49cc4 100644 --- a/packages/schema/src/model.ts +++ b/packages/schema/src/model.ts @@ -609,7 +609,7 @@ export class JupyterGISModel implements IJupyterGISModel { }; } - private _onClientStateChanged = changed => { + private _onClientStateChanged = (changed: any) => { const clients = this.sharedModel.awareness.getStates() as Map< number, IJupyterGISClientState @@ -617,7 +617,7 @@ export class JupyterGISModel implements IJupyterGISModel { this._clientStateChanged.emit(clients); - this._sharedModel.awareness.on('change', update => { + this._sharedModel.awareness.on('change', (update: any) => { if (update.added.length || update.removed.length) { this._userChanged.emit(this.users); } diff --git a/python/jupytergis_qgis/src/plugins.ts b/python/jupytergis_qgis/src/plugins.ts index b81a8c9b..a74e01a5 100644 --- a/python/jupytergis_qgis/src/plugins.ts +++ b/python/jupytergis_qgis/src/plugins.ts @@ -104,7 +104,7 @@ const activate = async ( QGISSharedModelFactory ); - const widgetCreatedCallback = (sender, widget: JupyterGISWidget) => { + const widgetCreatedCallback = (sender: any, widget: JupyterGISWidget) => { // Notify the instance tracker if restore data needs to update. widget.context.pathChanged.connect(() => { tracker.save(widget); diff --git a/tsconfigbase.json b/tsconfigbase.json index 5c5c09ba..e056fcdf 100644 --- a/tsconfigbase.json +++ b/tsconfigbase.json @@ -9,8 +9,8 @@ "module": "esnext", "moduleResolution": "node", "noEmitOnError": true, - "noImplicitAny": false, - "noUnusedLocals": false, + "noImplicitAny": true, + "noUnusedLocals": true, "preserveWatchOutput": true, "resolveJsonModule": true, "strict": true, diff --git a/ui-tests/tests/gis-files/context-test.jGIS b/ui-tests/tests/gis-files/context-test.jGIS index 9498dbcc..a6aaf774 100644 --- a/ui-tests/tests/gis-files/context-test.jGIS +++ b/ui-tests/tests/gis-files/context-test.jGIS @@ -48,6 +48,7 @@ "latitude": 45.83799886047626, "longitude": 1.195999428191726, "pitch": 0.0, + "projection": "EPSG:3857", "zoom": 4.075821017792898 }, "sources": { @@ -77,5 +78,6 @@ }, "type": "GeoJSONSource" } - } + }, + "terrain": {} } \ No newline at end of file diff --git a/ui-tests/tests/gis-files/empty-france.jGIS b/ui-tests/tests/gis-files/empty-france.jGIS index b2d62039..db0e24c4 100644 --- a/ui-tests/tests/gis-files/empty-france.jGIS +++ b/ui-tests/tests/gis-files/empty-france.jGIS @@ -1,12 +1,13 @@ { + "layerTree": [], "layers": {}, - "sources": {}, "options": { - "bearing": 0.0, + "bearing": 0.0, "latitude": 44.75868528451835, "longitude": 3.12113766286636, "projection": "EPSG:3857", "zoom": 4.920920690595499 }, - "layerTree": [] + "sources": {}, + "terrain": {} } \ No newline at end of file diff --git a/ui-tests/tests/gis-files/filter-test.jGIS b/ui-tests/tests/gis-files/filter-test.jGIS index c58ba795..a86bee6a 100644 --- a/ui-tests/tests/gis-files/filter-test.jGIS +++ b/ui-tests/tests/gis-files/filter-test.jGIS @@ -1,5 +1,5 @@ { - "layerTree": [ + "layerTree": [ "f907e26c-c4c8-4c2d-ad62-813f63ed9de9", "0336896f-f7ce-460f-8d11-07a589ff03d8" ], @@ -31,8 +31,9 @@ "options": { "bearing": 0.0, "latitude": 36.721052981505736, - "longitude": -117.65116711904051, + "longitude": -117.6511671190405, "pitch": 0.0, + "projection": "EPSG:3857", "zoom": 3.9435402350822097 }, "sources": { diff --git a/ui-tests/tests/gis-files/panel-test.jGIS b/ui-tests/tests/gis-files/panel-test.jGIS index 9498dbcc..a6aaf774 100644 --- a/ui-tests/tests/gis-files/panel-test.jGIS +++ b/ui-tests/tests/gis-files/panel-test.jGIS @@ -48,6 +48,7 @@ "latitude": 45.83799886047626, "longitude": 1.195999428191726, "pitch": 0.0, + "projection": "EPSG:3857", "zoom": 4.075821017792898 }, "sources": { @@ -77,5 +78,6 @@ }, "type": "GeoJSONSource" } - } + }, + "terrain": {} } \ No newline at end of file diff --git a/ui-tests/tests/gis-files/test.jGIS b/ui-tests/tests/gis-files/test.jGIS index 9498dbcc..a6aaf774 100644 --- a/ui-tests/tests/gis-files/test.jGIS +++ b/ui-tests/tests/gis-files/test.jGIS @@ -48,6 +48,7 @@ "latitude": 45.83799886047626, "longitude": 1.195999428191726, "pitch": 0.0, + "projection": "EPSG:3857", "zoom": 4.075821017792898 }, "sources": { @@ -77,5 +78,6 @@ }, "type": "GeoJSONSource" } - } + }, + "terrain": {} } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0ef5900d..9f2fa254 100644 --- a/yarn.lock +++ b/yarn.lock @@ -928,6 +928,7 @@ __metadata: "@types/d3-color": ^3.1.0 "@types/node": ^18.15.11 "@types/three": ^0.135.0 + "@types/uuid": ^10.0.0 ajv: ^8.14.0 d3-color: ^3.1.0 geojson-schema: ^1.0.5 @@ -3313,6 +3314,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^10.0.0": + version: 10.0.0 + resolution: "@types/uuid@npm:10.0.0" + checksum: e3958f8b0fe551c86c14431f5940c3470127293280830684154b91dc7eb3514aeb79fe3216968833cf79d4d1c67f580f054b5be2cd562bebf4f728913e73e944 + languageName: node + linkType: hard + "@types/webpack-env@npm:^1.18.5": version: 1.18.5 resolution: "@types/webpack-env@npm:1.18.5"