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