refactor(ui): cleanup initial data fetching code
[e-mobility-charging-stations-simulator.git] / ui / web / src / views / ChargingStationsView.vue
CommitLineData
32de5a57 1<template>
ca1e5439 2 <Container id="charging-stations-container">
239bd875
JB
3 <Container id="buttons-container">
4 <Container
5 v-show="Array.isArray(uiServerConfigurations) && uiServerConfigurations.length > 1"
6 id="ui-server-container"
0344ad2b 7 >
239bd875
JB
8 <select
9 id="ui-server-selector"
10 v-model="state.uiServerIndex"
11 @change="
12 () => {
13 if (
14 getFromLocalStorage<number>('uiServerConfigurationIndex', 0) !== state.uiServerIndex
15 ) {
97cd0ef3 16 uiClient.setConfiguration(
239bd875
JB
17 app?.appContext.config.globalProperties.$configuration.uiServer[
18 state.uiServerIndex
19 ]
20 )
21 initializeWSEventListeners()
97cd0ef3 22 uiClient.registerWSEventListener(
239bd875
JB
23 'open',
24 () => {
25 setToLocalStorage<number>('uiServerConfigurationIndex', state.uiServerIndex)
26 clearToggleButtons()
27 $router.currentRoute.value.name !== 'charging-stations' &&
28 $router.push({ name: 'charging-stations' })
29 },
30 { once: true }
31 )
97cd0ef3 32 uiClient.registerWSEventListener(
239bd875
JB
33 'error',
34 () => {
35 state.uiServerIndex = getFromLocalStorage<number>(
36 'uiServerConfigurationIndex',
37 0
38 )
97cd0ef3 39 uiClient.setConfiguration(
239bd875
JB
40 app?.appContext.config.globalProperties.$configuration.uiServer[
41 getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
42 ]
43 )
44 initializeWSEventListeners()
45 },
46 { once: true }
47 )
48 }
49 }
50 "
0344ad2b 51 >
239bd875
JB
52 <option
53 v-for="uiServerConfiguration in uiServerConfigurations"
54 :value="uiServerConfiguration.index"
55 >
56 {{
57 uiServerConfiguration.configuration.name ?? uiServerConfiguration.configuration.host
58 }}
59 </option>
60 </select>
61 </Container>
240fa4da
JB
62 <ToggleButton
63 :id="'simulator'"
64 :key="state.renderSimulator"
65 :status="state.simulatorState?.started"
66 :on="() => startSimulator()"
67 :off="() => stopSimulator()"
ec7366ed 68 :class="simulatorButtonClass"
240fa4da 69 >
ec7366ed 70 {{ simulatorButtonMessage }}
240fa4da 71 </ToggleButton>
2610da71
JB
72 <ToggleButton
73 :id="'add-charging-stations'"
d64ea57b 74 :key="state.renderAddChargingStations"
2610da71
JB
75 :shared="true"
76 :on="
77 () => {
78 $router.push({ name: 'add-charging-stations' })
79 }
80 "
81 :off="
82 () => {
83 $router.push({ name: 'charging-stations' })
84 }
85 "
83468764
JB
86 @clicked="
87 () => {
88 state.renderChargingStations = randomUUID()
89 }
90 "
2610da71 91 >
1eb5f592 92 Add Charging Stations
2610da71 93 </ToggleButton>
b9d447d2
JB
94 <ReloadButton
95 id="reload-button"
26cf7d99
JB
96 :loading="state.gettingChargingStations"
97 @click="getChargingStations()"
b9d447d2 98 />
13c19b7b 99 </Container>
5c0e9352 100 <CSTable
7378b34a 101 v-show="
5c0e9352 102 Array.isArray(app?.appContext.config.globalProperties.$chargingStations) &&
3eea3ebc 103 app.appContext.config.globalProperties.$chargingStations.length > 0
5c0e9352 104 "
3eea3ebc 105 :key="state.renderChargingStations"
5c0e9352 106 :charging-stations="app?.appContext.config.globalProperties.$chargingStations"
83468764
JB
107 @need-refresh="
108 () => {
109 state.renderAddChargingStations = randomUUID()
110 state.renderChargingStations = randomUUID()
111 }
112 "
5c0e9352 113 />
32de5a57
LM
114 </Container>
115</template>
116
117<script setup lang="ts">
ec7366ed 118import { computed, getCurrentInstance, onMounted, ref } from 'vue'
cea23fa0 119import { useToast } from 'vue-toast-notification'
66a7748d 120import CSTable from '@/components/charging-stations/CSTable.vue'
e8237645 121import type { ResponsePayload, SimulatorState, UIServerConfigurationSection } from '@/types'
66a7748d
JB
122import Container from '@/components/Container.vue'
123import ReloadButton from '@/components/buttons/ReloadButton.vue'
2610da71 124import {
b767fda7 125 deleteFromLocalStorage,
2610da71
JB
126 getFromLocalStorage,
127 getLocalStorage,
128 randomUUID,
2610da71
JB
129 setToLocalStorage
130} from '@/composables'
131import ToggleButton from '@/components/buttons/ToggleButton.vue'
a4868fd7 132
240fa4da
JB
133const state = ref<{
134 renderSimulator: `${string}-${string}-${string}-${string}-${string}`
135 renderAddChargingStations: `${string}-${string}-${string}-${string}-${string}`
136 renderChargingStations: `${string}-${string}-${string}-${string}-${string}`
26cf7d99
JB
137 gettingSimulatorState: boolean
138 gettingTemplates: boolean
139 gettingChargingStations: boolean
e8237645 140 simulatorState?: SimulatorState
240fa4da
JB
141 uiServerIndex: number
142}>({
143 renderSimulator: randomUUID(),
144 renderAddChargingStations: randomUUID(),
145 renderChargingStations: randomUUID(),
26cf7d99
JB
146 gettingSimulatorState: false,
147 gettingTemplates: false,
148 gettingChargingStations: false,
240fa4da
JB
149 uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
150})
151
ec7366ed
JB
152const simulatorButtonClass = computed<string>(() =>
153 state.value.simulatorState?.started === true ? 'simulator-stop-button' : 'simulator-start-button'
154)
155const simulatorButtonMessage = computed<string>(
156 () =>
1fa3425a 157 `${state.value.simulatorState?.started === true ? 'Stop' : 'Start'} Simulator${state.value.simulatorState?.version != null ? ` (${state.value.simulatorState.version})` : ''}`
ec7366ed
JB
158)
159
d64ea57b
JB
160const clearToggleButtons = (): void => {
161 for (const key in getLocalStorage()) {
162 if (key.includes('toggle-button')) {
b767fda7 163 deleteFromLocalStorage(key)
d64ea57b
JB
164 }
165 }
26cf7d99
JB
166 state.value.renderChargingStations = randomUUID()
167 state.value.renderAddChargingStations = randomUUID()
d64ea57b
JB
168}
169
97cd0ef3
JB
170const app = getCurrentInstance()
171
d64ea57b 172const clearChargingStations = (): void => {
26cf7d99
JB
173 if (app != null) {
174 app.appContext.config.globalProperties.$chargingStations = []
175 }
3eea3ebc 176 state.value.renderChargingStations = randomUUID()
d64ea57b
JB
177}
178
240fa4da
JB
179const uiClient = app?.appContext.config.globalProperties.$uiClient
180
97cd0ef3
JB
181const $toast = useToast()
182
240fa4da 183const getSimulatorState = (): void => {
26cf7d99
JB
184 if (state.value.gettingSimulatorState === false) {
185 state.value.gettingSimulatorState = true
3b0c6e17 186 uiClient
26cf7d99 187 .simulatorState()
3b0c6e17 188 .then((response: ResponsePayload) => {
26cf7d99 189 state.value.simulatorState = response.state as SimulatorState
3b0c6e17
JB
190 })
191 .catch((error: Error) => {
26cf7d99
JB
192 $toast.error('Error at fetching simulator state')
193 console.error('Error at fetching simulator state:', error)
3b0c6e17 194 })
240fa4da 195 .finally(() => {
26cf7d99
JB
196 state.value.renderSimulator = randomUUID()
197 state.value.gettingSimulatorState = false
240fa4da 198 })
26cf7d99
JB
199 }
200}
201
97cd0ef3
JB
202const getTemplates = (): void => {
203 if (state.value.gettingTemplates === false) {
204 state.value.gettingTemplates = true
205 uiClient
206 .listTemplates()
207 .then((response: ResponsePayload) => {
208 if (app != null) {
209 app.appContext.config.globalProperties.$templates = response.templates
210 }
211 })
212 .catch((error: Error) => {
213 if (app != null) {
214 app.appContext.config.globalProperties.$templates = []
215 }
216 $toast.error('Error at fetching charging station templates')
217 console.error('Error at fetching charging station templates:', error)
218 })
219 .finally(() => {
220 state.value.gettingTemplates = false
221 })
222 }
916fe456
JB
223}
224
26cf7d99
JB
225const getChargingStations = (): void => {
226 if (state.value.gettingChargingStations === false) {
227 state.value.gettingChargingStations = true
57c0ba05
JB
228 uiClient
229 .listChargingStations()
230 .then((response: ResponsePayload) => {
231 if (app != null) {
232 app.appContext.config.globalProperties.$chargingStations = response.chargingStations
233 }
234 })
235 .catch((error: Error) => {
916fe456
JB
236 if (app != null) {
237 app.appContext.config.globalProperties.$chargingStations = []
238 }
cea23fa0 239 $toast.error('Error at fetching charging stations')
57c0ba05
JB
240 console.error('Error at fetching charging stations:', error)
241 })
242 .finally(() => {
26cf7d99
JB
243 state.value.renderChargingStations = randomUUID()
244 state.value.gettingChargingStations = false
57c0ba05 245 })
2113b3c6 246 }
32de5a57 247}
5a010bf0 248
97cd0ef3
JB
249const initializeWSEventListeners = () => {
250 uiClient.registerWSEventListener('open', () => {
251 getSimulatorState()
252 getTemplates()
253 getChargingStations()
254 })
255 uiClient.registerWSEventListener('error', clearChargingStations)
256 uiClient.registerWSEventListener('close', clearChargingStations)
257}
258
259onMounted(() => {
260 initializeWSEventListeners()
261})
262
263const uiServerConfigurations: { index: number; configuration: UIServerConfigurationSection }[] =
264 app?.appContext.config.globalProperties.$configuration.uiServer.map(
265 (configuration: UIServerConfigurationSection, index: number) => ({
266 index,
267 configuration
268 })
269 )
270
fa5d129a 271const startSimulator = (): void => {
cea23fa0
JB
272 uiClient
273 .startSimulator()
274 .then(() => {
275 $toast.success('Simulator successfully started')
276 })
277 .catch((error: Error) => {
278 $toast.error('Error at starting simulator')
279 console.error('Error at starting simulator:', error)
280 })
240fa4da
JB
281 .finally(() => {
282 getSimulatorState()
283 })
5a010bf0 284}
fa5d129a 285const stopSimulator = (): void => {
cea23fa0
JB
286 uiClient
287 .stopSimulator()
288 .then(() => {
5c0e9352
JB
289 if (app != null) {
290 app.appContext.config.globalProperties.$chargingStations = []
291 }
cea23fa0
JB
292 $toast.success('Simulator successfully stopped')
293 })
294 .catch((error: Error) => {
295 $toast.error('Error at stopping simulator')
296 console.error('Error at stopping simulator:', error)
297 })
240fa4da
JB
298 .finally(() => {
299 getSimulatorState()
300 })
5a010bf0 301}
32de5a57
LM
302</script>
303
304<style>
ca1e5439 305#charging-stations-container {
1d41bc6b 306 height: fit-content;
32de5a57 307 width: 100%;
5a010bf0 308 display: flex;
32de5a57 309 flex-direction: column;
5a010bf0
JB
310}
311
0344ad2b
JB
312#ui-server-container {
313 display: flex;
239bd875 314 justify-content: center;
754d8199 315 border-style: outset;
0344ad2b
JB
316}
317
318#ui-server-selector {
319 width: 100%;
239bd875 320 background-color: rgb(239, 239, 239);
c6308554 321 font: small-caption;
0344ad2b
JB
322 text-align: center;
323}
324
239bd875 325#ui-server-selector:hover {
bad93db3 326 background-color: rgb(229, 229, 229);
239bd875
JB
327}
328
13c19b7b
JB
329#buttons-container {
330 display: flex;
331 flex-direction: row;
332}
333
6027002f 334.simulator-start-button {
3802683b
JB
335 color: ivory;
336 background-color: green;
337}
338
fec03138 339.simulator-start-button:hover {
fec03138
JB
340 background-color: rgb(0, 98, 0);
341}
342
6027002f 343.simulator-stop-button {
3802683b
JB
344 color: ivory;
345 background-color: red;
346}
347
fec03138
JB
348.simulator-stop-button:hover {
349 background-color: rgb(225, 0, 0);
350}
351
14ee627a
JB
352#action-button {
353 flex: none;
878855a2
JB
354}
355
32de5a57 356#reload-button {
3802683b 357 color: ivory;
9dc8b66f 358 background-color: blue;
c6308554 359 font-size: 2rem;
32de5a57
LM
360}
361
362#reload-button:hover {
9dc8b66f 363 background-color: rgb(0, 0, 225);
32de5a57
LM
364}
365
366#reload-button:active {
4b10e4f9 367 background-color: darkblue;
32de5a57 368}
229d8c34
JB
369
370#action {
916f0920 371 min-width: max-content;
3802683b 372 color: ivory;
229d8c34 373 background-color: black;
916f0920 374 padding: 0.8%;
229d8c34 375}
32de5a57 376</style>