refactor(ui): resize buttons bar
[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 () =>
145 `${simulatorState.value?.started === true ? 'Stop' : 'Start'} Simulator${simulatorState.value?.version != null ? ` (${simulatorState.value.version})` : ''}`
146)
147
240fa4da
JB
148const state = ref<{
149 renderSimulator: `${string}-${string}-${string}-${string}-${string}`
150 renderAddChargingStations: `${string}-${string}-${string}-${string}-${string}`
151 renderChargingStations: `${string}-${string}-${string}-${string}-${string}`
26cf7d99
JB
152 gettingSimulatorState: boolean
153 gettingTemplates: boolean
154 gettingChargingStations: boolean
240fa4da
JB
155 uiServerIndex: number
156}>({
157 renderSimulator: randomUUID(),
158 renderAddChargingStations: randomUUID(),
159 renderChargingStations: randomUUID(),
26cf7d99
JB
160 gettingSimulatorState: false,
161 gettingTemplates: false,
162 gettingChargingStations: false,
240fa4da
JB
163 uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
164})
165
d64ea57b
JB
166const clearToggleButtons = (): void => {
167 for (const key in getLocalStorage()) {
168 if (key.includes('toggle-button')) {
b767fda7 169 deleteFromLocalStorage(key)
d64ea57b
JB
170 }
171 }
26cf7d99
JB
172 state.value.renderChargingStations = randomUUID()
173 state.value.renderAddChargingStations = randomUUID()
d64ea57b
JB
174}
175
97cd0ef3
JB
176const app = getCurrentInstance()
177
f4b3f35d 178watch(app!.appContext.config.globalProperties.$chargingStations, () => {
f6cb1767
JB
179 state.value.renderChargingStations = randomUUID()
180})
181
182watch(simulatorState, () => {
183 state.value.renderSimulator = randomUUID()
184})
185
186const clearTemplates = (): void => {
187 if (app != null) {
188 app.appContext.config.globalProperties.$templates.value = []
189 }
190}
191
d64ea57b 192const clearChargingStations = (): void => {
26cf7d99 193 if (app != null) {
7e315430 194 app.appContext.config.globalProperties.$chargingStations.value = []
26cf7d99 195 }
d64ea57b
JB
196}
197
39cd8fcb 198const uiClient = useUIClient()
240fa4da 199
97cd0ef3
JB
200const $toast = useToast()
201
240fa4da 202const getSimulatorState = (): void => {
26cf7d99
JB
203 if (state.value.gettingSimulatorState === false) {
204 state.value.gettingSimulatorState = true
3b0c6e17 205 uiClient
26cf7d99 206 .simulatorState()
3b0c6e17 207 .then((response: ResponsePayload) => {
f6cb1767 208 simulatorState.value = response.state as SimulatorState
3b0c6e17
JB
209 })
210 .catch((error: Error) => {
26cf7d99
JB
211 $toast.error('Error at fetching simulator state')
212 console.error('Error at fetching simulator state:', error)
3b0c6e17 213 })
240fa4da 214 .finally(() => {
26cf7d99 215 state.value.gettingSimulatorState = false
240fa4da 216 })
26cf7d99
JB
217 }
218}
219
97cd0ef3
JB
220const getTemplates = (): void => {
221 if (state.value.gettingTemplates === false) {
222 state.value.gettingTemplates = true
223 uiClient
224 .listTemplates()
225 .then((response: ResponsePayload) => {
226 if (app != null) {
f4b3f35d 227 app.appContext.config.globalProperties.$templates.value = response.templates as string[]
97cd0ef3
JB
228 }
229 })
230 .catch((error: Error) => {
f6cb1767 231 clearTemplates()
97cd0ef3
JB
232 $toast.error('Error at fetching charging station templates')
233 console.error('Error at fetching charging station templates:', error)
234 })
235 .finally(() => {
236 state.value.gettingTemplates = false
237 })
238 }
916fe456
JB
239}
240
26cf7d99
JB
241const getChargingStations = (): void => {
242 if (state.value.gettingChargingStations === false) {
243 state.value.gettingChargingStations = true
57c0ba05
JB
244 uiClient
245 .listChargingStations()
246 .then((response: ResponsePayload) => {
247 if (app != null) {
f4b3f35d
JB
248 app.appContext.config.globalProperties.$chargingStations.value =
249 response.chargingStations as ChargingStationData[]
57c0ba05
JB
250 }
251 })
252 .catch((error: Error) => {
f6cb1767 253 clearChargingStations()
cea23fa0 254 $toast.error('Error at fetching charging stations')
57c0ba05
JB
255 console.error('Error at fetching charging stations:', error)
256 })
257 .finally(() => {
26cf7d99 258 state.value.gettingChargingStations = false
57c0ba05 259 })
2113b3c6 260 }
32de5a57 261}
5a010bf0 262
aa9b0a1e
JB
263const getData = (): void => {
264 getSimulatorState()
265 getTemplates()
266 getChargingStations()
267}
268
269const registerWSEventListeners = () => {
270 uiClient.registerWSEventListener('open', getData)
97cd0ef3
JB
271 uiClient.registerWSEventListener('error', clearChargingStations)
272 uiClient.registerWSEventListener('close', clearChargingStations)
273}
274
aa9b0a1e
JB
275const unregisterWSEventListeners = () => {
276 uiClient.unregisterWSEventListener('open', getData)
277 uiClient.unregisterWSEventListener('error', clearChargingStations)
278 uiClient.unregisterWSEventListener('close', clearChargingStations)
279}
280
97cd0ef3 281onMounted(() => {
aa9b0a1e
JB
282 registerWSEventListeners()
283})
284
285onUnmounted(() => {
286 unregisterWSEventListeners()
97cd0ef3
JB
287})
288
f4b3f35d
JB
289const uiServerConfigurations: { index: number; configuration: UIServerConfigurationSection }[] = (
290 app?.appContext.config.globalProperties.$configuration.value
291 .uiServer as UIServerConfigurationSection[]
292).map((configuration: UIServerConfigurationSection, index: number) => ({
293 index,
294 configuration
295}))
97cd0ef3 296
fa5d129a 297const startSimulator = (): void => {
cea23fa0
JB
298 uiClient
299 .startSimulator()
300 .then(() => {
301 $toast.success('Simulator successfully started')
302 })
303 .catch((error: Error) => {
304 $toast.error('Error at starting simulator')
305 console.error('Error at starting simulator:', error)
306 })
240fa4da
JB
307 .finally(() => {
308 getSimulatorState()
309 })
5a010bf0 310}
fa5d129a 311const stopSimulator = (): void => {
cea23fa0
JB
312 uiClient
313 .stopSimulator()
314 .then(() => {
f6cb1767 315 clearChargingStations()
cea23fa0
JB
316 $toast.success('Simulator successfully stopped')
317 })
318 .catch((error: Error) => {
319 $toast.error('Error at stopping simulator')
320 console.error('Error at stopping simulator:', error)
321 })
240fa4da
JB
322 .finally(() => {
323 getSimulatorState()
324 })
5a010bf0 325}
32de5a57
LM
326</script>
327
328<style>
ca1e5439 329#charging-stations-container {
1d41bc6b 330 height: fit-content;
32de5a57 331 width: 100%;
5a010bf0 332 display: flex;
32de5a57 333 flex-direction: column;
5a010bf0
JB
334}
335
0344ad2b
JB
336#ui-server-container {
337 display: flex;
239bd875 338 justify-content: center;
754d8199 339 border-style: outset;
0344ad2b
JB
340}
341
342#ui-server-selector {
343 width: 100%;
239bd875 344 background-color: rgb(239, 239, 239);
c6308554 345 font: small-caption;
0344ad2b
JB
346 text-align: center;
347}
348
239bd875 349#ui-server-selector:hover {
bad93db3 350 background-color: rgb(229, 229, 229);
239bd875
JB
351}
352
13c19b7b
JB
353#buttons-container {
354 display: flex;
355 flex-direction: row;
558db46f
JB
356 position: sticky;
357 top: 0;
13c19b7b
JB
358}
359
6027002f 360.simulator-start-button {
3802683b
JB
361 color: ivory;
362 background-color: green;
363}
364
fec03138 365.simulator-start-button:hover {
fec03138
JB
366 background-color: rgb(0, 98, 0);
367}
368
6027002f 369.simulator-stop-button {
3802683b
JB
370 color: ivory;
371 background-color: red;
372}
373
fec03138
JB
374.simulator-stop-button:hover {
375 background-color: rgb(225, 0, 0);
376}
377
14ee627a
JB
378#action-button {
379 flex: none;
878855a2
JB
380}
381
32de5a57 382#reload-button {
3802683b 383 color: ivory;
9dc8b66f 384 background-color: blue;
350f7bd5 385 font-size: 1.5rem;
32de5a57
LM
386}
387
388#reload-button:hover {
9dc8b66f 389 background-color: rgb(0, 0, 225);
32de5a57
LM
390}
391
392#reload-button:active {
4b10e4f9 393 background-color: darkblue;
32de5a57 394}
229d8c34
JB
395
396#action {
916f0920 397 min-width: max-content;
3802683b 398 color: ivory;
229d8c34 399 background-color: black;
916f0920 400 padding: 0.8%;
229d8c34 401}
32de5a57 402</style>