Skip to content

Commit

Permalink
refactor(events) - Finished work on events, incl. map-events, appbar,…
Browse files Browse the repository at this point in the history
… navbar, footerbar, and more (#1990)

* Appbar and Navbar events refactored
FooterBar and Modal events refactored
MapComponent and MapKeyFocus events refactored
Slider events refactored
Map-reload events refactored
Main Event class rewritten (now was a good time)
TimeSlider fix with the new Slider implementation

* Renaming AppBar to AppBarUI in ui folder
Added MapViewer as props in Shell.tsx
More ui refactoring
SliderBase ui deleted
Slider callbacks rewritten
  • Loading branch information
Alex-NRCan authored Apr 5, 2024
1 parent e6c0994 commit bbce924
Show file tree
Hide file tree
Showing 52 changed files with 994 additions and 1,730 deletions.
153 changes: 92 additions & 61 deletions packages/geoview-core/public/templates/ui-components.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ <h3>Accessing slider value from outside of the core viewer using api event liste

<script src="codedoc.js"></script>
<script>
function createAndAddSliderComponent(domId, propsSlider) {
// Create the react element
const compSlider = cgpv.react.createElement(cgpv.ui.elements.Slider, propsSlider);

// Add a slider component and link it to a map with mapId props
return cgpv.api.utilities.core.addUiComponent(domId, compSlider);
}

function createAndUpdateSliderComponent(domId, propsSlider, root) {
// Create the react element
const compSlider = cgpv.react.createElement(cgpv.ui.elements.Slider, propsSlider);

// Update the component
// GV Ideally, we'd like to reuse the root and just do root.render(), but it is unstable, because react doesn't know if you want to actually change the state inside the Slider component or not.
// It'll even try to guess based on the props you've sent it originally. This can be proven with the Math.random() below.
// This can lead to unexpected results. So, I've ended up just unmounting and recreating from scratch to make sure all state is reset inside Slider.
// In any case, jumping into react behavior from pure JavaScript calls seems counter-pattern and will need careful design and consideration on how to
// bridge the gap between React's declarative model and imperative JavaScript code. This pattern might lead to more issues like this down the road.
// If we really want to do that, I'm afraid we'll need explicit callbacks provided back via props - to pretend we're in React when we're not.

// Swap between twose 2 pattern to notice how the slider behaves when clicking a button, then scrolling, then clicking button again.
// 1) just recreates from scratch a new component
// 2) works for the min/max perfectly, but for the 'value' props it's hit or miss, because of the internal state on it, depending on the value given on each update!
// To test, click button, move slider, click button again.

// 1)
root.unmount();
return cgpv.api.utilities.core.addUiComponent(domId, compSlider);

// 2)
// root.render(compSlider);
// return root;
}

// initialize cgpv and api events, a callback is optional, used if calling api's after the rendering is ready
cgpv.init(
(mapId) => {
Expand Down Expand Up @@ -152,10 +186,10 @@ <h3>Accessing slider value from outside of the core viewer using api event liste
{ value: 2023, label: '2023' },
],
track: 'normal',
customOnChange: (dates) => {
onChange: (dates) => {
const field = cgpv.api.maps.UI1.layer.geoviewLayer('historical-flood/0').getTemporalDimension('historical-flood/0').field;
cgpv.api.maps.UI1.layer.geoviewLayer('historical-flood/0').applyViewFilter('historical-flood/0', `${field} >= date '${dates[0]}-01-01' and ${field} <= date '${dates[1]}-12-31'`);
},
}
})
);
/**
Expand All @@ -165,76 +199,73 @@ <h3>Accessing slider value from outside of the core viewer using api event liste
/**
* SLIDER UI SECTION START
*/

// get the slider position 2 dom element
const sliderPosition2 = document.getElementsByClassName('slider-position2');

// Props for slider 1
const propsSlider1 = {
mapId: 'UI1',
id: 'UI1-slider1',
min: 0,
max: 18,
value: 8,
marks: [
{ value: 0, label: 'Min Level 0' },
{ value: 4, label: 'Level 4' },
{ value: 8, label: 'Level 8' },
{ value: 18, label: 'Max Level 18' },
],
track: false,
// TODO: setting the view zoom level create bugs with the overview map
onChange: (zoomLevel) => {
const lat = 50;
const lng = -95;
cgpv.api.maps['UI1'].getView().animate({ zoom: zoomLevel });
},
};

// Create and add the react element
let root1 = createAndAddSliderComponent('UI1-slider1', propsSlider1);

// set min max
function setSliderMinMax() {
cgpv.api.event.emit({ event: 'slider/set_min_max', handlerName: 'UI1-slider1', sliderValues: { min: 2, max: 16 }})
// Update the react component from external call
root1 = createAndUpdateSliderComponent('UI1-slider1', {...propsSlider1, min: 4, max: 12}, root1);
}
document.getElementById('sliderminmax').addEventListener('click', setSliderMinMax, false);
document.getElementById('sliderminmax').addEventListener('click', setSliderMinMax);

