Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2170-Schema cleanup and inheritance #2171

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/app/geoview-layer/map-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The `navBar` property is optional and its type is `TypeNavBarProps`. It is used

## components

The `components` property is optional and its type is `TypeMapComponents` which is an array whose value domain is `'north-arrow', 'overview-map'`.
The `components` property is optional and its type is `TypeMapComponents[]` which is an array whose value domain is `'north-arrow', 'overview-map'`.

## corePackages

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions packages/geoview-core/public/configs/validator/04-geocore.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"map": {
"interaction": "dynamic",
"viewSettings": {
"minZoom": 5,
"projection": 3857
},
"basemapOptions": {
"basemapId": "transport",
"shaded": false,
"labeled": true
},
"listOfGeoviewLayerConfig": [
{
"geoviewLayerId": "12acd145-626a-49eb-b850-0a59c9bc7506",
"isGeocore": true
},
{
"geoviewLayerId": "ccc75c12-5acc-4a6a-959f-ef6f621147b9",
"isGeocore": true
}
],
"highlightColor": "black",
"extraOptions": {}
},
"theme": "geo.ca",
"navBar": [
"zoom",
"fullscreen",
"home"
],
"appBar": {
"tabs": {
"core": [
"geolocator"
]
}
},
"overviewMap": {
"hideOnZoom": 0
},
"components": [
"overview-map"
],
"corePackages": [],
"externalPackages": [],
"schemaVersionUsed": "1.0"
}
28 changes: 15 additions & 13 deletions packages/geoview-core/public/templates/config-sandbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ <h1><strong>Sandbox Configuration</strong></h1>
<tbody>
<tr>
<td>
<span style="margin:10px;">Input Configuration</span>
<div class="editor">
<div class="line-numbers" id="inputLineNumbers">
<span></span>
Expand All @@ -112,6 +113,7 @@ <h1><strong>Sandbox Configuration</strong></h1>
</div>
</td>
<td>
<span style="margin:10px;">Internal configuration:</span>
<span id="validationMessage" style="margin:10px;">File not validated...</span>
<div class="editor">
<div class="line-numbers" id="outputLineNumbers">
Expand Down Expand Up @@ -184,7 +186,7 @@ <h4 id="HLCONF1">Sanbox Map</h4>
return res.text();
})
.then((data) => {
document.getElementById('configGeoview').textContent = data;
document.getElementById('configGeoview').value = data;

// set default number of lines
const textarea = document.querySelector('textarea');
Expand Down Expand Up @@ -212,18 +214,18 @@ <h4 id="HLCONF1">Sanbox Map</h4>
const configArea = document.getElementById('configGeoview');
const configOutput = document.getElementById('configOutput');

// get config and test if JSON is valid
const mapConfig = cgpv.api.configApi.getMapConfig(configArea.value.replaceAll('"', "'").replaceAll("\\'", "\'"), langue);
configOutput.textContent = mapConfig.getIndentedJsonString();

// Generate line numbers
(() => {
const textarea = document.getElementById('configOutput');
const lineNumbersContainer = document.getElementById('outputLineNumbers');
const lines = textarea.value.split('\n').length+1;
const lineNumbers = Array.from({ length: lines }, (_, index) => '').join('<span />');
lineNumbersContainer.innerHTML = lineNumbers;
})();
// get config and test if JSON is valid
const mapConfig = cgpv.api.configApi.getMapConfig(configArea.value.replaceAll('"', "'").replaceAll("\\'", "\'"), langue);
configOutput.value = mapConfig.getIndentedJsonString();

// Generate line numbers
(() => {
const textarea = document.getElementById('configOutput');
const lineNumbersContainer = document.getElementById('outputLineNumbers');
const lines = textarea.value.split('\n').length+1;
const lineNumbers = Array.from({ length: lines }, (_, index) => '').join('<span />');
lineNumbersContainer.innerHTML = lineNumbers;
})();

// set class and message
message.classList.add('config-json-valid');
Expand Down
2 changes: 1 addition & 1 deletion packages/geoview-core/src/api/config/config-api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { CV_DEFAULT_MAP_FEATURE_CONFIG } from '@config/types/config-constants';
import { Cast, TypeJsonValue, TypeJsonObject, toJsonObject, TypeJsonArray } from '@config/types/config-types';
import { TypeDisplayLanguage } from '@config/types/map-schema-types';
import { MapFeatureConfig } from '@config/types/classes/map-feature-config';
import { UUIDmapConfigReader } from '@config/uuid-config-reader';
import { TypeDisplayLanguage } from '@config/types/map-schema-types';
import { logger } from '@/core//utils/logger';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
// Needs to disable class-methods-use-this because we need to pass the instance reference 'this' to the agregated sublayers.
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
import defaultsDeep from 'lodash/defaultsDeep';
import cloneDeep from 'lodash/cloneDeep';

import { MapFeatureConfig } from '@config/types/classes/map-feature-config';
import { Cast, TypeGeoviewLayerType, TypeJsonObject, TypeJsonArray } from '@config/types/config-types';
import { ConfigBaseClass } from '@config/types/classes/sub-layer-config/config-base-class';
import { TypeDisplayLanguage, TypeLayerInitialSettings } from '@config/types/map-schema-types';
import { normalizeLocalizedString } from '@config/utils';
import { CV_CONST_SUB_LAYER_TYPES, CV_DEFAULT_LAYER_INITIAL_SETTINGS } from '@config/types/config-constants';
import { CV_DEFAULT_LAYER_INITIAL_SETTINGS } from '@config/types/config-constants';
import { GroupLayerEntryConfig } from '@config/types/classes/sub-layer-config/group-layer-entry-config';
import { layerEntryIsGroupLayer } from '@config/types/type-guards';
import { logger } from '@/core/utils/logger';
import { generateId } from '@/core/utils/utilities';
import { MapFeatureConfig } from '@/api/config/types/classes/map-feature-config';

/**
* Base class for the definition of a Geoview layer configuration.
Expand Down Expand Up @@ -76,14 +73,14 @@ export abstract class AbstractGeoviewLayerConfig {
this.initialSettings = Cast<TypeLayerInitialSettings>(
defaultsDeep(this.#originalgeoviewLayerConfig.initialSettings, CV_DEFAULT_LAYER_INITIAL_SETTINGS)
);
// Topmost layer must be a layer group or a leaf node.
// The top layer must be a layer group or a leaf node.
if ((this.#originalgeoviewLayerConfig.listOfLayerEntryConfig as TypeJsonArray).length > 1)
(this.#originalgeoviewLayerConfig.listOfLayerEntryConfig as TypeJsonArray) = [
{
layerId: this.#originalgeoviewLayerConfig.geoviewLayerId,
initialSettings: this.initialSettings as TypeJsonObject,
layerName: { ...(this.#originalgeoviewLayerConfig.geoviewLayerName as object) },
entryType: CV_CONST_SUB_LAYER_TYPES.GROUP as TypeJsonObject,
isLayerGroup: true as TypeJsonObject,
listOfLayerEntryConfig: this.#originalgeoviewLayerConfig.listOfLayerEntryConfig,
},
];
Expand All @@ -108,22 +105,13 @@ export abstract class AbstractGeoviewLayerConfig {
* @private
*/
protected validate(): void {
if (!this.geoviewLayerType) {
logger.logError(`Property geoviewLayerType is mandatory for GeoView layer ${this.geoviewLayerId} of type ${this.geoviewLayerType}.`);
this.propagateError();
}
if (!this.geoviewLayerId) {
throw new Error(`geoviewLayerId is mandatory for GeoView layer of type ${this.geoviewLayerType}.`);
this.propagateError();
}
if (!this.geoviewLayerName) {
logger.logError(`Property geoviewLayerName is mandatory for GeoView layer ${this.geoviewLayerId} of type ${this.geoviewLayerType}.`);
this.propagateError();
}
if (!this.metadataAccessPath) {
if (!this.geoviewLayerType)
throw new Error(`Property geoviewLayerType is mandatory for GeoView layer ${this.geoviewLayerId} of type ${this.geoviewLayerType}.`);
if (!this.geoviewLayerId) throw new Error(`geoviewLayerId is mandatory for GeoView layer of type ${this.geoviewLayerType}.`);
if (!this.geoviewLayerName)
throw new Error(`Property geoviewLayerName is mandatory for GeoView layer ${this.geoviewLayerId} of type ${this.geoviewLayerType}.`);
if (!this.metadataAccessPath)
throw new Error(`metadataAccessPath is mandatory for GeoView layer ${this.geoviewLayerId} of type ${this.geoviewLayerType}.`);
this.propagateError();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,17 @@ import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config
import { EsriDynamicLayerEntryConfig } from '@config/types/classes/sub-layer-config/raster-leaf/esri-dynamic-layer-entry-config';
import { ConfigBaseClass } from '@config/types/classes/sub-layer-config/config-base-class';
import { GroupLayerEntryConfig } from '@config/types/classes/sub-layer-config/group-layer-entry-config';
import { AbstractBaseLayerEntryConfig } from '@config/types/classes/sub-layer-config/abstract-base-layer-entry-config';
import { TypeGeoviewLayerType, TypeJsonObject } from '@config/types/config-types';
import { TypeJsonObject } from '@config/types/config-types';
import { TypeDisplayLanguage, TypeLayerInitialSettings } from '@config/types/map-schema-types';
import { isvalidComparedToSchema } from '@config/utils';
import { MapFeatureConfig } from '@/api/config/types/classes/map-feature-config';
import { MapFeatureConfig } from '@config/types/classes/map-feature-config';

/* */
export type TypeEsriDynamicLayerNode = GroupLayerEntryConfig | EsriDynamicLayerEntryConfig;

export type TypeEsriDynamicLayerNode = GroupLayerEntryConfig | (AbstractBaseLayerEntryConfig & EsriDynamicLayerEntryConfig);

/**
* The ESRI dynamic geoview layer class.
*/
/** The ESRI dynamic geoview layer class. */
export class EsriDynamicLayerConfig extends AbstractGeoviewLayerConfig {
/** Type of GeoView layer. */
geoviewLayerType: TypeGeoviewLayerType;
geoviewLayerType = CV_CONST_LAYER_TYPES.ESRI_DYNAMIC;

/** The layer entries to use from the GeoView layer. */
declare listOfLayerEntryConfig: TypeEsriDynamicLayerNode[];
Expand All @@ -32,7 +27,6 @@ export class EsriDynamicLayerConfig extends AbstractGeoviewLayerConfig {
*/
constructor(layerConfig: TypeJsonObject, language: TypeDisplayLanguage, mapFeatureConfig?: MapFeatureConfig) {
super(layerConfig, language, mapFeatureConfig);
this.geoviewLayerType = CV_CONST_LAYER_TYPES.ESRI_DYNAMIC;
if (!isvalidComparedToSchema(this.geoviewLayerSchema, layerConfig)) this.propagateError();
if (!isvalidComparedToSchema(this.geoviewLayerSchema, this)) this.propagateError();
this.validate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,17 @@ import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config
import { EsriFeatureLayerEntryConfig } from '@config/types/classes/sub-layer-config/vector-leaf/esri-feature-layer-entry-config';
import { ConfigBaseClass } from '@config/types/classes/sub-layer-config/config-base-class';
import { GroupLayerEntryConfig } from '@config/types/classes/sub-layer-config/group-layer-entry-config';
import { AbstractBaseLayerEntryConfig } from '@config/types/classes/sub-layer-config/abstract-base-layer-entry-config';
import { TypeGeoviewLayerType, TypeJsonObject } from '@config/types/config-types';
import { TypeJsonObject } from '@config/types/config-types';
import { TypeDisplayLanguage, TypeLayerInitialSettings } from '@config/types/map-schema-types';
import { isvalidComparedToSchema } from '@config/utils';
import { MapFeatureConfig } from '@/api/config/types/classes/map-feature-config';
import { MapFeatureConfig } from '@config/types/classes/map-feature-config';

/* */
export type TypeEsriFeatureLayerNode = GroupLayerEntryConfig | EsriFeatureLayerEntryConfig;

export type TypeEsriFeatureLayerNode =
| (ConfigBaseClass & GroupLayerEntryConfig)
| (ConfigBaseClass & AbstractBaseLayerEntryConfig & EsriFeatureLayerEntryConfig);

/**
* The ESRI feature geoview layer class.
*/
/** The ESRI feature geoview layer class. */
export class EsriFeatureLayerConfig extends AbstractGeoviewLayerConfig {
/** Type of GeoView layer. */
geoviewLayerType: TypeGeoviewLayerType;
geoviewLayerType = CV_CONST_LAYER_TYPES.ESRI_FEATURE;

/** The layer entries to use from the GeoView layer. */
declare listOfLayerEntryConfig: TypeEsriFeatureLayerNode[];
Expand All @@ -34,7 +27,6 @@ export class EsriFeatureLayerConfig extends AbstractGeoviewLayerConfig {
*/
constructor(layerConfig: TypeJsonObject, language: TypeDisplayLanguage, mapFeatureConfig?: MapFeatureConfig) {
super(layerConfig, language, mapFeatureConfig);
this.geoviewLayerType = CV_CONST_LAYER_TYPES.ESRI_FEATURE;
if (!isvalidComparedToSchema(this.geoviewLayerSchema, layerConfig)) this.propagateError();
if (!isvalidComparedToSchema(this.geoviewLayerSchema, this)) this.propagateError();
this.validate();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import cloneDeep from 'lodash/cloneDeep';
import defaultsDeep from 'lodash/defaultsDeep';

import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config/abstract-geoview-layer-config';
import { EsriDynamicLayerConfig } from '@config/types/classes/geoview-config/raster-config/esri-dynamic-config';
import { Cast, TypeJsonArray, TypeJsonObject, toJsonObject } from '@config/types/config-types';
import { EsriFeatureLayerConfig } from '@config/types/classes/geoview-config/vector-config/esri-feature-config';
import {
CV_BASEMAP_ID,
CV_BASEMAP_LABEL,
CV_BASEMAP_SHADED,
CV_CONST_LAYER_TYPES,
CV_DEFAULT_MAP_FEATURE_CONFIG,
CV_MAP_CENTER,
CV_MAP_CONFIG_SCHEMA_PATH,
CV_MAP_EXTENTS,
ACCEPTED_SCHEMA_VERSIONS,
VALID_PROJECTION_CODES,
} from '@config/types/config-constants';
import { isvalidComparedToSchema } from '@config/utils';
import {
Extent,
TypeAppBarProps,
Expand All @@ -16,24 +33,7 @@ import {
TypeServiceUrls,
TypeValidMapProjectionCodes,
TypeValidVersions,
VALID_PROJECTION_CODES,
VALID_VERSIONS,
} from '@config/types/map-schema-types';
import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config/abstract-geoview-layer-config';
import { EsriDynamicLayerConfig } from '@config/types/classes/geoview-config/raster-config/esri-dynamic-config';
import { Cast, TypeJsonArray, TypeJsonObject, toJsonObject } from '@config/types/config-types';
import { EsriFeatureLayerConfig } from '@config/types/classes/geoview-config/vector-config/esri-feature-config';
import {
CV_BASEMAP_ID,
CV_BASEMAP_LABEL,
CV_BASEMAP_SHADED,
CV_CONST_LAYER_TYPES,
CV_DEFAULT_MAP_FEATURE_CONFIG,
CV_MAP_CENTER,
CV_MAP_CONFIG_SCHEMA_PATH,
CV_MAP_EXTENTS,
} from '@config/types/config-constants';
import { isvalidComparedToSchema } from '@config/utils';
import { isJsonString, removeCommentsFromJSON } from '@/core/utils/utilities';
import { logger } from '@/core//utils/logger';

Expand Down Expand Up @@ -292,14 +292,14 @@ export class MapFeatureConfig {

this.#validateCenter();

// zoom cannot be undefined because udefined values were set with default values.
// zoom cannot be undefined because undefined values were set with default values.
const zoom = this.map.viewSettings.initialView!.zoomAndCenter![0];
this.map.viewSettings.initialView!.zoomAndCenter![0] =
!Number.isNaN(zoom) && zoom >= 0 && zoom <= 28 ? zoom : CV_DEFAULT_MAP_FEATURE_CONFIG.map.viewSettings.initialView!.zoomAndCenter![0];

this.#validateBasemap();

this.schemaVersionUsed = VALID_VERSIONS.includes(this.schemaVersionUsed!)
this.schemaVersionUsed = ACCEPTED_SCHEMA_VERSIONS.includes(this.schemaVersionUsed!)
? this.schemaVersionUsed
: CV_DEFAULT_MAP_FEATURE_CONFIG.schemaVersionUsed!;
const minZoom = this.map.viewSettings.minZoom!;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,26 @@
import cloneDeep from 'lodash/cloneDeep';

import { Cast, TypeJsonObject } from '@config/types/config-types';
import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config/abstract-geoview-layer-config';
import { ConfigBaseClass } from '@config/types/classes/sub-layer-config/config-base-class';
import {
TypeBaseSourceVectorInitialConfig,
TypeDisplayLanguage,
TypeLayerInitialSettings,
TypeSourceImageEsriInitialConfig,
TypeSourceImageInitialConfig,
TypeSourceImageStaticInitialConfig,
TypeSourceImageWmsInitialConfig,
TypeSourceTileInitialConfig,
TypeBaseSourceInitialConfig,
TypeTemporalDimension,
TypeVectorSourceInitialConfig,
TypeVectorTileSourceInitialConfig,
TypeGeometryType,
} from '@config/types/map-schema-types';
import { AbstractGeoviewLayerConfig } from '@config/types/classes/geoview-config/abstract-geoview-layer-config';
import { ConfigBaseClass } from '@config/types/classes/sub-layer-config/config-base-class';

// TODO: Refactor - Instead of listing all the possible types, for the `source` attribute, use a parent type
export type TypeSourceInitialConfig =
| TypeBaseSourceVectorInitialConfig
| TypeSourceTileInitialConfig
| TypeVectorSourceInitialConfig
| TypeVectorTileSourceInitialConfig
| TypeSourceImageInitialConfig
| TypeSourceImageWmsInitialConfig
| TypeSourceImageEsriInitialConfig
| TypeSourceImageStaticInitialConfig;
import { CV_DEFAULT_MAP_FEATURE_CONFIG } from '../../config-constants';

/**
* Base type used to define a GeoView sublayer to display on the map.
*/
export abstract class AbstractBaseLayerEntryConfig extends ConfigBaseClass {
/** The geometry type of the leaf node. */
geometryType: TypeGeometryType;

/** Source settings to apply to the GeoView vector layer source at creation time. */
source: TypeSourceInitialConfig;
source?: TypeBaseSourceInitialConfig;

/** Optional temporal dimension. */
temporalDimension?: TypeTemporalDimension;
Expand All @@ -55,12 +42,11 @@ export abstract class AbstractBaseLayerEntryConfig extends ConfigBaseClass {
parentNode?: ConfigBaseClass
) {
super(layerConfig, initialSettings, language, geoviewLayerConfig, parentNode);
this.geometryType = layerConfig.geometryType as TypeGeometryType;
// If the user has provided a source then keep it, else create one using default values.
if (layerConfig.source) this.source = Cast<TypeBaseSourceVectorInitialConfig>(cloneDeep(layerConfig.source));
else
this.source = {
maxRecordCount: 0,
};
// GV: This Cast operation uses a cloned version of the entire configuration, it covers even the child properties.
if (layerConfig.source) this.source = Cast<TypeBaseSourceInitialConfig>(cloneDeep(layerConfig.source));
else this.source = Cast<TypeBaseSourceInitialConfig>({ projection: CV_DEFAULT_MAP_FEATURE_CONFIG.map.viewSettings.projection });
if (layerConfig.temporalDimension) this.temporalDimension = Cast<TypeTemporalDimension>(cloneDeep(layerConfig.temporalDimension));
}
}
Loading
Loading