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