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