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