// set values
function setSliderValues() {
cgpv.api.event.emit({ event: 'slider/set_values', handlerName: 'UI1-slider1', sliderValues: { min: 2, max: 16, value: 8 }})
// Update the react component from external call
root1 = createAndUpdateSliderComponent('UI1-slider1', {...propsSlider1, min: 0, max: 20, value: 12}, root1); // Math.floor(Math.random() * 2) + 4 <-- Helpful to test funky react stuff
}
document.getElementById('slidervalues').addEventListener('click', setSliderValues, false);
document.getElementById('slidervalues').addEventListener('click', setSliderValues);

// add a slider component and link it to a map with mapId props
cgpv.api.utilities.core.addUiComponent(
'UI1-slider1',
cgpv.react.createElement(cgpv.ui.elements.Slider, {
mapId: 'UI1',
id: 'UI1-slider1',
min: 0,
max: 18,
value: 5,
marks: [
{ value: 0, label: 'Min Level 0' },
{ value: 4, label: 'Level 4' },
{ value: 8, label: 'Level 8' },
{ value: 18, label: 'Max Level 18' },
],
track: false,
// TODO: setting the view zoom level create bugs with the overview map
customOnChange: (zoomLevel) => {
const lat = 50;
const lng = -95;
cgpv.api.maps['UI1'].getView().animate({ zoom: zoomLevel });
},
})
);

// listen to slider value change event
const sliderPosition2 = document.getElementsByClassName('slider-position2');
cgpv.api.event.on(
cgpv.api.eventNames.SLIDER.EVENT_SLIDER_CHANGE,
(payload) => {
if (cgpv.types.payloadIsASlider(payload)) {
sliderPosition2[0].innerHTML = `<p>Slider min ${payload.sliderValues.min}, max ${payload.sliderValues.max}, values ${
payload.sliderValues.value
} and active thumb ${payload.sliderValues.activeThumb === 0 ? 'left' : 'right'}</p>`;
}
// Props for slider 2
const propsSlider2 = {
id: 'UI1-slider2',
min: 0,
max: 18,
value: [5, 10],
marks: [
{ value: 0, label: 'Min Level 0' },
{ value: 2 },
{ value: 4, label: 'Level 4' },
{ value: 5, label: 'Level 5' },
{ value: 6, label: 'Level 6' },
{ value: 8, label: 'Level 8' },
{ value: 18, label: 'Max Level 18' },
],
onChange: (sliderValues, activeThumb) => {
sliderPosition2[0].innerHTML = `<p>Slider values ${sliderValues} and active thumb ${activeThumb === 0 ? 'left' : 'right'}</p>`;
},
'UI1-slider2'
);
};

// Create and add the react element
const root2 = createAndAddSliderComponent('UI1-slider2', propsSlider2);

// add a slider component and DO NOT link it to a map
cgpv.api.utilities.core.addUiComponent(
'UI1-slider2',
cgpv.react.createElement(cgpv.ui.elements.Slider, {
id: 'UI1-slider2',
min: 0,
max: 18,
value: [5, 10],
marks: [
{ value: 0, label: 'Min Level 0' },
{ value: 2 },
{ value: 4, label: 'Level 4' },
{ value: 5, label: 'Level 5' },
{ value: 6, label: 'Level 6' },
{ value: 8, label: 'Level 8' },
{ value: 18, label: 'Max Level 18' },
],
})
);
/**
* SLIDER UI SECTION END
*/
Expand Down
5 changes: 0 additions & 5 deletions packages/geoview-core/src/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { EVENT_NAMES } from './events/event-types';
import { Event } from './events/event';

import { Projection } from '@/geo/projection/projection';
Expand All @@ -24,10 +23,6 @@ export class API {
// event object used to handle triggering events, subscribing to an event etc...
event: Event;

// TODO: refactor - once we have no more genereic event, we can remove eventNames
// available event names
eventNames = EVENT_NAMES;

// list of available maps
maps: Record<string, MapViewer> = {};

Expand Down

This file was deleted.

This file was deleted.

6 changes: 0 additions & 6 deletions packages/geoview-core/src/api/events/constants/index.ts

This file was deleted.

33 changes: 0 additions & 33 deletions packages/geoview-core/src/api/events/constants/map-constants.ts

This file was deleted.

22 changes: 0 additions & 22 deletions packages/geoview-core/src/api/events/constants/modal-constants.ts

This file was deleted.

This file was deleted.

27 changes: 0 additions & 27 deletions packages/geoview-core/src/api/events/constants/slider-constants.ts

This file was deleted.

Loading

0 comments on commit bbce924

Please sign in to comment.