Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
86abfa8
feat: Restore part of funcionallity to implementation seitcher control
andrestcpy Jun 5, 2026
f1a6edf
Merge branch 'scaffolding' into refactor
andrestcpy Jun 5, 2026
6feb2f5
fix: tests of flyTo method on 3d view
andrestcpy Jun 8, 2026
acfa212
fix: destroy method of cesium control contains errors
andrestcpy Jun 8, 2026
6a309c8
Merge branch 'scaffolding' into refactor
andrestcpy Jun 8, 2026
d62b43d
feat: preselect current map implementation on first load
andrestcpy Jun 8, 2026
97550a7
feat: updates destroy method uncompleted
andrestcpy Jun 8, 2026
bde3c9c
Merge branch 'scaffolding' into refactor
andrestcpy Jun 8, 2026
8c7b78e
fix: fix cesium origin
andrestcpy Jun 9, 2026
4d943d2
Merge branch 'refactor' of https://github.com/sistemascotesa/API-IDEE…
andrestcpy Jun 9, 2026
84c1bd9
Merge branch 'scaffolding' into refactor
andrestcpy Jun 9, 2026
2cb28eb
Merge branch 'refactor' of https://github.com/sistemascotesa/API-IDEE…
andrestcpy Jun 9, 2026
e5d1f36
fix: restore implementation switcher src path
andrestcpy Jun 9, 2026
9c1ab06
feat: try to dont remove configuration file to restore the path
andrestcpy Jun 9, 2026
f11ee1e
Merge branch 'scaffolding' into refactor
andrestcpy Jun 9, 2026
2ea87e8
fix: an error ocurred on destroy one side panel nd all side active si…
andrestcpy Jun 9, 2026
662f5b6
feat: use corredt default projection on control implementation switcher
andrestcpy Jun 9, 2026
4f544fb
Merge branch 'refactor' of https://github.com/sistemascotesa/API-IDEE…
andrestcpy Jun 9, 2026
18775bf
Merge branch 'scaffolding' into refactor
andrestcpy Jun 9, 2026
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
6 changes: 3 additions & 3 deletions api-idee-js/src/facade/assets/css/overview_map_button.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
aspect-ratio: 1;
color: var(--idee-color-white);
background-color: var(--idee-color-primary);
border: 2px solid var(--idee-color-white);
border: 2px solid var(--button-border-color);
border-radius: 50%;
display: flex;
align-items: center;
Expand All @@ -20,7 +20,7 @@

.m-api-idee-container .m-overviewmap-button:hover,
.m-api-idee-container .m-control-button:hover {
border: 2px solid var(--idee-color-white) !important;
border: 2px solid var(--button-border-color) !important;
background-color: var(--idee-color-links);
transition: all 0.3s ease;
}
Expand All @@ -32,7 +32,7 @@

