feat(ui): introduce toggle button and use it for actions
[e-mobility-charging-stations-simulator.git] / ui / web / src / views / ChargingStationsView.vue
CommitLineData
32de5a57 1<template>
ca1e5439 2 <Container id="charging-stations-container">
47521384
JB
3 <Container
4 v-show="Array.isArray(uiServerConfigurations) && uiServerConfigurations.length > 1"
5 id="ui-server-container"
6 >
0344ad2b 7 <select
0344ad2b
JB
8 id="ui-server-selector"
9 v-model="state.uiServerIndex"
10 @change="
11 () => {
916fe456
JB
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)
2610da71
JB
23 for (const key in getLocalStorage()) {
24 if (key.includes('toggle-button')) {
25 removeFromLocalStorage(key)
26 }
27 }
a4edfbb3 28 $router.currentRoute.value.name !== 'charging-stations' &&
de3e2a49 29 $router.push({ name: 'charging-stations' })
916fe456
JB
30 },
31 { once: true }
32 )
33 app?.appContext.config.globalProperties.$uiClient.registerWSEventListener(
34 'error',
35 () => {
36 state.uiServerIndex = getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
37 app?.appContext.config.globalProperties.$uiClient.setConfiguration(
38 app?.appContext.config.globalProperties.$configuration.uiServer[
39 getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
40 ]
41 )
42 initializeWSEventListeners()
43 },
44 { once: true }
45 )
0344ad2b
JB
46 }
47 }
48 "
49 >
50 <option
51 v-for="uiServerConfiguration in uiServerConfigurations"
52 :value="uiServerConfiguration.index"
53 >
258666f9 54 {{ uiServerConfiguration.configuration.name ?? uiServerConfiguration.configuration.host }}
0344ad2b
JB
55 </option>
56 </select>
57 </Container>
13c19b7b 58 <Container id="buttons-container">
14ee627a
JB
59 <Button @click="startSimulator()">Start Simulator</Button>
60 <Button @click="stopSimulator()">Stop Simulator</Button>
2610da71
JB
61 <ToggleButton
62 :id="'add-charging-stations'"
63 :shared="true"
64 :on="
65 () => {
66 $router.push({ name: 'add-charging-stations' })
67 }
68 "
69 :off="
70 () => {
71 $router.push({ name: 'charging-stations' })
72 }
73 "
74 >
1eb5f592 75 Add Charging Stations
2610da71 76 </ToggleButton>
b9d447d2
JB
77 <ReloadButton
78 id="reload-button"
a4868fd7 79 :loading="state.loading"
86545028 80 @click="loadChargingStations(() => (state.renderChargingStationsList = randomUUID()))"
b9d447d2 81 />
13c19b7b 82 </Container>
5c0e9352 83 <CSTable
7378b34a 84 v-show="
5c0e9352
JB
85 Array.isArray(app?.appContext.config.globalProperties.$chargingStations) &&
86 app?.appContext.config.globalProperties.$chargingStations.length > 0
87 "
86545028 88 :key="state.renderChargingStationsList"
5c0e9352
JB
89 :charging-stations="app?.appContext.config.globalProperties.$chargingStations"
90 />
32de5a57
LM
91 </Container>
92</template>
93
94<script setup lang="ts">
3b0c6e17 95import { getCurrentInstance, onMounted, ref } from 'vue'
cea23fa0 96import { useToast } from 'vue-toast-notification'
66a7748d 97import CSTable from '@/components/charging-stations/CSTable.vue'
0344ad2b 98import type { ResponsePayload, UIServerConfigurationSection } from '@/types'
66a7748d
JB
99import Container from '@/components/Container.vue'
100import ReloadButton from '@/components/buttons/ReloadButton.vue'
13c19b7b 101import Button from '@/components/buttons/Button.vue'
2610da71
JB
102import {
103 getFromLocalStorage,
104 getLocalStorage,
105 randomUUID,
106 removeFromLocalStorage,
107 setToLocalStorage
108} from '@/composables'
109import ToggleButton from '@/components/buttons/ToggleButton.vue'
a4868fd7 110
916fe456
JB
111const app = getCurrentInstance()
112
113const initializeWSEventListeners = () => {
114 app?.appContext.config.globalProperties.$uiClient.registerWSEventListener('open', () => {
3b0c6e17
JB
115 uiClient
116 .listTemplates()
117 .then((response: ResponsePayload) => {
118 if (app != null) {
119 app.appContext.config.globalProperties.$templates = response.templates
120 }
121 })
122 .catch((error: Error) => {
123 if (app != null) {
124 app.appContext.config.globalProperties.$templates = []
125 }
126 $toast.error('Error at fetching charging station templates')
127 console.error('Error at fetching charging station templates:', error)
128 })
129 loadChargingStations(() => (state.value.renderChargingStationsList = randomUUID()))
916fe456
JB
130 })
131 app?.appContext.config.globalProperties.$uiClient.registerWSEventListener('error', () => {
132 app.appContext.config.globalProperties.$chargingStations = []
3b0c6e17 133 state.value.renderChargingStationsList = randomUUID()
916fe456
JB
134 })
135 app?.appContext.config.globalProperties.$uiClient.registerWSEventListener('close', () => {
136 app.appContext.config.globalProperties.$chargingStations = []
3b0c6e17 137 state.value.renderChargingStationsList = randomUUID()
916fe456
JB
138 })
139}
140
141onMounted(() => {
142 initializeWSEventListeners()
143})
144
3b0c6e17 145const state = ref({
86545028 146 renderChargingStationsList: randomUUID(),
a4868fd7 147 loading: false,
0344ad2b 148 uiServerIndex: getFromLocalStorage<number>('uiServerConfigurationIndex', 0)
66a7748d 149})
32de5a57 150
57c0ba05 151const uiClient = app?.appContext.config.globalProperties.$uiClient
0344ad2b
JB
152const uiServerConfigurations: { configuration: UIServerConfigurationSection; index: number }[] =
153 app?.appContext.config.globalProperties.$configuration.uiServer.map(
154 (configuration: UIServerConfigurationSection, index: number) => ({
155 configuration,
156 index
157 })
158 )
57c0ba05 159
cea23fa0
JB
160const $toast = useToast()
161
86545028 162const loadChargingStations = (renderCallback?: () => void): void => {
3b0c6e17
JB
163 if (state.value.loading === false) {
164 state.value.loading = true
57c0ba05
JB
165 uiClient
166 .listChargingStations()
167 .then((response: ResponsePayload) => {
168 if (app != null) {
169 app.appContext.config.globalProperties.$chargingStations = response.chargingStations
170 }
171 })
172 .catch((error: Error) => {
916fe456
JB
173 if (app != null) {
174 app.appContext.config.globalProperties.$chargingStations = []
175 }
cea23fa0 176 $toast.error('Error at fetching charging stations')
57c0ba05
JB
177 console.error('Error at fetching charging stations:', error)
178 })
179 .finally(() => {
86545028
JB
180 if (renderCallback != null) {
181 renderCallback()
b9d447d2 182 }
3b0c6e17 183 state.value.loading = false
57c0ba05 184 })
2113b3c6 185 }
32de5a57 186}
5a010bf0 187
fa5d129a 188const startSimulator = (): void => {
cea23fa0
JB
189 uiClient
190 .startSimulator()
191 .then(() => {
192 $toast.success('Simulator successfully started')
193 })
194 .catch((error: Error) => {
195 $toast.error('Error at starting simulator')
196 console.error('Error at starting simulator:', error)
197 })
5a010bf0 198}
fa5d129a 199const stopSimulator = (): void => {
cea23fa0
JB
200 uiClient
201 .stopSimulator()
202 .then(() => {
5c0e9352
JB
203 if (app != null) {
204 app.appContext.config.globalProperties.$chargingStations = []
205 }
cea23fa0
JB
206 $toast.success('Simulator successfully stopped')
207 })
208 .catch((error: Error) => {
209 $toast.error('Error at stopping simulator')
210 console.error('Error at stopping simulator:', error)
211 })
5a010bf0 212}
32de5a57
LM
213</script>
214
215<style>
ca1e5439 216#charging-stations-container {
1d41bc6b 217 height: fit-content;
32de5a57 218 width: 100%;
5a010bf0 219 display: flex;
32de5a57 220 flex-direction: column;
5a010bf0
JB
221}
222
0344ad2b
JB
223#ui-server-container {
224 display: flex;
225 flex-direction: row;
226}
227
228#ui-server-selector {
229 width: 100%;
230 text-align: center;
231}
232
13c19b7b
JB
233#buttons-container {
234 display: flex;
235 flex-direction: row;
236}
237
14ee627a
JB
238#action-button {
239 flex: none;
878855a2
JB
240}
241
32de5a57 242#reload-button {
5a010bf0 243 flex: auto;
32de5a57 244 color: white;
9dc8b66f 245 background-color: blue;
13c19b7b 246 font-size: 1.5rem;
32de5a57 247 font-weight: bold;
aee67dee
JB
248 align-items: center;
249 justify-content: center;
32de5a57
LM
250}
251
252#reload-button:hover {
9dc8b66f 253 background-color: rgb(0, 0, 225);
32de5a57
LM
254}
255
256#reload-button:active {
9dc8b66f 257 background-color: red;
32de5a57 258}
229d8c34
JB
259
260#action {
261 color: white;
262 background-color: black;
263 padding: 1%;
264}
32de5a57 265</style>