mirror of
https://git.rwth-aachen.de/acs/public/villas/web/
synced 2025-03-09 00:00:01 +01:00
updated redux storage and added RTK Query
Signed-off-by: Andrii Podriez <andrey5577990@gmail.com>
This commit is contained in:
parent
3ca56016a4
commit
8faab6613e
4 changed files with 474 additions and 34 deletions
306
src/store/apiSlice.js
Normal file
306
src/store/apiSlice.js
Normal file
|
@ -0,0 +1,306 @@
|
|||
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
|
||||
import { sessionToken } from '../localStorage';
|
||||
|
||||
export const apiSlice = createApi({
|
||||
reducerPath: 'scenarios',
|
||||
baseQuery: fetchBaseQuery({
|
||||
baseUrl: '/api/v2',
|
||||
prepareHeaders: (headers) => {
|
||||
const token = sessionToken;
|
||||
if (token) {
|
||||
headers.set('Authorization', `Bearer ${token}`);
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
}),
|
||||
endpoints: (builder) => ({
|
||||
getScenarios: builder.query({
|
||||
query: () => 'scenarios',
|
||||
}),
|
||||
getScenarioById: builder.query({
|
||||
query: (id) => `scenarios/${id}`,
|
||||
}),
|
||||
addScenario: builder.mutation({
|
||||
query: (scenario) => ({
|
||||
url: 'scenarios',
|
||||
method: 'POST',
|
||||
body: scenario,
|
||||
}),
|
||||
}),
|
||||
deleteScenario: builder.mutation({
|
||||
query: (id) => ({
|
||||
url: `scenarios/${id}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
updateScenario: builder.mutation({
|
||||
query: ({ id, ...updatedScenario }) => ({
|
||||
url: `scenarios/${id}`,
|
||||
method: 'PUT',
|
||||
body: updatedScenario,
|
||||
}),
|
||||
}),
|
||||
getConfigs: builder.query({
|
||||
query: (scenarioID) => `configs?scenarioID=${scenarioID}`,
|
||||
}),
|
||||
getUsersOfScenario: builder.query({
|
||||
query: (scenarioID) => `scenarios/${scenarioID}/users/`,
|
||||
}),
|
||||
getDashboards: builder.query({
|
||||
query: (scenarioID) => `dashboards?scenarioID=${scenarioID}`,
|
||||
}),
|
||||
getICS: builder.query({
|
||||
query: () => 'ic',
|
||||
}),
|
||||
addUserToScenario: builder.mutation({
|
||||
query: ({ scenarioID, username }) => {
|
||||
return ({
|
||||
url: `scenarios/${scenarioID}/user?username=${username}`,
|
||||
method: 'PUT',
|
||||
})},
|
||||
}),
|
||||
removeUserFromScenario: builder.mutation({
|
||||
query: ({ scenarioID, username }) => ({
|
||||
url: `scenarios/${scenarioID}/user/?username=${username}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
addComponentConfig: builder.mutation({
|
||||
query: (config) => ({
|
||||
url: 'configs',
|
||||
method: 'POST',
|
||||
body: config,
|
||||
}),
|
||||
}),
|
||||
deleteComponentConfig: builder.mutation({
|
||||
query: (configID) => ({
|
||||
url: `configs/${configID}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
addDashboard: builder.mutation({
|
||||
query: (dashboard) => ({
|
||||
url: 'dashboards',
|
||||
method: 'POST',
|
||||
body: dashboard,
|
||||
}),
|
||||
}),
|
||||
deleteDashboard: builder.mutation({
|
||||
query: (dashboardID) => ({
|
||||
url: `dashboards/${dashboardID}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
updateDashboard: builder.mutation({
|
||||
query: ({ dashboardID, dashboard }) => ({
|
||||
url: `dashboards/${dashboardID}`,
|
||||
method: 'PUT',
|
||||
body: {dashboard},
|
||||
}),
|
||||
}),
|
||||
getSignals: builder.query({
|
||||
query: ({ direction, configID }) => ({
|
||||
url: 'signals',
|
||||
params: { direction, configID },
|
||||
}),
|
||||
}),
|
||||
addSignal: builder.mutation({
|
||||
query: (signal) => ({
|
||||
url: 'signals',
|
||||
method: 'POST',
|
||||
body: { signal },
|
||||
}),
|
||||
}),
|
||||
deleteSignal: builder.mutation({
|
||||
query: (signalID) => ({
|
||||
url: `signals/${signalID}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
//users
|
||||
getUsers: builder.query({
|
||||
query: () => 'users',
|
||||
}),
|
||||
getUserById: builder.query({
|
||||
query: (id) => `users/${id}`,
|
||||
}),
|
||||
addUser: builder.mutation({
|
||||
query: (user) => ({
|
||||
url: 'users',
|
||||
method: 'POST',
|
||||
body: user,
|
||||
}),
|
||||
}),
|
||||
updateUser: builder.mutation({
|
||||
query: (user) => {
|
||||
return {
|
||||
url: `users/${user.id}`,
|
||||
method: 'PUT',
|
||||
body: {user: user},
|
||||
}},
|
||||
}),
|
||||
deleteUser: builder.mutation({
|
||||
query: (id) => ({
|
||||
url: `users/${id}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
//results
|
||||
getResults: builder.query({
|
||||
query: (scenarioID) => ({
|
||||
url: 'results',
|
||||
params: { scenarioID },
|
||||
}),
|
||||
}),
|
||||
addResult: builder.mutation({
|
||||
query: (result) => ({
|
||||
url: 'results',
|
||||
method: 'POST',
|
||||
body: result,
|
||||
}),
|
||||
}),
|
||||
deleteResult: builder.mutation({
|
||||
query: (resultID) => ({
|
||||
url: `results/${resultID}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
//files
|
||||
getFiles: builder.query({
|
||||
query: (scenarioID) => ({
|
||||
url: 'files',
|
||||
params: { scenarioID },
|
||||
}),
|
||||
}),
|
||||
addFile: builder.mutation({
|
||||
query: ({ scenarioID, file }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('inputFile', file);
|
||||
return {
|
||||
url: `files?scenarioID=${scenarioID}`,
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
}),
|
||||
downloadFile: builder.query({
|
||||
query: (fileID) => ({
|
||||
url: `files/${fileID}`,
|
||||
responseHandler: 'blob',
|
||||
responseType: 'blob',
|
||||
}),
|
||||
}),
|
||||
updateFile: builder.mutation({
|
||||
query: ({ fileID, file }) => {
|
||||
const formData = new FormData();
|
||||
formData.append('inputFile', file);
|
||||
return {
|
||||
url: `files/${fileID}`,
|
||||
method: 'PUT',
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
}),
|
||||
deleteFile: builder.mutation({
|
||||
query: (fileID) => ({
|
||||
url: `files/${fileID}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
sendAction: builder.mutation({
|
||||
query: (params) => ({
|
||||
url: `/ic/${params.icid}/action`,
|
||||
method: 'POST',
|
||||
body: [params],
|
||||
}),
|
||||
}),
|
||||
|
||||
getDashboard: builder.query({
|
||||
query: (dashboardID) => `/dashboards/${dashboardID}`,
|
||||
}),
|
||||
|
||||
getWidgets: builder.query({
|
||||
query: (dashboardID) => ({
|
||||
url: 'widgets',
|
||||
params: { dashboardID },
|
||||
}),
|
||||
}),
|
||||
addWidget: builder.mutation({
|
||||
query: (widget) => ({
|
||||
url: 'widgets',
|
||||
method: 'POST',
|
||||
body: { widget },
|
||||
}),
|
||||
}),
|
||||
getWidget: builder.query({
|
||||
query: (widgetID) => `/widgets/${widgetID}`,
|
||||
}),
|
||||
updateWidget: builder.mutation({
|
||||
query: ({ widgetID, updatedWidget }) => ({
|
||||
url: `/widgets/${widgetID}`,
|
||||
method: 'PUT',
|
||||
body: updatedWidget,
|
||||
}),
|
||||
}),
|
||||
deleteWidget: builder.mutation({
|
||||
query: (widgetID) => ({
|
||||
url: `/widgets/${widgetID}`,
|
||||
method: 'DELETE',
|
||||
}),
|
||||
}),
|
||||
|
||||
getConfig: builder.query({
|
||||
query: () => '/config',
|
||||
})
|
||||
}),
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetScenariosQuery,
|
||||
useGetScenarioByIdQuery,
|
||||
useGetConfigsQuery,
|
||||
useLazyGetConfigsQuery,
|
||||
useGetDashboardsQuery,
|
||||
useGetICSQuery,
|
||||
useAddScenarioMutation,
|
||||
useDeleteScenarioMutation,
|
||||
useUpdateScenarioMutation,
|
||||
useGetUsersOfScenarioQuery,
|
||||
useAddUserToScenarioMutation,
|
||||
useRemoveUserFromScenarioMutation,
|
||||
useAddComponentConfigMutation,
|
||||
useDeleteComponentConfigMutation,
|
||||
useAddDashboardMutation,
|
||||
useDeleteDashboardMutation,
|
||||
useLazyGetSignalsQuery,
|
||||
useGetSignalsQuery,
|
||||
useAddSignalMutation,
|
||||
useDeleteSignalMutation,
|
||||
|
||||
useGetResultsQuery,
|
||||
useAddResultMutation,
|
||||
useDeleteResultMutation,
|
||||
|
||||
useGetUsersQuery,
|
||||
useGetUserByIdQuery,
|
||||
useAddUserMutation,
|
||||
useUpdateUserMutation,
|
||||
useDeleteUserMutation,
|
||||
|
||||
useGetFilesQuery,
|
||||
useAddFileMutation,
|
||||
useLazyDownloadFileQuery,
|
||||
useUpdateFileMutation,
|
||||
useDeleteFileMutation,
|
||||
|
||||
useGetDashboardQuery,
|
||||
useUpdateDashboardMutation,
|
||||
|
||||
useSendActionMutation,
|
||||
|
||||
useAddWidgetMutation,
|
||||
useLazyGetWidgetsQuery,
|
||||
useUpdateWidgetMutation,
|
||||
useDeleteWidgetMutation,
|
||||
useGetConfigQuery,
|
||||
} = apiSlice;
|
|
@ -17,25 +17,67 @@
|
|||
|
||||
import {createSlice, createAsyncThunk} from '@reduxjs/toolkit'
|
||||
import RestAPI from '../common/api/rest-api';
|
||||
|
||||
import { sessionToken } from '../localStorage';
|
||||
import NotificationsDataManager from '../common/data-managers/notifications-data-manager';
|
||||
import NotificationsFactory from '../common/data-managers/notifications-factory';
|
||||
|
||||
|
||||
const icSlice = createSlice({
|
||||
name: 'infrastructure',
|
||||
initialState: {
|
||||
ICsArray: [],
|
||||
checkedICsArray: [],
|
||||
|
||||
checkedICsIds: [],
|
||||
isLoading: false,
|
||||
currentIC: {},
|
||||
isCurrentICLoading: false
|
||||
isCurrentICLoading: false,
|
||||
//IC used for Edit and Delete Modals
|
||||
editModalIC: null,
|
||||
deleteModalIC: null,
|
||||
isDeleteModalOpened: false,
|
||||
isEditModalOpened: false
|
||||
},
|
||||
reducers: {
|
||||
checkICsByCategory: (state, args) => {
|
||||
const category = args.payload;
|
||||
updateCheckedICs: (state, args) => {
|
||||
// each table has an object that maps IDs of all its ICs to boolean values
|
||||
// which indicates wether or note user picked it in checbox column
|
||||
const checkboxValues = args.payload;
|
||||
let checkedICsIds = [...state.checkedICsIds];
|
||||
|
||||
for(const ic in state.ICsArray){
|
||||
if (ic.category == category) state.checkedICsArray.push(ic)
|
||||
for(const id in checkboxValues){
|
||||
if(checkedICsIds.includes(id)){
|
||||
if(!checkboxValues[id]){
|
||||
checkedICsIds = checkedICsIds.filter((checkedId) => checkedId != id);
|
||||
}
|
||||
} else {
|
||||
if(checkboxValues[id]){
|
||||
checkedICsIds.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.checkedICsIds = checkedICsIds;
|
||||
},
|
||||
clearCheckedICs: (state, args) => {
|
||||
state.checkedICsIds = [];
|
||||
},
|
||||
openEditModal: (state, args) => {
|
||||
state.isEditModalOpened = true;
|
||||
state.editModalIC = args.payload;
|
||||
console.log(state.editModalIC)
|
||||
},
|
||||
closeEditModal: (state, args) => {
|
||||
state.isEditModalOpened = false;
|
||||
state.editModalIC = null;
|
||||
},
|
||||
openDeleteModal: (state, args) => {
|
||||
state.deleteModalIC = args.payload;
|
||||
state.isDeleteModalOpened = true;
|
||||
},
|
||||
closeDeleteModal: (state, args) => {
|
||||
state.deleteModalIC = null;
|
||||
state.isDeleteModalOpened = false;
|
||||
|
||||
}
|
||||
},
|
||||
extraReducers: builder => {
|
||||
|
@ -50,20 +92,33 @@ const icSlice = createSlice({
|
|||
.addCase(loadICbyId.pending, (state, action) => {
|
||||
state.isCurrentICLoading = true
|
||||
})
|
||||
.addCase(loadICbyId.fulfilled, (state, action) => {
|
||||
state.isCurrentICLoading = false
|
||||
state.currentIC = action.payload;
|
||||
console.log("fetched IC", state.currentIC.name)
|
||||
})
|
||||
//TODO
|
||||
// .addCase(restartIC.fullfilled, (state, action) => {
|
||||
// console.log("restart fullfilled")
|
||||
// //loadAllICs({token: sessionToken})
|
||||
// })
|
||||
// .addCase(shutdownIC.fullfilled, (state, action) => {
|
||||
// console.log("shutdown fullfilled")
|
||||
// //loadAllICs({token: sessionToken})
|
||||
// })
|
||||
|
||||
.addCase(loadICbyId.fulfilled, (state, action) => {
|
||||
state.isCurrentICLoading = false
|
||||
state.currentIC = action.payload;
|
||||
console.log("fetched IC", state.currentIC.name)
|
||||
})
|
||||
.addCase(addIC.rejected, (state, action) => {
|
||||
NotificationsDataManager.addNotification(NotificationsFactory.ADD_ERROR("Error while adding infrastructural component: " + action.error.message));
|
||||
})
|
||||
.addCase(sendActionToIC.rejected, (state, action) => {
|
||||
NotificationsDataManager.addNotification(NotificationsFactory.ADD_ERROR("Error while sending action to infrastructural component: " + action.error.message));
|
||||
})
|
||||
.addCase(editIC.rejected, (state, action) => {
|
||||
NotificationsDataManager.addNotification(NotificationsFactory.ADD_ERROR("Error while trying to update an infrastructural component: " + action.error.message));
|
||||
})
|
||||
.addCase(deleteIC.rejected, (state, action) => {
|
||||
NotificationsDataManager.addNotification(NotificationsFactory.ADD_ERROR("Error while trying to delete an infrastructural component: " + action.error.message));
|
||||
})
|
||||
//TODO
|
||||
// .addCase(restartIC.fullfilled, (state, action) => {
|
||||
// console.log("restart fullfilled")
|
||||
// //loadAllICs({token: sessionToken})
|
||||
// })
|
||||
// .addCase(shutdownIC.fullfilled, (state, action) => {
|
||||
// console.log("shutdown fullfilled")
|
||||
// //loadAllICs({token: sessionToken})
|
||||
// })
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -93,6 +148,85 @@ export const loadICbyId = createAsyncThunk(
|
|||
}
|
||||
)
|
||||
|
||||
//adds a new Infrastructural component. Data object must contain token and ic fields
|
||||
export const addIC = createAsyncThunk(
|
||||
'infrastructure/addIC',
|
||||
async (data, {rejectWithValue}) => {
|
||||
try {
|
||||
//post request body: ic object that is to be added
|
||||
const ic = {ic: data.ic};
|
||||
const res = await RestAPI.post('/api/v2/ic/', ic, data.token);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.log("Error adding IC: ", error);
|
||||
return rejectWithValue(error.response.data);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
//sends an action to IC. Data object must contain a token, IC's id and actions string
|
||||
export const sendActionToIC = createAsyncThunk(
|
||||
'infrastructure/sendActionToIC',
|
||||
async (data, {rejectWithValue}) => {
|
||||
try {
|
||||
const token = data.token;
|
||||
const id = data.id;
|
||||
let actions = data.actions;
|
||||
|
||||
console.log("actions: ", actions)
|
||||
|
||||
if (!Array.isArray(actions))
|
||||
actions = [ actions ]
|
||||
|
||||
for (let action of actions) {
|
||||
if (action.when) {
|
||||
// Send timestamp as Unix Timestamp
|
||||
action.when = Math.round(new Date(action.when).getTime() / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
const res = await RestAPI.post('/api/v2/ic/'+id+'/action', actions, token);
|
||||
NotificationsDataManager.addNotification(NotificationsFactory.ACTION_INFO());
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.log("Error sending an action to IC: ", error);
|
||||
return rejectWithValue(error.response.data);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
//send a request to update IC's data. Data object must contain token, and updated ic object
|
||||
export const editIC = createAsyncThunk(
|
||||
'infrastructure/editIC',
|
||||
async (data, {rejectWithValue}) => {
|
||||
try {
|
||||
//post request body: ic object that is to be added
|
||||
const {token, ic} = data;
|
||||
const res = await RestAPI.put('/api/v2/ic/'+ic.id, {ic: ic}, token);
|
||||
return res;
|
||||
} catch (error) {
|
||||
return rejectWithValue(error.response.data);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
//send a request to delete IC. Data object must contain token, and id of the IC that is to be deleted
|
||||
export const deleteIC = createAsyncThunk(
|
||||
'infrastructure/deleteIC',
|
||||
async (data, {rejectWithValue}) => {
|
||||
try {
|
||||
//post request body: ic object that is to be added
|
||||
const {token, id} = data;
|
||||
const res = await RestAPI.delete('/api/v2/ic/'+id, token);
|
||||
return res;
|
||||
} catch (error) {
|
||||
console.log("Error updating IC: ", error);
|
||||
return rejectWithValue(error.response.data);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
//TODO
|
||||
|
||||
//restarts ICs
|
||||
|
@ -110,7 +244,8 @@ export const restartIC = createAsyncThunk(
|
|||
}
|
||||
)
|
||||
|
||||
//restarts ICs
|
||||
|
||||
//shut ICs down
|
||||
export const shutdownIC = createAsyncThunk(
|
||||
'infrastructure/shutdownIC',
|
||||
async (data) => {
|
||||
|
@ -125,6 +260,8 @@ export const shutdownIC = createAsyncThunk(
|
|||
}
|
||||
)
|
||||
|
||||
export const {checkICsByCategory} = icSlice.actions;
|
||||
|
||||
export default icSlice.reducer;
|
||||
export const {updateCheckedICs, clearCheckedICs, openEditModal, openDeleteModal, closeDeleteModal, closeEditModal} = icSlice.actions;
|
||||
|
||||
export default icSlice.reducer;
|
||||
|
||||
|
|
|
@ -16,16 +16,19 @@
|
|||
******************************************************************************/
|
||||
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
|
||||
import userReducer from './userSlice';
|
||||
import icReducer from './icSlice';
|
||||
import configReducer from './configSlice'
|
||||
import { apiSlice } from "./apiSlice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
user: userReducer,
|
||||
infrastructure: icReducer,
|
||||
config: configReducer
|
||||
config: configReducer,
|
||||
[apiSlice.reducerPath]: apiSlice.reducer,
|
||||
},
|
||||
devTools: true
|
||||
})
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware().concat(apiSlice.middleware),
|
||||
devTools: true,
|
||||
})
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
******************************************************************************/
|
||||
|
||||
import {createSlice, createAsyncThunk} from '@reduxjs/toolkit'
|
||||
|
||||
import RestAPI from '../common/api/rest-api';
|
||||
import ICDataDataManager from '../ic/ic-data-data-manager';
|
||||
|
||||
const userSlice = createSlice({
|
||||
name: 'user',
|
||||
|
@ -91,12 +89,8 @@ export const loginExternal = createAsyncThunk(
|
|||
export const logout = createAsyncThunk(
|
||||
'user/logout',
|
||||
async () => {
|
||||
// disconnect from all infrastructure components
|
||||
ICDataDataManager.closeAll();
|
||||
//remove token and current user from local storage
|
||||
localStorage.clear();
|
||||
|
||||
console.log("logged out")
|
||||
}
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue