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