.m-api-idee-container .m-overviewmap-button.active,
.m-api-idee-container .m-control-button.active {
border: 2px solid var(--idee-color-white);
border: 2px solid var(--button-border-color);
color: var(--idee-color-white);
background-color: var(--idee-color-primary-dark);
transition: all 0.3s ease;
Expand Down
62 changes: 59 additions & 3 deletions api-idee-js/src/facade/js/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -3323,6 +3323,32 @@ class Map extends Base {
return this;
}

/**
* Hace un vuelo a una extensión dada con opciones de animación.
*
* @public
* @function
* @param {String|Array<String>|Array<Number>|Mx.Extent} extent Extensión [minX, minY, maxX, maxY].
* @param {Object} vendorOpts Opciones de proveedores.
* @returns {Map}
* @api
*/
flyTo(extent, vendorOpts = {}) {
if (isUndefined(MapImpl.prototype.flyTo)) {
Exception(getValue('exception').flyTo_method);
}

try {
// parses the parameter
const maxExtent = parameter.maxExtent(extent);
this.getImpl().flyTo(maxExtent, vendorOpts);
} catch (err) {
Dialog.error(getValue('exception').flyTo_method);
throw err;
}
return this;
}

/**
* Este método proporciona el zoom actual de esta
* instancia del mapa.
Expand Down Expand Up @@ -4035,8 +4061,9 @@ class Map extends Base {
plugin.destroy();
this.plugins = this.plugins.filter((plugin2) => plugin2.name !== plugin.name);

const plugins = this.plugins.filter((plugin2) => plugin2.position === plugin.position);
if (plugins.length === 0) {
const positionPlugins = this.plugins
.filter((plugin2) => plugin2.position === plugin.position);
if (positionPlugins.length === 0) {
this.closeSidePanels(plugin.position);
}
} catch (e) {
Expand Down Expand Up @@ -4223,6 +4250,17 @@ class Map extends Base {
});
}

/**
* Este método elimina todas las capas del mapa.
*
* @public
* @function
* @api
*/
removeAllLayers() {
this.removeLayers(this.getLayers());
}

/**
* Este método destruye el mapa, limpiando el HTML
* y anular el registro de todos los eventos.
Expand All @@ -4237,9 +4275,14 @@ class Map extends Base {
if (isUndefined(MapImpl.prototype.destroy)) {
Exception(getValue('exception').destroy_method);
}

this.removeAllLayers();
this.getImpl().destroy();

const mapFrameContainer = this.getFrameContainer();
if (mapFrameContainer.children.length > 0) {
Array.from(mapFrameContainer.children).forEach((child) => child.remove());
}

return this;
}

Expand Down Expand Up @@ -4681,6 +4724,8 @@ class Map extends Base {
this.toolPanelsContainer.style.setProperty('--up-height', `${newHeight}px`);
}
});

this.mapFrameContainer_ = container;
}

/**
Expand Down Expand Up @@ -4865,6 +4910,17 @@ class Map extends Base {
this.toolPanelsContainer.style.setProperty('--up-height', `${this.openUpPanelHeight}px`);
}

/**
* Este método devuelve el contenedor del marco del mapa.
*
* @function
* @api
* @returns {Object} Devuelve el contenedor.
*/
getFrameContainer() {
return this.mapFrameContainer_;
}

/**
* Este método proporciona el contenedor.
*
Expand Down
183 changes: 126 additions & 57 deletions api-idee-js/src/facade/js/control/ImplementationSwitcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class ImplementationSwitcher extends ControlBase {
*/
constructor(options = {}) {
if (isUndefined(ImplementationSwitcherImpl) || (isObject(ImplementationSwitcherImpl)
&& isNullOrEmpty(Object.keys(ImplementationSwitcherImpl)))) {
&& isNullOrEmpty(Object.keys(ImplementationSwitcherImpl)))) {
Exception(getValue('exception').implementationswitcher_method);
}

Expand All @@ -64,16 +64,10 @@ class ImplementationSwitcher extends ControlBase {
super(ImplementationSwitcher.NAME, implementationSwitcherImpl, options);

if (!window.implementations) {
window.implementations = IDEE.config.implementationswitcher;

if (window.implementations?.length > 0) {
window.implementations[0].selected = true;

window.implementations = window.implementations.map((impl) => ({
...impl,
epsg: impl.type === 'cesium' ? 'EPSG:4979' : impl.epsg,
}));
}
window.implementations = (IDEE.config.implementationswitcher || []).map((impl) => ({
...impl,
epsg: impl.type === 'cesium' ? 'EPSG:4979' : impl.epsg,
}));
}

this.collapsible = isBoolean(options.collapsible) ? options.collapsible : true;
Expand All @@ -90,8 +84,10 @@ class ImplementationSwitcher extends ControlBase {
* @returns {Promise} HTML generado, promesa.
* @api
*/
createView() {
createView(map) {
return new Promise((resolve) => {
this.selectCurrentImplementation(map);

this.html = compileTemplate(template, {
vars: {
title: this.tooltip ?? getValue(ImplementationSwitcher.NAME).title,
Expand All @@ -106,6 +102,35 @@ class ImplementationSwitcher extends ControlBase {
});
}

/**
* Selecciona en el desplegable la implementación del mapa actual.
*
* @public
* @function
* @param {IDEE.Map} map Mapa actual.
* @api
*/
selectCurrentImplementation(map) {
const currentImplementation = map?.getImplementation?.();
const implementations = window.implementations || [];

if (implementations.length > 0) {
const currentIndex = implementations.findIndex((impl) => impl.type === currentImplementation);
const selectedIndex = implementations.findIndex((impl) => impl.selected);
const targetIndex = currentIndex >= 0 ? currentIndex : Math.max(selectedIndex, 0);

window.implementations = implementations.map((impl, index) => {
const nextImpl = { ...impl };
if (index === targetIndex) {
nextImpl.selected = true;
} else {
delete nextImpl.selected;
}
return nextImpl;
});
}
}

/**
* Esta función agrega el detector de eventos en el desplegable de implementaciones.
* @param {HTMLElement} html Elemento desplegable.
Expand All @@ -129,46 +154,70 @@ class ImplementationSwitcher extends ControlBase {
* @api
*/
loadImplementation(implementation) {
const API_IDEE_URL = IDEE.config.API_IDEE_URL;
const API_IDEE_URL = IDEE.config.API_IDEE_URL || '';
const baseUrl = API_IDEE_URL.endsWith('/') ? API_IDEE_URL : `${API_IDEE_URL}/`;
const resolveUrl = (value) => {
if (!value) return '';
if (/^(?:https?:)?\/\//i.test(value)) {
return value;
}
try {
return new URL(value.replace(/^\/+/, ''), baseUrl || document.baseURI).href;
} catch (error) {
return `${baseUrl}${value.replace(/^\/+/, '')}`;
}
};

const implementationUrl = resolveUrl(implementation.js);
const implementationCssUrl = resolveUrl(implementation.css);
const existingConfigScript = document.querySelector('script[src$="/config.js"], script[src$="config.js"]');

const configurationUrl = existingConfigScript ? existingConfigScript.src : resolveUrl('js/configuration.js');

if (existingConfigScript) {
existingConfigScript.remove();
}

window.implementations.forEach((impl) => {
// eslint-disable-next-line no-param-reassign
delete impl.selected;

const scripts = Array.from(document.querySelectorAll('script'))
.filter((script) => script.src === `${API_IDEE_URL}${impl.js}`);
Array.from(document.querySelectorAll('script'))
.filter((script) => script.src.endsWith(impl.js))
.forEach((script) => script.remove());

if (scripts.length > 0) {
scripts[0].remove();
}

const styles = Array.from(document.querySelectorAll('link[rel="stylesheet"]'))
.filter((style) => style.href === `${API_IDEE_URL}${impl.css}`);

if (styles.length > 0) {
styles[0].remove();
}
Array.from(document.querySelectorAll('link[rel="stylesheet"]'))
.filter((style) => style.href.endsWith(impl.css))
.forEach((style) => style.remove());
});

// remove duplicate configuration scripts, keep only the first one
if (configurationUrl) {
const configurationScripts = Array.from(document.querySelectorAll('script'))
.filter((configuration) => configuration.src === configurationUrl);
configurationScripts.slice(1).forEach((configuration) => configuration.remove());
}

// eslint-disable-next-line no-param-reassign
implementation.selected = true;

const configurations = Array.from(document.querySelectorAll('script'))
.filter((configuration) => configuration.src === `${API_IDEE_URL}js/configuration.js`);

const script = document.createElement('script');
script.type = 'text/javascript';
script.src = `${API_IDEE_URL}${implementation.js}`;
script.src = implementationUrl;
script.onload = () => {
if (configurations.length > 0) {
fetch(`${API_IDEE_URL}js/configuration.js`)
.then((response) => response.text())
.then((scriptContent) => {
// eslint-disable-next-line no-eval
const scriptFn = eval(scriptContent);
scriptFn.call(window);

this.loadMap(implementation);
});
const existingConfig = configurationUrl && document.querySelector(`script[src="${configurationUrl}"]`);
if (configurationUrl && !existingConfig) {
const configScript = document.createElement('script');
configScript.type = 'text/javascript';
configScript.src = configurationUrl;
configScript.onload = () => {
this.loadMap(implementation);
};
configScript.onerror = (error) => {
console.error('CONFIGURATION LOAD ERROR', configurationUrl, error);
this.loadMap(implementation);
};
document.body.appendChild(configScript);
} else {
this.loadMap(implementation);
}
Expand All @@ -180,31 +229,51 @@ class ImplementationSwitcher extends ControlBase {
};
document.body.appendChild(script);

const style = document.createElement('link');
style.type = 'text/css';
style.href = `${API_IDEE_URL}${implementation.css}`;
style.rel = 'stylesheet';
document.head.appendChild(style);
if (implementationCssUrl) {
const style = document.createElement('link');
style.type = 'text/css';
style.href = implementationCssUrl;
style.rel = 'stylesheet';
document.head.appendChild(style);
}
}

loadMap(implementation) {
const div = this.map.getContainer().id === ''
? this.map.getContainer().parentElement.parentElement : this.map.getContainer();
div.innerHTML = '';
/** @type {HTMLDivElement} */
const mapFrameContainer = this.map.getFrameContainer();
const rootContainer = mapFrameContainer || this.map.getContainer();

const center = [this.map.getCenter().x, this.map.getCenter().y];
const zoom = this.map.getZoom();
const sourceProjection = this.map.getProjection().code;
const destProjection = implementation.epsg;
const projection = implementation.epsg ?? IDEE.config.DEFAULT_PROJ;
const { x, y } = this.map.getCenter();
const center = (typeof ol !== 'undefined' && ol !== null)
? ol.proj.transform([x, y], sourceProjection, projection)
: transform([x, y], sourceProjection, projection);

const controls = Array.from(this.map.getControls()).map(
(control) => control.name ?? control.NAME,
);
const plugins = this.map.getPlugins();
const layers = [...this.map.getBaseLayers(), ...this.map.getRootLayers()];

this.map.removeControls(this);

try {
this.map.destroy();
} catch (e) {
// eslint-disable-next-line no-console
console.warn('Error destroying previous map', e);
}

IDEE.map({
container: div.id,
zoom: this.map.getZoom(),
center: (typeof ol !== 'undefined' && ol !== null)
? ol.proj.transform(center, sourceProjection, destProjection)
: transform(center, sourceProjection, destProjection),
controls: Array.from(this.map.getControls()).map((control) => control.name),
plugins: this.map.getPlugins(),
layers: this.map.getLayers(),
container: rootContainer.id,
zoom,
projection,
center,
controls,
plugins,
layers,
});
}

Expand Down
1 change: 1 addition & 0 deletions api-idee-js/src/facade/js/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
"invalidJsonFormat": "Invalid JSON format",
"removecontrol_method": "The used implementation does not have the removeControls method.",
"setmaxextent_method": "The used implementation does not have the setMaxExtent method.",
"flyTo_method": "The used implementation does not have the flyTo method.",
"getbbox_method": "The used implementation does not have the getBbox method.",
"no_bbox": "You have not specified any bbox.",
"setbbox_method": "The used implementation does not have the setBbox method.",
Expand Down
1 change: 1 addition & 0 deletions api-idee-js/src/facade/js/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@
"invalidJsonFormat": "Formato JSON inválido",
"removecontrol_method": "La implementación usada no posee el método removeControls.",
"setmaxextent_method": "La implementación usada no posee el método setMaxExtent.",
"flyTo_method": "La implementación usada no posee el método flyTo.",
"getbbox_method": "La implementación usada no posee el método getBbox.",
"no_bbox": "No ha especificado ningún bbox.",
"setbbox_method": "La implementación usada no posee el método setBbox.",
Expand Down
Loading